Skip to content
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

used-before-assignment false positive with walrus #9984

Open
nickdrozd opened this issue Sep 28, 2024 · 1 comment
Open

used-before-assignment false positive with walrus #9984

nickdrozd opened this issue Sep 28, 2024 · 1 comment
Labels
Assignment expression Related to the walrus operator / assignment expression C: used-before-assignment Issues related to 'used-before-assignment' check False Positive 🦟 A message is emitted but nothing is wrong with the code

Comments

@nickdrozd
Copy link
Collaborator

nickdrozd commented Sep 28, 2024

Bug description

from collections import defaultdict

KEYS: dict[int, dict[int, int]] = defaultdict(dict)

def f(x: int, y: int, z: int) -> int:
    try:
        return (keys := KEYS[x])[y]
    except KeyError:
        keys[y] = z  # [used-before-assignment] FALSE POSITIVE
        return z

print(f(1, 2, 3))
print(f(4, 5, 6))
print(f(4, 5, 6))

Configuration

No response

Command used

pylint asdf.py

Pylint output

pylint asdf.py 
************* Module asdf
asdf.py:9:8: E0601: Using variable 'keys' before assignment (used-before-assignment)

------------------------------------------------------------------
Your code has been rated at 5.45/10 (previous run: 5.45/10, +0.00)

Expected behavior

KEYS[x] succeeds, and so does keys := KEYS[x]. keys[y] may fail with KeyError, but by that time keys is defined, so its use in the except block works.

It is important that KEYS is defaultdict. If it were a regular dictionary, KEYS[x] might fail, in which case keys would indeed be undefined in the except block. Is that something inference can determine? Possibly this should be possibly-used-before-assignment instead.

Pylint version

pylint 4.0.0-dev0
astroid 3.4.0-dev0
Python 3.12.3 (tags/v3.12.3:f6650f9ad73, May 28 2024, 17:31:51) [GCC 9.4.0]

OS / Environment

No response

Additional dependencies

No response

@nickdrozd nickdrozd added Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling C: used-before-assignment Issues related to 'used-before-assignment' check False Positive 🦟 A message is emitted but nothing is wrong with the code Assignment expression Related to the walrus operator / assignment expression and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Sep 28, 2024
@jacobtylerwalls
Copy link
Member

jacobtylerwalls commented Sep 29, 2024

keys[y] may fail with KeyError, but by that time keys is defined, so its use in the except block works.

Right, but what about this:

    try:
        return (keys := KEYS[x][0])[y]

Now it will fail with KeyError but before keys is defined:

  File "/Users/jwalls/Desktop/a.py", line 9, in f
    keys[y] = z  # [used-before-assignment] FALSE POSITIVE
    ^^^^
UnboundLocalError: cannot access local variable 'keys' where it is not associated with a value

I think the idea here is to keep the principle as simple/stupid as possible: except blocks shouldn't depend on try statements succeeding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Assignment expression Related to the walrus operator / assignment expression C: used-before-assignment Issues related to 'used-before-assignment' check False Positive 🦟 A message is emitted but nothing is wrong with the code
Projects
None yet
Development

No branches or pull requests

2 participants