1 | """
|
---|
2 | Test the API of the symtable module.
|
---|
3 | """
|
---|
4 | import symtable
|
---|
5 | import unittest
|
---|
6 |
|
---|
7 | from test import test_support
|
---|
8 |
|
---|
9 |
|
---|
10 | TEST_CODE = """
|
---|
11 | import sys
|
---|
12 |
|
---|
13 | glob = 42
|
---|
14 |
|
---|
15 | class Mine:
|
---|
16 | instance_var = 24
|
---|
17 | def a_method(p1, p2):
|
---|
18 | pass
|
---|
19 |
|
---|
20 | def spam(a, b, *var, **kw):
|
---|
21 | global bar
|
---|
22 | bar = 47
|
---|
23 | x = 23
|
---|
24 | glob
|
---|
25 | def internal():
|
---|
26 | return x
|
---|
27 | return internal
|
---|
28 |
|
---|
29 | def foo():
|
---|
30 | exec 'm'
|
---|
31 | from sys import *
|
---|
32 |
|
---|
33 | def namespace_test(): pass
|
---|
34 | def namespace_test(): pass
|
---|
35 | """
|
---|
36 |
|
---|
37 |
|
---|
38 | def find_block(block, name):
|
---|
39 | for ch in block.get_children():
|
---|
40 | if ch.get_name() == name:
|
---|
41 | return ch
|
---|
42 |
|
---|
43 |
|
---|
44 | class SymtableTest(unittest.TestCase):
|
---|
45 |
|
---|
46 | with test_support.check_warnings(
|
---|
47 | ("import \* only allowed at module level", SyntaxWarning)):
|
---|
48 | top = symtable.symtable(TEST_CODE, "?", "exec")
|
---|
49 | # These correspond to scopes in TEST_CODE
|
---|
50 | Mine = find_block(top, "Mine")
|
---|
51 | a_method = find_block(Mine, "a_method")
|
---|
52 | spam = find_block(top, "spam")
|
---|
53 | internal = find_block(spam, "internal")
|
---|
54 | foo = find_block(top, "foo")
|
---|
55 |
|
---|
56 | def test_type(self):
|
---|
57 | self.assertEqual(self.top.get_type(), "module")
|
---|
58 | self.assertEqual(self.Mine.get_type(), "class")
|
---|
59 | self.assertEqual(self.a_method.get_type(), "function")
|
---|
60 | self.assertEqual(self.spam.get_type(), "function")
|
---|
61 | self.assertEqual(self.internal.get_type(), "function")
|
---|
62 |
|
---|
63 | def test_optimized(self):
|
---|
64 | self.assertFalse(self.top.is_optimized())
|
---|
65 | self.assertFalse(self.top.has_exec())
|
---|
66 | self.assertFalse(self.top.has_import_star())
|
---|
67 |
|
---|
68 | self.assertTrue(self.spam.is_optimized())
|
---|
69 |
|
---|
70 | self.assertFalse(self.foo.is_optimized())
|
---|
71 | self.assertTrue(self.foo.has_exec())
|
---|
72 | self.assertTrue(self.foo.has_import_star())
|
---|
73 |
|
---|
74 | def test_nested(self):
|
---|
75 | self.assertFalse(self.top.is_nested())
|
---|
76 | self.assertFalse(self.Mine.is_nested())
|
---|
77 | self.assertFalse(self.spam.is_nested())
|
---|
78 | self.assertTrue(self.internal.is_nested())
|
---|
79 |
|
---|
80 | def test_children(self):
|
---|
81 | self.assertTrue(self.top.has_children())
|
---|
82 | self.assertTrue(self.Mine.has_children())
|
---|
83 | self.assertFalse(self.foo.has_children())
|
---|
84 |
|
---|
85 | def test_lineno(self):
|
---|
86 | self.assertEqual(self.top.get_lineno(), 0)
|
---|
87 | self.assertEqual(self.spam.get_lineno(), 11)
|
---|
88 |
|
---|
89 | def test_function_info(self):
|
---|
90 | func = self.spam
|
---|
91 | self.assertEqual(sorted(func.get_parameters()), ["a", "b", "kw", "var"])
|
---|
92 | expected = ["a", "b", "internal", "kw", "var", "x"]
|
---|
93 | self.assertEqual(sorted(func.get_locals()), expected)
|
---|
94 | self.assertEqual(sorted(func.get_globals()), ["bar", "glob"])
|
---|
95 | self.assertEqual(self.internal.get_frees(), ("x",))
|
---|
96 |
|
---|
97 | def test_globals(self):
|
---|
98 | self.assertTrue(self.spam.lookup("glob").is_global())
|
---|
99 | self.assertFalse(self.spam.lookup("glob").is_declared_global())
|
---|
100 | self.assertTrue(self.spam.lookup("bar").is_global())
|
---|
101 | self.assertTrue(self.spam.lookup("bar").is_declared_global())
|
---|
102 | self.assertFalse(self.internal.lookup("x").is_global())
|
---|
103 | self.assertFalse(self.Mine.lookup("instance_var").is_global())
|
---|
104 |
|
---|
105 | def test_local(self):
|
---|
106 | self.assertTrue(self.spam.lookup("x").is_local())
|
---|
107 | self.assertFalse(self.internal.lookup("x").is_local())
|
---|
108 |
|
---|
109 | def test_referenced(self):
|
---|
110 | self.assertTrue(self.internal.lookup("x").is_referenced())
|
---|
111 | self.assertTrue(self.spam.lookup("internal").is_referenced())
|
---|
112 | self.assertFalse(self.spam.lookup("x").is_referenced())
|
---|
113 |
|
---|
114 | def test_parameters(self):
|
---|
115 | for sym in ("a", "var", "kw"):
|
---|
116 | self.assertTrue(self.spam.lookup(sym).is_parameter())
|
---|
117 | self.assertFalse(self.spam.lookup("x").is_parameter())
|
---|
118 |
|
---|
119 | def test_symbol_lookup(self):
|
---|
120 | self.assertEqual(len(self.top.get_identifiers()),
|
---|
121 | len(self.top.get_symbols()))
|
---|
122 |
|
---|
123 | self.assertRaises(KeyError, self.top.lookup, "not_here")
|
---|
124 |
|
---|
125 | def test_namespaces(self):
|
---|
126 | self.assertTrue(self.top.lookup("Mine").is_namespace())
|
---|
127 | self.assertTrue(self.Mine.lookup("a_method").is_namespace())
|
---|
128 | self.assertTrue(self.top.lookup("spam").is_namespace())
|
---|
129 | self.assertTrue(self.spam.lookup("internal").is_namespace())
|
---|
130 | self.assertTrue(self.top.lookup("namespace_test").is_namespace())
|
---|
131 | self.assertFalse(self.spam.lookup("x").is_namespace())
|
---|
132 |
|
---|
133 | self.assertTrue(self.top.lookup("spam").get_namespace() is self.spam)
|
---|
134 | ns_test = self.top.lookup("namespace_test")
|
---|
135 | self.assertEqual(len(ns_test.get_namespaces()), 2)
|
---|
136 | self.assertRaises(ValueError, ns_test.get_namespace)
|
---|
137 |
|
---|
138 | def test_assigned(self):
|
---|
139 | self.assertTrue(self.spam.lookup("x").is_assigned())
|
---|
140 | self.assertTrue(self.spam.lookup("bar").is_assigned())
|
---|
141 | self.assertTrue(self.top.lookup("spam").is_assigned())
|
---|
142 | self.assertTrue(self.Mine.lookup("a_method").is_assigned())
|
---|
143 | self.assertFalse(self.internal.lookup("x").is_assigned())
|
---|
144 |
|
---|
145 | def test_imported(self):
|
---|
146 | self.assertTrue(self.top.lookup("sys").is_imported())
|
---|
147 |
|
---|
148 | def test_name(self):
|
---|
149 | self.assertEqual(self.top.get_name(), "top")
|
---|
150 | self.assertEqual(self.spam.get_name(), "spam")
|
---|
151 | self.assertEqual(self.spam.lookup("x").get_name(), "x")
|
---|
152 | self.assertEqual(self.Mine.get_name(), "Mine")
|
---|
153 |
|
---|
154 | def test_class_info(self):
|
---|
155 | self.assertEqual(self.Mine.get_methods(), ('a_method',))
|
---|
156 |
|
---|
157 | def test_filename_correct(self):
|
---|
158 | ### Bug tickler: SyntaxError file name correct whether error raised
|
---|
159 | ### while parsing or building symbol table.
|
---|
160 | def checkfilename(brokencode):
|
---|
161 | try:
|
---|
162 | symtable.symtable(brokencode, "spam", "exec")
|
---|
163 | except SyntaxError as e:
|
---|
164 | self.assertEqual(e.filename, "spam")
|
---|
165 | else:
|
---|
166 | self.fail("no SyntaxError for %r" % (brokencode,))
|
---|
167 | checkfilename("def f(x): foo)(") # parse-time
|
---|
168 | checkfilename("def f(x): global x") # symtable-build-time
|
---|
169 |
|
---|
170 | def test_eval(self):
|
---|
171 | symbols = symtable.symtable("42", "?", "eval")
|
---|
172 |
|
---|
173 | def test_single(self):
|
---|
174 | symbols = symtable.symtable("42", "?", "single")
|
---|
175 |
|
---|
176 | def test_exec(self):
|
---|
177 | symbols = symtable.symtable("def f(x): return x", "?", "exec")
|
---|
178 |
|
---|
179 |
|
---|
180 | def test_main():
|
---|
181 | test_support.run_unittest(SymtableTest)
|
---|
182 |
|
---|
183 | if __name__ == '__main__':
|
---|
184 | test_main()
|
---|