ruff
ruff copied to clipboard
False positive for F821
It seems that using dict
as a parameter name in a function (which I'd consider bad style) breaks ruff's parsing in unexpected ways. In particular the following gives 6:31: F821 Undefined name 'name'
, when it shouldn't.
def unimportant(name):
pass
def dang(dict):
return unimportant(name=dict["name"])
Here is my pyproject.toml if that's needed to reproduce:
[tool.ruff]
ignore = [
'B007',
'E741',
'E501',
]
line-length = 88
select = [
'B',
'E',
'F',
'W',
]
Thanks! Yeah, definitely a legit bug. We need to verify that dict
corresponds to the built-in and hasn't been shadowed.
Appreciate the clear test case.
(I'll fix this tomorrow most likely, probably not tonight.)
Tangentially, I guess I'd argue that Flake8 erroneously doesn't catch this:
# Flake8 allows this
x = dict["foo"]
# Flake8 raises F821 here
x: dict["foo"]
Both should raise an undefined error on foo
.
The reason I mention it is because both Flake8 and Ruff accidentally raise F821 here:
def f(dict):
x: dict["foo"] = 1
But I will fix this in Ruff :)
Thanks for the quick response! Yeah interesting that flake8 has that issue too - I guess it's a bit more niche, so as-yet undiscovered (or unfixed) by them.
Well, I've also let the pyflakes team know about this edge case https://github.com/PyCQA/pyflakes/issues/738 I assume they'll want to fix it!
The reason I mention it is because both Flake8 and Ruff accidentally raise F821 here:
def f(dict): x: dict["foo"] = 1
So pyflakes adopt the attitude of "this is a bad type annotation - won't fix". In fact this also gives F821 with flake8 but not ruff:
def f(noshadow):
x: noshadow["foo"] = 1
Either way, having consistent behavior in ruff with or without shadowing is good (whether or not that differs from flake8 slightly).
I'm behind on this, it'll come soon :)
@charliermarsh, I could work on it if it is ok with you.
That'd be great @JonathanPlasse! I know it's relevant to the sys.exit
stuff too.