Home | History | Annotate | Download | only in test
      1 """
      2 Test the API of the symtable module.
      3 """
      4 import symtable
      5 import unittest
      6 
      7 
      8 
      9 TEST_CODE = """
     10 import sys
     11 
     12 glob = 42
     13 
     14 class Mine:
     15     instance_var = 24
     16     def a_method(p1, p2):
     17         pass
     18 
     19 def 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 
     28 def foo():
     29     pass
     30 
     31 def namespace_test(): pass
     32 def namespace_test(): pass
     33 """
     34 
     35 
     36 def find_block(block, name):
     37     for ch in block.get_children():
     38         if ch.get_name() == name:
     39             return ch
     40 
     41 
     42 class 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 
    192 if __name__ == '__main__':
    193     unittest.main()
    194