Skip to content

Commit

Permalink
[used-before-assignment] Extend "same test" exception to named expres…
Browse files Browse the repository at this point in the history
…sions (#10062)
  • Loading branch information
jacobtylerwalls authored Nov 3, 2024
1 parent 4e4f04f commit ac2ae53
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This warns:

If you find this surprising, consider that pylint, as a static analysis
tool, does not know if ``guarded()`` is deterministic or talks to
a database. For constants (e.g. ``guarded`` versus ``guarded()``),
a database. For variables (e.g. ``guarded`` versus ``guarded()``),
this is less of an issue, so in this case,
``possibly-used-before-assignment`` acts more like a future-proofing style
preference than an error, per se.
5 changes: 5 additions & 0 deletions doc/whatsnew/fragments/10061.false_positive
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fix a false positive for `used-before-assignment` when a variable defined under
an `if` and via a named expression (walrus operator) is used later when guarded
under the same `if` test.

Closes #10061
10 changes: 7 additions & 3 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,10 +765,14 @@ def _node_guarded_by_same_test(node: nodes.NodeNG, other_if: nodes.If) -> bool:
or if their inferred values consist only of constants and those constants
are identical, and the if test guarding `node` is not a Name.
"""
other_if_test_as_string = other_if.test.as_string()
other_if_test_all_inferred = utils.infer_all(other_if.test)
if isinstance(other_if.test, nodes.NamedExpr):
other_if_test = other_if.test.target
else:
other_if_test = other_if.test
other_if_test_as_string = other_if_test.as_string()
other_if_test_all_inferred = utils.infer_all(other_if_test)
for ancestor in node.node_ancestors():
if not isinstance(ancestor, nodes.If):
if not isinstance(ancestor, (nodes.If, nodes.IfExp)):
continue
if ancestor.test.as_string() == other_if_test_as_string:
return True
Expand Down
8 changes: 8 additions & 0 deletions tests/functional/u/used/used_before_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ def turn_on2(**kwargs):
if 1 in []:
print(PERCENT)


# Always true
if always_true := True:
ONE = 1

print(ONE if always_true else 2)


# Different test
if 1 in [1]:
print(SALE) # [used-before-assignment]
Expand Down
14 changes: 7 additions & 7 deletions tests/functional/u/used/used_before_assignment.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ possibly-used-before-assignment:75:3:75:7::Possibly using variable 'VAR5' before
used-before-assignment:80:3:80:7::Using variable 'VAR6' before assignment:INFERENCE
used-before-assignment:115:6:115:11::Using variable 'VAR10' before assignment:INFERENCE
possibly-used-before-assignment:121:6:121:11::Possibly using variable 'VAR12' before assignment:CONTROL_FLOW
used-before-assignment:152:10:152:14::Using variable 'SALE' before assignment:INFERENCE
used-before-assignment:184:10:184:18::Using variable 'ALL_DONE' before assignment:INFERENCE
used-before-assignment:195:6:195:24::Using variable 'NOT_ALWAYS_DEFINED' before assignment:INFERENCE
used-before-assignment:231:10:231:11::Using variable 'x' before assignment:CONTROL_FLOW
possibly-used-before-assignment:245:10:245:15:__:Possibly using variable 'fail1' before assignment:CONTROL_FLOW
used-before-assignment:259:18:259:19:outer_.inner_try:Using variable 'a' before assignment:HIGH
used-before-assignment:270:18:270:19:outer_.inner_while:Using variable 'a' before assignment:HIGH
used-before-assignment:160:10:160:14::Using variable 'SALE' before assignment:INFERENCE
used-before-assignment:192:10:192:18::Using variable 'ALL_DONE' before assignment:INFERENCE
used-before-assignment:203:6:203:24::Using variable 'NOT_ALWAYS_DEFINED' before assignment:INFERENCE
used-before-assignment:239:10:239:11::Using variable 'x' before assignment:CONTROL_FLOW
possibly-used-before-assignment:253:10:253:15:__:Possibly using variable 'fail1' before assignment:CONTROL_FLOW
used-before-assignment:267:18:267:19:outer_.inner_try:Using variable 'a' before assignment:HIGH
used-before-assignment:278:18:278:19:outer_.inner_while:Using variable 'a' before assignment:HIGH

0 comments on commit ac2ae53

Please sign in to comment.