From 58b9e6421b2246597c97c75640ee6337460cb0ba Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Mon, 16 Dec 2019 09:26:45 +0100 Subject: [PATCH] ``undefined-variable`` can now find undefined loop iterables Close #498 --- ChangeLog | 4 ++++ pylint/checkers/variables.py | 10 +++++++++- tests/functional/u/undefined_variable.py | 7 +++++++ tests/functional/u/undefined_variable.txt | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f68cdb2260..997195510b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,10 @@ Release date: TBA Close #3301 +* ``undefined-variable`` can now find undefined loop iterables + + Close #498 + * ``safe_infer`` can infer a value as long as all the paths share the same type. Close #2503 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 6a28870536..4449bd960e 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -546,7 +546,7 @@ def mark_as_consumed(self, name, new_node): del self.to_consume[name] def get_next_to_consume(self, node): - # mark the name as consumed if it's defined in this scope + # Get the definition of `node` from this scope name = node.name parent_node = node.parent found_node = self.to_consume.get(name) @@ -558,6 +558,14 @@ def get_next_to_consume(self, node): lhs = found_node[0].parent.targets[0] if lhs.name == name: # this name is defined in this very statement found_node = None + + if ( + found_node + and isinstance(parent_node, astroid.For) + and parent_node.iter == node + and parent_node.target in found_node + ): + found_node = None return found_node diff --git a/tests/functional/u/undefined_variable.py b/tests/functional/u/undefined_variable.py index 4323bfd3c7..4787beb9a2 100644 --- a/tests/functional/u/undefined_variable.py +++ b/tests/functional/u/undefined_variable.py @@ -274,3 +274,10 @@ def func_should_fail(_dt: datetime): # [used-before-assignment] def tick(counter: Counter, name: str, dictionary: OrderedDict) -> OrderedDict: counter[name] += 1 return dictionary + + +# pylint: disable=unused-argument +def not_using_loop_variable_accordingly(iterator): + for iteree in iteree: # [undefined-variable] + yield iteree +# pylint: enable=unused-argument diff --git a/tests/functional/u/undefined_variable.txt b/tests/functional/u/undefined_variable.txt index fa86ff5b6e..d9aa6c86db 100644 --- a/tests/functional/u/undefined_variable.txt +++ b/tests/functional/u/undefined_variable.txt @@ -25,3 +25,4 @@ undefined-variable:170::Undefined variable 'unicode_3' undefined-variable:225:LambdaClass4.:Undefined variable 'LambdaClass4' undefined-variable:233:LambdaClass5.:Undefined variable 'LambdaClass5' used-before-assignment:254:func_should_fail:Using variable 'datetime' before assignment +undefined-variable:281:not_using_loop_variable_accordingly:Undefined variable 'iteree'