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