test_asdl_parser.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. """Tests for the asdl parser in Parser/asdl.py"""
  2. import importlib.machinery
  3. import importlib.util
  4. import os
  5. from os.path import dirname
  6. import sys
  7. import sysconfig
  8. import unittest
  9. # This test is only relevant for from-source builds of Python.
  10. if not sysconfig.is_python_build():
  11. raise unittest.SkipTest('test irrelevant for an installed Python')
  12. src_base = dirname(dirname(dirname(__file__)))
  13. parser_dir = os.path.join(src_base, 'Parser')
  14. class TestAsdlParser(unittest.TestCase):
  15. @classmethod
  16. def setUpClass(cls):
  17. # Loads the asdl module dynamically, since it's not in a real importable
  18. # package.
  19. # Parses Python.asdl into an ast.Module and run the check on it.
  20. # There's no need to do this for each test method, hence setUpClass.
  21. sys.path.insert(0, parser_dir)
  22. loader = importlib.machinery.SourceFileLoader(
  23. 'asdl', os.path.join(parser_dir, 'asdl.py'))
  24. spec = importlib.util.spec_from_loader('asdl', loader)
  25. module = importlib.util.module_from_spec(spec)
  26. loader.exec_module(module)
  27. cls.asdl = module
  28. cls.mod = cls.asdl.parse(os.path.join(parser_dir, 'Python.asdl'))
  29. cls.assertTrue(cls.asdl.check(cls.mod), 'Module validation failed')
  30. @classmethod
  31. def tearDownClass(cls):
  32. del sys.path[0]
  33. def setUp(self):
  34. # alias stuff from the class, for convenience
  35. self.asdl = TestAsdlParser.asdl
  36. self.mod = TestAsdlParser.mod
  37. self.types = self.mod.types
  38. def test_module(self):
  39. self.assertEqual(self.mod.name, 'Python')
  40. self.assertIn('stmt', self.types)
  41. self.assertIn('expr', self.types)
  42. self.assertIn('mod', self.types)
  43. def test_definitions(self):
  44. defs = self.mod.dfns
  45. self.assertIsInstance(defs[0], self.asdl.Type)
  46. self.assertIsInstance(defs[0].value, self.asdl.Sum)
  47. self.assertIsInstance(self.types['withitem'], self.asdl.Product)
  48. self.assertIsInstance(self.types['alias'], self.asdl.Product)
  49. def test_product(self):
  50. alias = self.types['alias']
  51. self.assertEqual(
  52. str(alias),
  53. 'Product([Field(identifier, name), Field(identifier, asname, opt=True)], '
  54. '[Field(int, lineno), Field(int, col_offset), '
  55. 'Field(int, end_lineno, opt=True), Field(int, end_col_offset, opt=True)])')
  56. def test_attributes(self):
  57. stmt = self.types['stmt']
  58. self.assertEqual(len(stmt.attributes), 4)
  59. self.assertEqual(repr(stmt.attributes[0]), 'Field(int, lineno)')
  60. self.assertEqual(repr(stmt.attributes[1]), 'Field(int, col_offset)')
  61. self.assertEqual(repr(stmt.attributes[2]), 'Field(int, end_lineno, opt=True)')
  62. self.assertEqual(repr(stmt.attributes[3]), 'Field(int, end_col_offset, opt=True)')
  63. def test_constructor_fields(self):
  64. ehandler = self.types['excepthandler']
  65. self.assertEqual(len(ehandler.types), 1)
  66. self.assertEqual(len(ehandler.attributes), 4)
  67. cons = ehandler.types[0]
  68. self.assertIsInstance(cons, self.asdl.Constructor)
  69. self.assertEqual(len(cons.fields), 3)
  70. f0 = cons.fields[0]
  71. self.assertEqual(f0.type, 'expr')
  72. self.assertEqual(f0.name, 'type')
  73. self.assertTrue(f0.opt)
  74. f1 = cons.fields[1]
  75. self.assertEqual(f1.type, 'identifier')
  76. self.assertEqual(f1.name, 'name')
  77. self.assertTrue(f1.opt)
  78. f2 = cons.fields[2]
  79. self.assertEqual(f2.type, 'stmt')
  80. self.assertEqual(f2.name, 'body')
  81. self.assertFalse(f2.opt)
  82. self.assertTrue(f2.seq)
  83. def test_visitor(self):
  84. class CustomVisitor(self.asdl.VisitorBase):
  85. def __init__(self):
  86. super().__init__()
  87. self.names_with_seq = []
  88. def visitModule(self, mod):
  89. for dfn in mod.dfns:
  90. self.visit(dfn)
  91. def visitType(self, type):
  92. self.visit(type.value)
  93. def visitSum(self, sum):
  94. for t in sum.types:
  95. self.visit(t)
  96. def visitConstructor(self, cons):
  97. for f in cons.fields:
  98. if f.seq:
  99. self.names_with_seq.append(cons.name)
  100. v = CustomVisitor()
  101. v.visit(self.types['mod'])
  102. self.assertEqual(v.names_with_seq,
  103. ['Module', 'Module', 'Interactive', 'FunctionType'])
  104. if __name__ == '__main__':
  105. unittest.main()