Skip to content

Fix #5326: Fix false positive for unused-variable for a comprehension variable matching a type annotation #5651

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ Release date: TBA

Closes #5461

* Fix false positive for ``unused-variable`` for a comprehension variable matching
an outer scope type annotation.

Closes #5326

* 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 @@ -116,6 +116,11 @@ Other Changes

Closes #5461

* Fix false positive for ``unused-variable`` for a comprehension variable matching
an outer scope type annotation.

Closes #5326

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

Closes #5065
Expand Down
2 changes: 1 addition & 1 deletion pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1803,7 +1803,7 @@ def _is_only_type_assignment(node: nodes.Name, defstmt: nodes.Statement) -> bool
# Local refs are ordered, so we break.
# print(var)
# var = 1 # <- irrelevant
if defstmt_frame == node_frame and not ref_node.lineno < node.lineno:
if defstmt_frame == node_frame and ref_node.lineno > node.lineno:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the small optimization to save a "not" on top of the clever fix !

break

# If the parent of the local reference is anything but an AnnAssign
Expand Down
21 changes: 19 additions & 2 deletions tests/functional/u/undefined/undefined_variable_py38.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ def typing_and_assignment_expression():
print(var)


def typing_and_self_referncing_assignment_expression():
def typing_and_self_referencing_assignment_expression():
"""The variable gets assigned in an assignment expression that references itself"""
var: int
if (var := var ** 2): # [undefined-variable]
if (var := var ** 2): # false negative--walrus operator!
print(var)


Expand Down Expand Up @@ -108,3 +108,20 @@ def no_parameters_in_function_default() -> None:
if (x_0 := thing.this_value) < (x_1 := thing.that_value)
else x_1,
)


# Tests for type annotation reused in comprehension

def type_annotation_used_after_comprehension():
"""https://github.com/PyCQA/pylint/issues/5326#issuecomment-982635371"""
my_int: int
ints = [my_int + 1 for my_int in range(5)]

for my_int in ints:
print(my_int)


def type_annotation_unused_after_comprehension():
"""https://github.com/PyCQA/pylint/issues/5326"""
my_int: int
_ = [print(kwarg1=my_int, kwarg2=my_int) for my_int in range(10)]
1 change: 0 additions & 1 deletion tests/functional/u/undefined/undefined_variable_py38.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
undefined-variable:17:15:17:18:typing_and_self_referncing_assignment_expression:Undefined variable 'var':UNDEFINED
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
Expand Down