fixhunt

ruff W605

labelled unknown
Runs / 2026-10-17T20-50-05-853Z-2tuo-ruff-W605ruff 0.17.12026-10-17 20:50 UTC8 programs × 2 round(s)8 programs, 7 fired, 7 fixed, 7 findings, 0 rejectedmodel cost $0.13

Analysis Nemotron 3 Super

Flags backslash-character combinations in string literals that do not form valid Python escape sequences.

Fix: Replace the invalid escape sequence by doubling the backslash before the character to treat it as a literal backslash followed by that character, preserving all other string content and quote style.

12 hazards
  • In raw strings (r"..."), doubling backslashes introduces extra literal backslashes, altering the intended pattern (e.g., r"\." becomes r"\\." which matches two backslashes then a dot).
  • In byte strings, the fix may produce invalid byte escape sequences if the character after the backslash is not a valid hex digit or octal digit, causing a SyntaxError.
  • If the string is part of a larger expression where the backslash was intended as a line continuation (outside string literals), the fix does not apply and is irrelevant, but misidentification could lead to incorrect changes.
  • When the invalid escape appears in a docstring or comment-like context inside a string, doubling the backslash changes the literal text, potentially breaking tools that parse the string content (e.g., help(), doctests).
  • If the string uses triple quotes and the invalid escape spans across implicit line joining due to a backslash at end-of-line inside the string, fixing it may disrupt the line continuation semantics within the string content.
  • In f-strings, if the invalid escape occurs inside an expression part ({...}), the fix is not applied there; but if mistakenly applied, it would corrupt the expression syntax.
  • If the string is adjacent to another string literal for concatenation (e.g., "a" "b"), and the fix is applied only to one part, the resulting concatenated string may have unintended backslash duplication.
  • When the invalid escape is immediately followed by a quote of the same kind that ends the string (e.g., "\""), doubling the backslash may interfere with the string termination if not handled correctly by the lexer during refactoring.
  • If the string contains mixed valid and invalid escapes (e.g., "\n\_"), fixing only the invalid part may create an inconsistent interpretation where the valid escape remains unchanged but the invalid one becomes literal, which may be the intent but must be verified.
  • In code generated by macros or templating systems where backslashes are placeholders, doubling them could break the generator's assumptions about the output format.
  • When the string is used in a regex context via re.sub or similar, doubling backslashes changes the number of escape layers, potentially requiring compensatory changes elsewhere in the pattern.
  • If the invalid escape is part of a Unicode name escape like \N{...} with invalid contents, doubling the backslash yields a literal backslash-N, which is not equivalent and may raise a different error at runtime.

Findings

programoraclelabeljudgestatussummary
r1-p001fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites the invalid escape sequence '\.' into a raw string r'\.' to eliminate the SyntaxWarning, which is exactly the documented purpose. The program…
r1-p002fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites the string literal containing an invalid escape sequence '\_' into a raw string r'\_' to eliminate the SyntaxWarning, which is the documented…
r1-p004fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites the invalid escape sequence '\_' to the valid escaped backslash '\\_', which changes the string value from a newline followed by '_' to a new…
r1-p005fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites the string literal '\_' to a raw string r'\_' to eliminate the SyntaxWarning about an invalid escape sequence. The observed difference is the…
r1-p006fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites an invalid escape sequence '\.' to a raw string r'\.' to eliminate the SyntaxWarning, which is exactly the documented purpose. The stderr dif…
r1-p007fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites an invalid escape sequence '\.' to a raw string r'\.' to eliminate the SyntaxWarning, which is the documented purpose of the fix. The program…
r1-p008fix-changes-behaviorlabelled safeintended-change · lowduplicateThe rule rewrites the string literal to a raw string to eliminate the SyntaxWarning about the invalid escape sequence '\_'. The stderr difference (warning disa…

Programs

idresulttitlehazard
r1-p001fix-changes-behaviorString concatenation adjacencyIf the string is adjacent to another string literal for concatenation (e.g., "a" "b"), and the fix is applied only to one part, the resulting concatenated string may have unintended backslash duplicat
r1-p002fix-changes-behaviorMutable default arguments and aliasingmutable default arguments and aliasing after a rewrite
r1-p003silentLine continuation misidentificationIf the string is part of a larger expression where the backslash was intended as a line continuation (outside string literals), the fix does not apply and is irrelevant, but misidentification could le
r1-p004fix-changes-behaviorMixed valid and invalid escapesIf the string contains mixed valid and invalid escapes (e.g., "\n\_"), fixing only the invalid part may create an inconsistent interpretation where the valid escape remains unchanged but the invalid o
r1-p005fix-changes-behaviorContext managers without close()context managers that are not files, objects with write() but no close()
r1-p006fix-changes-behaviorNumeric coercion and arithmeticint/float/bool coercion, Decimal, division and rounding
r1-p007fix-changes-behaviorRegex substitution backfireWhen the string is used in a regex context via re.sub or similar, doubling backslashes changes the number of escape layers, potentially requiring compensatory changes elsewhere in the pattern.
r1-p008fix-changes-behaviorFile write modes and truncationfile modes and truncation, partial writes, non-str data passed to write

Sources

r1-p001 · String concatenation adjacency
1s = '\.' 'rest'
2t = s
3print(repr(t))
4if '__' in t:
5 print('double backslash')
6else:
7 print('single backslash')
--- orig.py	2026-10-17 16:50:20.020514587 -0400
+++ fixed.py	2026-10-17 16:50:20.224518552 -0400
@@ -1,4 +1,4 @@
-s = '\.' 'rest'
+s = r'\.' 'rest'
 t = s
 print(repr(t))
 if '__' in t:
'\\.rest'
single backslash
r1-p002 · Mutable default arguments and aliasing
1def f(x=['\_']):
2 x[0] = 'changed'
3 return x
4print(f())
5print(f())
6s = ['\_']
7f(s)
8print(s)
--- orig.py	2026-10-17 16:50:20.330520613 -0400
+++ fixed.py	2026-10-17 16:50:20.541524714 -0400
@@ -1,8 +1,8 @@
-def f(x=['\_']):
+def f(x=[r'\_']):
     x[0] = 'changed'
     return x
 print(f())
 print(f())
-s = ['\_']
+s = [r'\_']
 f(s)
 print(s)
['changed']
['changed']
['changed']
r1-p003 · Line continuation misidentification
1total = 1 + \
2 2
3print(total)
4x = 'hello'
5# no trigger here
3
r1-p004 · Mixed valid and invalid escapes
1s = '\n\_'
2print(repr(s))
3print(len(s))
4for c in s:
5 print(ord(c))
--- orig.py	2026-10-17 16:50:20.778529321 -0400
+++ fixed.py	2026-10-17 16:50:20.992533481 -0400
@@ -1,4 +1,4 @@
-s = '\n\_'
+s = '\n\\_'
 print(repr(s))
 print(len(s))
 for c in s:
'\n\\_'
3
10
92
95
r1-p005 · Context managers without close()
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]))
['\\_']
len: 2
r1-p006 · Numeric coercion and arithmetic
1from decimal import Decimal
2s = '\.'
3print(bool(s))
4print(int(s, 16) if all(c in '0123456789abcdefABCDEF' for c in s.replace('\\', '')) else 'NaN')
5d = Decimal('1.5')
6print(d / 2)
7print(round(2.5))
--- orig.py	2026-10-17 16:50:21.403541462 -0400
+++ fixed.py	2026-10-17 16:50:21.613545540 -0400
@@ -1,5 +1,5 @@
 from decimal import Decimal
-s = '\.'
+s = r'\.'
 print(bool(s))
 print(int(s, 16) if all(c in '0123456789abcdefABCDEF' for c in s.replace('\\', '')) else 'NaN')
 d = Decimal('1.5')
True
NaN
0.75
2
r1-p007 · Regex substitution backfire
1import re
2pattern = '\.'
3text = 'a.b'
4result = re.sub(pattern, 'X', text)
5print(result)
6print('expected: aXb')
7if result == 'aXb':
8 print('match')
9else:
10 print('mismatch:', repr(result))
--- orig.py	2026-10-17 16:50:21.723547676 -0400
+++ fixed.py	2026-10-17 16:50:21.933551754 -0400
@@ -1,5 +1,5 @@
 import re
-pattern = '\.'
+pattern = r'\.'
 text = 'a.b'
 result = re.sub(pattern, 'X', text)
 print(result)
aXb
expected: aXb
match
r1-p008 · File write modes and truncation
1with open('test.txt', 'w') as f:
2 f.write('\_')
3with open('test.txt', 'r') as f:
4 content = f.read()
5print(repr(content))
6import os
7os.remove('test.txt')
--- orig.py	2026-10-17 16:50:22.036553753 -0400
+++ fixed.py	2026-10-17 16:50:22.239557691 -0400
@@ -1,5 +1,5 @@
 with open('test.txt', 'w') as f:
-    f.write('\_')
+    f.write(r'\_')
 with open('test.txt', 'r') as f:
     content = f.read()
 print(repr(content))
'\\_'