Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions pyflakes/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,8 @@ class Checker:
def __init__(self, tree, filename='(none)', builtins=None,
withDoctest='PYFLAKES_DOCTEST' in os.environ):
self._nodeHandlers = {}
self._parents = {}
self._node_depths = {}
self._deferred = collections.deque()
self.deadScopes = []
self.messages = []
Expand Down Expand Up @@ -888,29 +890,26 @@ def report(self, messageClass, *args, **kwargs):
def getParent(self, node):
# Lookup the first parent which is not Tuple, List or Starred
while True:
node = node._pyflakes_parent
node = self._parents[node]
if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
return node

def getCommonAncestor(self, lnode, rnode, stop):
if (
stop in (lnode, rnode) or
not (
hasattr(lnode, '_pyflakes_parent') and
hasattr(rnode, '_pyflakes_parent')
)
not (lnode in self._parents and rnode in self._parents)
):
return None
if lnode is rnode:
return lnode

if (lnode._pyflakes_depth > rnode._pyflakes_depth):
return self.getCommonAncestor(lnode._pyflakes_parent, rnode, stop)
if (lnode._pyflakes_depth < rnode._pyflakes_depth):
return self.getCommonAncestor(lnode, rnode._pyflakes_parent, stop)
if self._node_depths[lnode] > self._node_depths[rnode]:
return self.getCommonAncestor(self._parents[lnode], rnode, stop)
if self._node_depths[lnode] < self._node_depths[rnode]:
return self.getCommonAncestor(lnode, self._parents[rnode], stop)
return self.getCommonAncestor(
lnode._pyflakes_parent,
rnode._pyflakes_parent,
self._parents[lnode],
self._parents[rnode],
stop,
)

Expand Down Expand Up @@ -938,7 +937,7 @@ def addBinding(self, node, value):
- `node` is the statement responsible for the change
- `value` is the new value, a Binding instance
"""
# assert value.source in (node, node._pyflakes_parent):
# assert value.source in (node, self._parents[node]):
for scope in reversed(self.scopeStack):
if value.name in scope:
break
Expand Down Expand Up @@ -1137,18 +1136,18 @@ def handleNodeStore(self, node):
if isinstance(parent_stmt, ast.AnnAssign) and parent_stmt.value is None:
binding = Annotation(name, node)
elif isinstance(parent_stmt, (FOR_TYPES, ast.comprehension)) or (
parent_stmt != node._pyflakes_parent and
parent_stmt != self._parents[node] and
not self.isLiteralTupleUnpacking(parent_stmt)):
binding = Binding(name, node)
elif (
name == '__all__' and
isinstance(self.scope, ModuleScope) and
isinstance(
node._pyflakes_parent,
self._parents[node],
(ast.Assign, ast.AugAssign, ast.AnnAssign)
)
):
binding = ExportBinding(name, node._pyflakes_parent, self.scope)
binding = ExportBinding(name, self._parents[node], self.scope)
elif isinstance(parent_stmt, ast.NamedExpr):
binding = NamedExprAssignment(name, node)
else:
Expand All @@ -1161,11 +1160,11 @@ def on_conditional_branch():
"""
Return `True` if node is part of a conditional body.
"""
current = getattr(node, '_pyflakes_parent', None)
current = self._parents.get(node)
while current:
if isinstance(current, (ast.If, ast.While, ast.IfExp)):
return True
current = getattr(current, '_pyflakes_parent', None)
current = self._parents.get(current)
return False

if on_conditional_branch():
Expand Down Expand Up @@ -1245,8 +1244,8 @@ def handleNode(self, node, parent):
):
self.futuresAllowed = False
self.nodeDepth += 1
node._pyflakes_depth = self.nodeDepth
node._pyflakes_parent = parent
self._node_depths[node] = self.nodeDepth
self._parents[node] = parent
try:
handler = self.getNodeHandler(node.__class__)
handler(node)
Expand Down Expand Up @@ -1915,7 +1914,7 @@ def NAME(self, node):
if isinstance(node.ctx, ast.Load):
self.handleNodeLoad(node, self.getParent(node))
if (node.id == 'locals' and isinstance(self.scope, FunctionScope) and
isinstance(node._pyflakes_parent, ast.Call)):
isinstance(self._parents[node], ast.Call)):
# we are doing locals() call in current scope
self.scope.usesLocals = True
elif isinstance(node.ctx, ast.Store):
Expand All @@ -1931,8 +1930,8 @@ def CONTINUE(self, node):
# definition (not OK), for 'continue', a finally block (not OK), or
# the top module scope (not OK)
n = node
while hasattr(n, '_pyflakes_parent'):
n, n_child = n._pyflakes_parent, n
while n in self._parents:
n, n_child = self._parents[n], n
if isinstance(n, (ast.While, ast.For, ast.AsyncFor)):
# Doesn't apply unless it's in the loop itself
if n_child not in n.orelse:
Expand Down
Loading