ruff
ruff copied to clipboard
B007 breaks code
$ cat foo.py
for foo, bar, baz in (['1', '2', '3'], ):
if foo or baz:
break
int(bar)
$ ruff --select B007 foo.py
foo.py:1:10: B007 Loop control variable `bar` not used within loop body
Found 1 error.
1 potentially fixable with the --fix option.
$ ruff --select B007 --fix foo.py
Found 1 error (1 fixed, 0 remaining).
$ cat foo.py
for foo, _bar, baz in (['1', '2', '3'], ):
if foo or baz:
break
int(bar)
$ python3 foo.py
Traceback (most recent call last):
File "foo.py", line 5, in <module>
int(bar)
NameError: name 'bar' is not defined
Isn't this the right behaviour? bar is not used in the loop, it's used outside the loop.
If the thing you're iterating over is non-empty, then when the loop finishes, bar will continue to exist, taking on the last value (in this case, '2').
It's possible for us to avoid this, but it requires some refactoring. We do track whether variables are used, even after their declaration site, but this specific check doesn't have access to that info.
another real life example which was caused by this:
def _fake_func(self, iterator, *args):
- for args in iterator:
+ for _args in iterator:
break
yield function(self, *args)