mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00

WarningsRecorder object. This makes the API simpler to use as no special object must be learned. Closes issue 3781. Review by Benjamin Peterson.
200 lines
6.8 KiB
Python
200 lines
6.8 KiB
Python
"""
|
|
Test the API of the symtable module.
|
|
"""
|
|
import symtable
|
|
import unittest
|
|
import warnings
|
|
|
|
from test import test_support
|
|
|
|
|
|
TEST_CODE = """
|
|
import sys
|
|
|
|
glob = 42
|
|
|
|
class Mine:
|
|
instance_var = 24
|
|
def a_method(p1, p2):
|
|
pass
|
|
|
|
def spam(a, b, *var, **kw):
|
|
global bar
|
|
bar = 47
|
|
x = 23
|
|
glob
|
|
def internal():
|
|
return x
|
|
return internal
|
|
|
|
def foo():
|
|
exec 'm'
|
|
from sys import *
|
|
|
|
def namespace_test(): pass
|
|
def namespace_test(): pass
|
|
"""
|
|
|
|
|
|
def find_block(block, name):
|
|
for ch in block.get_children():
|
|
if ch.get_name() == name:
|
|
return ch
|
|
|
|
|
|
class SymtableTest(unittest.TestCase):
|
|
|
|
with warnings.catch_warnings():
|
|
# Ignore warnings about "from blank import *"
|
|
warnings.simplefilter("ignore", SyntaxWarning)
|
|
top = symtable.symtable(TEST_CODE, "?", "exec")
|
|
# These correspond to scopes in TEST_CODE
|
|
Mine = find_block(top, "Mine")
|
|
a_method = find_block(Mine, "a_method")
|
|
spam = find_block(top, "spam")
|
|
internal = find_block(spam, "internal")
|
|
foo = find_block(top, "foo")
|
|
|
|
def test_noops(self):
|
|
# Check methods that don't work. They should warn and return False.
|
|
def check(w, msg):
|
|
self.assertEqual(str(w.message), msg)
|
|
sym = self.top.lookup("glob")
|
|
with warnings.catch_warnings(record=True) as w:
|
|
warnings.simplefilter("always", DeprecationWarning)
|
|
self.assertFalse(sym.is_vararg())
|
|
check(w[-1].message, "is_vararg() is obsolete and will be removed")
|
|
self.assertFalse(sym.is_keywordarg())
|
|
check(w[-1].message,
|
|
"is_keywordarg() is obsolete and will be removed")
|
|
self.assertFalse(sym.is_in_tuple())
|
|
check(w[-1].message,
|
|
"is_in_tuple() is obsolete and will be removed")
|
|
|
|
def test_type(self):
|
|
self.assertEqual(self.top.get_type(), "module")
|
|
self.assertEqual(self.Mine.get_type(), "class")
|
|
self.assertEqual(self.a_method.get_type(), "function")
|
|
self.assertEqual(self.spam.get_type(), "function")
|
|
self.assertEqual(self.internal.get_type(), "function")
|
|
|
|
def test_optimized(self):
|
|
self.assertFalse(self.top.is_optimized())
|
|
self.assertFalse(self.top.has_exec())
|
|
self.assertFalse(self.top.has_import_star())
|
|
|
|
self.assertTrue(self.spam.is_optimized())
|
|
|
|
self.assertFalse(self.foo.is_optimized())
|
|
self.assertTrue(self.foo.has_exec())
|
|
self.assertTrue(self.foo.has_import_star())
|
|
|
|
def test_nested(self):
|
|
self.assertFalse(self.top.is_nested())
|
|
self.assertFalse(self.Mine.is_nested())
|
|
self.assertFalse(self.spam.is_nested())
|
|
self.assertTrue(self.internal.is_nested())
|
|
|
|
def test_children(self):
|
|
self.assertTrue(self.top.has_children())
|
|
self.assertTrue(self.Mine.has_children())
|
|
self.assertFalse(self.foo.has_children())
|
|
|
|
def test_lineno(self):
|
|
self.assertEqual(self.top.get_lineno(), 0)
|
|
self.assertEqual(self.spam.get_lineno(), 11)
|
|
|
|
def test_function_info(self):
|
|
func = self.spam
|
|
self.assertEqual(func.get_parameters(), ("a", "b", "kw", "var"))
|
|
self.assertEqual(func.get_locals(),
|
|
("a", "b", "bar", "internal", "kw", "var", "x"))
|
|
self.assertEqual(func.get_globals(), ("bar", "glob"))
|
|
self.assertEqual(self.internal.get_frees(), ("x",))
|
|
|
|
def test_globals(self):
|
|
self.assertTrue(self.spam.lookup("glob").is_global())
|
|
self.assertTrue(self.spam.lookup("bar").is_global())
|
|
self.assertFalse(self.internal.lookup("x").is_global())
|
|
self.assertFalse(self.Mine.lookup("instance_var").is_global())
|
|
|
|
def test_local(self):
|
|
self.assertTrue(self.spam.lookup("x").is_local())
|
|
self.assertFalse(self.internal.lookup("x").is_local())
|
|
|
|
def test_referenced(self):
|
|
self.assertTrue(self.internal.lookup("x").is_referenced())
|
|
self.assertTrue(self.spam.lookup("internal").is_referenced())
|
|
self.assertFalse(self.spam.lookup("x").is_referenced())
|
|
|
|
def test_parameters(self):
|
|
for sym in ("a", "var", "kw"):
|
|
self.assertTrue(self.spam.lookup(sym).is_parameter())
|
|
self.assertFalse(self.spam.lookup("x").is_parameter())
|
|
|
|
def test_symbol_lookup(self):
|
|
self.assertEqual(len(self.top.get_identifiers()),
|
|
len(self.top.get_symbols()))
|
|
|
|
self.assertRaises(KeyError, self.top.lookup, "not_here")
|
|
|
|
def test_namespaces(self):
|
|
self.assertTrue(self.top.lookup("Mine").is_namespace())
|
|
self.assertTrue(self.Mine.lookup("a_method").is_namespace())
|
|
self.assertTrue(self.top.lookup("spam").is_namespace())
|
|
self.assertTrue(self.spam.lookup("internal").is_namespace())
|
|
self.assertTrue(self.top.lookup("namespace_test").is_namespace())
|
|
self.assertFalse(self.spam.lookup("x").is_namespace())
|
|
|
|
self.assert_(self.top.lookup("spam").get_namespace() is self.spam)
|
|
ns_test = self.top.lookup("namespace_test")
|
|
self.assertEqual(len(ns_test.get_namespaces()), 2)
|
|
self.assertRaises(ValueError, ns_test.get_namespace)
|
|
|
|
def test_assigned(self):
|
|
self.assertTrue(self.spam.lookup("x").is_assigned())
|
|
self.assertTrue(self.spam.lookup("bar").is_assigned())
|
|
self.assertTrue(self.top.lookup("spam").is_assigned())
|
|
self.assertTrue(self.Mine.lookup("a_method").is_assigned())
|
|
self.assertFalse(self.internal.lookup("x").is_assigned())
|
|
|
|
def test_imported(self):
|
|
self.assertTrue(self.top.lookup("sys").is_imported())
|
|
|
|
def test_name(self):
|
|
self.assertEqual(self.top.get_name(), "top")
|
|
self.assertEqual(self.spam.get_name(), "spam")
|
|
self.assertEqual(self.spam.lookup("x").get_name(), "x")
|
|
self.assertEqual(self.Mine.get_name(), "Mine")
|
|
|
|
def test_class_info(self):
|
|
self.assertEqual(self.Mine.get_methods(), ('a_method',))
|
|
|
|
def test_filename_correct(self):
|
|
### Bug tickler: SyntaxError file name correct whether error raised
|
|
### while parsing or building symbol table.
|
|
def checkfilename(brokencode):
|
|
try:
|
|
symtable.symtable(brokencode, "spam", "exec")
|
|
except SyntaxError as e:
|
|
self.assertEqual(e.filename, "spam")
|
|
else:
|
|
self.fail("no SyntaxError for %r" % (brokencode,))
|
|
checkfilename("def f(x): foo)(") # parse-time
|
|
checkfilename("def f(x): global x") # symtable-build-time
|
|
|
|
def test_eval(self):
|
|
symbols = symtable.symtable("42", "?", "eval")
|
|
|
|
def test_single(self):
|
|
symbols = symtable.symtable("42", "?", "single")
|
|
|
|
def test_exec(self):
|
|
symbols = symtable.symtable("def f(x): return x", "?", "exec")
|
|
|
|
|
|
def test_main():
|
|
test_support.run_unittest(SymtableTest)
|
|
|
|
if __name__ == '__main__':
|
|
test_main()
|