ruff icon indicating copy to clipboard operation
ruff copied to clipboard

B007 breaks code

Open spaceone opened this issue 2 years ago • 4 comments

$ 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

spaceone avatar Jan 26 '23 17:01 spaceone

Isn't this the right behaviour? bar is not used in the loop, it's used outside the loop.

dycw avatar Jan 27 '23 02:01 dycw

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').

charliermarsh avatar Jan 27 '23 03:01 charliermarsh

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.

charliermarsh avatar Jan 28 '23 12:01 charliermarsh

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)

spaceone avatar Feb 01 '23 15:02 spaceone