-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Closed
Closed
Copy link
Labels
bugSomething isn't workingSomething isn't workingfixesRelated to suggested fixes for violationsRelated to suggested fixes for violations
Description
Description
for-loop-writes (FURB122) in Ruff 0.9.3 has a false positive if writing to the target variable has an effect beyond the write call. This can happen in two ways.
When the for loop’s target list includes a global or nonlocal variable, writing to the target has a side effect. Rewriting the loop as a generator puts the target in a new, nested scope, which can change program behavior.
$ cat >furb122_1.py <<'EOF'
from pathlib import Path
CURRENT_LINE = "..."
def wrap_line():
return f"<{CURRENT_LINE}>\n"
def write(lines):
with Path("furb122.txt").open("w") as f:
global CURRENT_LINE
for CURRENT_LINE in lines:
f.write(wrap_line())
write(["line1", "line2"])
EOF
$ python furb122_1.py
$ cat furb122.txt
<line1>
<line2>
$ ruff --isolated check --preview --select FURB122 furb122_1.py --fix
Found 1 error (1 fixed, 0 remaining).
$ cat furb122_1.py
from pathlib import Path
CURRENT_LINE = "..."
def wrap_line():
return f"<{CURRENT_LINE}>\n"
def write(lines):
with Path("furb122.txt").open("w") as f:
global CURRENT_LINE
f.writelines(wrap_line() for CURRENT_LINE in lines)
write(["line1", "line2"])
$ python furb122_1.py
$ cat furb122.txt
<...>
<...>Similarly, when the for loop’s target list includes a variable that is used after the loop, rewriting the loop as a generator changes the variable’s scope, so the outer variable is not set.
$ cat >furb122_2.py <<'EOF'
from pathlib import Path
line = "..."
with Path("furb122.txt").open("w") as f:
for line in ["line1", "line2"]:
f.write(f"{line}\n")
print(f"{line=}")
EOF
$ python furb122_2.py
line='line2'
$ ruff --isolated check --preview --select FURB122 furb122_2.py --fix
Found 1 error (1 fixed, 0 remaining).
$ cat furb122_2.py
from pathlib import Path
line = "..."
with Path("furb122.txt").open("w") as f:
f.writelines(f"{line}\n" for line in ["line1", "line2"])
print(f"{line=}")
$ python furb122_2.py
line='...'Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingfixesRelated to suggested fixes for violationsRelated to suggested fixes for violations