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