Skip to content

Commit

Permalink
Fix pylint-dev#5654: Fix false negative for undefined-variable for …
Browse files Browse the repository at this point in the history
…unused type annotation after the same name appears multiple times in a comprehension
  • Loading branch information
jacobtylerwalls committed Jan 24, 2022
1 parent ccd9aee commit 2bada5b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 3 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ Release date: TBA

Closes #5326

* Fix false negative for ``undefined-variable`` for a variable used multiple times
in a comprehension matching an unused outer scope type annotation.

Closes #5654

* Some files in ``pylint.testutils`` were deprecated. In the future imports should be done from the
``pylint.testutils.functional`` namespace directly.

Expand Down
5 changes: 5 additions & 0 deletions doc/whatsnew/2.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ Other Changes

Closes #5326

* Fix false negative for ``undefined-variable`` for a variable used multiple times
in a comprehension matching an unused outer scope type annotation.

Closes #5654

* Require Python ``3.6.2`` to run pylint.

Closes #5065
Expand Down
12 changes: 10 additions & 2 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1388,8 +1388,16 @@ def _check_consumer(
# (like "if x" in "[x for x in expr() if x]")
# https://github.com/PyCQA/pylint/issues/5586
and not (
isinstance(node.parent.parent, nodes.Comprehension)
and node.parent in node.parent.parent.ifs
(
isinstance(node.parent.parent, nodes.Comprehension)
and node.parent in node.parent.parent.ifs
)
# Or homonyms against values to keyword arguments
# (like "var" in [func(arg=var) for var in expr()])
or (
isinstance(node.scope(), nodes.ComprehensionScope)
and isinstance(node.parent, (nodes.Call, nodes.Keyword))
)
)
):
self._check_late_binding_closure(node)
Expand Down
16 changes: 15 additions & 1 deletion tests/functional/u/undefined/undefined_variable_py38.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,19 @@ def type_annotation_used_after_comprehension():

def type_annotation_unused_after_comprehension():
"""https://github.com/PyCQA/pylint/issues/5326"""
my_int: int # [unused-variable]
_ = [print(sep=my_int, end=my_int) for my_int in range(10)]


def type_annotation_used_improperly_after_comprehension():
"""https://github.com/PyCQA/pylint/issues/5654"""
my_int: int
_ = [print(sep=my_int, end=my_int) for my_int in range(10)]
print(my_int) # [undefined-variable]


def type_annotation_used_improperly_after_comprehension_2():
"""Same case as above but with positional arguments"""
my_int: int
_ = [print(kwarg1=my_int, kwarg2=my_int) for my_int in range(10)]
_ = [print(my_int, my_int) for my_int in range(10)]
print(my_int) # [undefined-variable]
3 changes: 3 additions & 0 deletions tests/functional/u/undefined/undefined_variable_py38.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ undefined-variable:42:6:42:16::Undefined variable 'no_default':UNDEFINED
undefined-variable:50:6:50:22::Undefined variable 'again_no_default':UNDEFINED
undefined-variable:76:6:76:19::Undefined variable 'else_assign_1':UNDEFINED
undefined-variable:99:6:99:19::Undefined variable 'else_assign_2':UNDEFINED
unused-variable:126:4:126:10:type_annotation_unused_after_comprehension:Unused variable 'my_int':UNDEFINED
undefined-variable:134:10:134:16:type_annotation_used_improperly_after_comprehension:Undefined variable 'my_int':UNDEFINED
undefined-variable:141:10:141:16:type_annotation_used_improperly_after_comprehension_2:Undefined variable 'my_int':UNDEFINED

0 comments on commit 2bada5b

Please sign in to comment.