fixhunt

ruff W605: fix changes program behavior

fix-changes-behaviorlabelled safeintended-change · lowduplicate
Findings / 2026-10-17T20-50-05-853Z-2tuo-ruff-W605 / r1-p005ruff 0.17.113 → 11 lines2026-10-17 20:50 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

context managers that are not files, objects with write() but no close()

Program

before
1class Logger:
2 def __init__(self):
3 self.buf = []
4 def write(self, msg):
5 self.buf.append(msg)
6 def __enter__(self):
7 return self
8 def __exit__(self, *args):
9 pass
10with Logger() as log:
11 log.write('\_')
after
1class Logger:
2 def __init__(self):
3 self.buf = []
4 def write(self, msg):
5 self.buf.append(msg)
6 def __enter__(self):
7 return self
8 def __exit__(self, *args):
9 pass
10with Logger() as log:
11 log.write(r'\_')

Output

stdout beforeexit 0
(no stdout)
/w/prog.py:11: SyntaxWarning: invalid escape sequence '\_'
stdout afterexit 0
(no stdout)
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory intended-change · low

The rule rewrites the string literal '\_' to a raw string r'\_' to eliminate the SyntaxWarning about an invalid escape sequence. The observed difference is the disappearance of that warning, which is exactly the semantic change the rule documents as its purpose.

Explanation Nemotron 3 Super unverified

The original string literal '\\_' contains a backslash followed by underscore; Python interprets this as an invalid escape sequence, issuing a SyntaxWarning but treating the backslash as a literal character, so the stored value is the two‑character string '\\_'. The rewritten literal r'\\_' is a raw string where backslashes are not escape characters, so it also stores the two‑character string '\\_'. Although the resulting string content is identical, the original code produced a SyntaxWarning on compilation, while the fixed version suppresses that warning. Since the presence or absence of a warning constitutes observable differing behavior, the transformation is not semantics‑preserving.

Reproduce

file
prog.py (the before program)
minimized program
r1-p005.py
evidence sheet
r1-p005.md
regression fixture
r1-p005.py the minimized program with a header stating the observed change, for the tool's test suite
python3 prog.py
ruff check --preview --isolated --select W605 --fix prog.py
python3 prog.py

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

W605 fix · W605 invalid escape sequence · W605 backslash underscore · W605 raw string literal

Details

program
Context managers without close()
hazard
context managers that are not files, objects with write() but no close()
oracle
stderr before: /w/prog.py:11: SyntaxWarning: invalid escape sequence '\_' stderr after: (none)
run
2026-10-17T20-50-05-853Z-2tuo-ruff-W605
generated program (13 lines) and the fix's diff
1class Logger:
2 def __init__(self):
3 self.buf = []
4 def write(self, msg):
5 self.buf.append(msg)
6 def __enter__(self):
7 return self
8 def __exit__(self, *args):
9 pass
10with Logger() as log:
11 log.write('\_')
12print(log.buf)
13print('len:', len(log.buf[0]))
--- orig.py	2026-10-17 16:50:21.096535501 -0400
+++ fixed.py	2026-10-17 16:50:21.300539462 -0400
@@ -8,6 +8,6 @@
     def __exit__(self, *args):
         pass
 with Logger() as log:
-    log.write('\_')
+    log.write(r'\_')
 print(log.buf)
 print('len:', len(log.buf[0]))
rule documentation given to the models
# invalid-escape-sequence (W605)

Derived from the **pycodestyle** linter.

Fix is always available.

## What it does
Checks for invalid escape sequences.

## Why is this bad?
Invalid escape sequences are deprecated in Python 3.6.

## Example
```python
regex = "\.png$"
```

Use instead:
```python
regex = r"\.png$"
```

Or, if the string already contains a valid escape sequence:
```python
value = "new line\nand invalid escape \_ here"
```

Use instead:
```python
value = "new line\nand invalid escape \\_ here"
```

## References
- [Python documentation: String and Bytes literals](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals)