Skip to content

Commit 98c171a

Browse files
committed
Reimplement the lookup() call by manually looking for the right nodes
On Python 3 we can't see the assignment statement of a deleted node, such as an assignment from a loop or from the except handler. Instead of relying on lookup() itself, look through the current scope manually for the right objects.
1 parent 8145096 commit 98c171a

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

pylint/checkers/python3.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -625,27 +625,42 @@ def visit_arguments(self, node):
625625

626626
def visit_name(self, node):
627627
"""Detect when a "bad" built-in is referenced."""
628-
found_node, located_statements = node.lookup(node.name)
628+
found_node, _ = node.lookup(node.name)
629629
if _is_builtin(found_node):
630630
if node.name in self._bad_builtins:
631631
message = node.name.lower() + '-builtin'
632632
self.add_message(message, node=node)
633633

634-
if len(located_statements) == 1:
635-
assign_statement = located_statements[0].statement()
636-
if isinstance(assign_statement, astroid.ExceptHandler):
637-
current = node
638-
while current and not isinstance(current.parent, astroid.ExceptHandler):
639-
current = current.parent
634+
# On Python 3 we don't find the leaked objects as
635+
# they are already deleted, so instead look for them manually.
636+
scope = node.scope()
637+
assign_names = (node_ for node_ in scope.nodes_of_class(astroid.AssignName)
638+
if node_.name == node.name and node_.lineno < node.lineno)
639+
assigned = next(assign_names, None)
640+
if not assigned:
641+
return
642+
643+
assign_statement = assigned.statement()
644+
assigns = (node_ for node_ in scope.nodes_of_class(astroid.Assign)
645+
if node_.lineno < node.lineno)
640646

641-
if current and isinstance(current.parent, astroid.ExceptHandler):
647+
for assign in assigns:
648+
for target in assign.targets:
649+
if getattr(target, 'name', None) == node.name:
642650
return
643-
self.add_message('exception-escape', node=node)
644651

645-
if isinstance(assign_statement, (astroid.Expr, astroid.Assign)):
646-
if (isinstance(assign_statement.value, astroid.ListComp)
647-
and not assign_statement.parent_of(node)):
648-
self.add_message('comprehension-escape', node=node)
652+
if isinstance(assign_statement, astroid.ExceptHandler):
653+
current = node
654+
while current and not isinstance(current.parent, astroid.ExceptHandler):
655+
current = current.parent
656+
if current and isinstance(current.parent, astroid.ExceptHandler):
657+
return
658+
self.add_message('exception-escape', node=node)
659+
660+
if isinstance(assign_statement, (astroid.Expr, astroid.Assign)):
661+
if (isinstance(assign_statement.value, astroid.ListComp)
662+
and not assign_statement.parent_of(node)):
663+
self.add_message('comprehension-escape', node=node)
649664

650665
@utils.check_messages('print-statement')
651666
def visit_print(self, node):

0 commit comments

Comments
 (0)