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