Skip to content
Snippets Groups Projects
Commit 483a478b authored by Mike Bayer's avatar Mike Bayer
Browse files

further fix to previous ast enhancement; dont log identifiers as "declared"...

further fix to previous ast enhancement; dont log identifiers as "declared" once we're traversing inside functions since they are local to the function.
parent 47afe17a
No related branches found
No related tags found
No related merge requests found
......@@ -40,54 +40,63 @@ class PythonCode(object):
else:
expr = code
local_ident_stack = {}
class FindIdentifiers(object):
def visitAssName(s, node, *args):
# if node.name not in self.undeclared_identifiers:
self.declared_identifiers.add(node.name)
def visitAssign(s, node, *args):
def __init__(self):
self.in_function = False
self.local_ident_stack = {}
def _add_declared(s, name):
if not s.in_function:
self.declared_identifiers.add(name)
def visitAssName(self, node, *args):
self._add_declared(node.name)
def visitAssign(self, node, *args):
# flip around the visiting of Assign so the expression gets evaluated first,
# in the case of a clause like "x=x+5" (x is undeclared)
s.visit(node.expr, *args)
self.visit(node.expr, *args)
for n in node.nodes:
s.visit(n, *args)
def visitFunction(s,node, *args):
# just need the function name. the contents of it are local to the function, dont parse those.
# TODO: parse the default values in the functions keyword arguments.
self.declared_identifiers.add(node.name)
self.visit(n, *args)
def visitFunction(self,node, *args):
self._add_declared(node.name)
# push function state onto stack. dont log any
# more identifiers as "declared" until outside of the function,
# but keep logging identifiers as "undeclared".
# track argument names in each function header so they arent counted as "undeclared"
saved = {}
inf = self.in_function
self.in_function = True
for arg in node.argnames:
if arg in local_ident_stack:
if arg in self.local_ident_stack:
saved[arg] = True
else:
local_ident_stack[arg] = True
self.local_ident_stack[arg] = True
for n in node.getChildNodes():
s.visit(n, *args)
self.visit(n, *args)
self.in_function = inf
for arg in node.argnames:
if arg not in saved:
del local_ident_stack[arg]
def visitFor(s, node, *args):
del self.local_ident_stack[arg]
def visitFor(self, node, *args):
# flip around visit
s.visit(node.list, *args)
s.visit(node.assign, *args)
s.visit(node.body, *args)
self.visit(node.list, *args)
self.visit(node.assign, *args)
self.visit(node.body, *args)
def visitName(s, node, *args):
if node.name not in __builtins__ and node.name not in self.declared_identifiers and node.name not in local_ident_stack:
if node.name not in __builtins__ and node.name not in self.declared_identifiers and node.name not in s.local_ident_stack:
self.undeclared_identifiers.add(node.name)
def visitImport(s, node, *args):
def visitImport(self, node, *args):
for (mod, alias) in node.names:
if alias is not None:
self.declared_identifiers.add(alias)
self._add_declared(alias)
else:
self.declared_identifiers.add(mod)
def visitFrom(s, node, *args):
self._add_declared(mod)
def visitFrom(self, node, *args):
for (mod, alias) in node.names:
if alias is not None:
self.declared_identifiers.add(alias)
self._add_declared(alias)
else:
if mod == '*':
raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared. Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", lineno, pos, filename)
self.declared_identifiers.add(mod)
self._add_declared(mod)
f = FindIdentifiers()
visitor.walk(expr, f) #, walker=walker())
......
......@@ -94,7 +94,18 @@ print x
parsed = ast.PythonCode(code, 0, 0, None)
assert parsed.undeclared_identifiers == util.Set(['z', 'x'])
assert parsed.declared_identifiers == util.Set(['lala'])
code = """
def lala(x, y):
def hoho():
def bar():
z = 7
print z
"""
parsed = ast.PythonCode(code, 0, 0, None)
assert parsed.undeclared_identifiers == util.Set(['z'])
assert parsed.declared_identifiers == util.Set(['lala'])
def test_no_global_imports(self):
code = """
from foo import *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment