fixhunt

ruff RUF101

labelled unknown
Runs / 2026-10-17T21-49-53-119Z-shie-ruff-RUF101ruff 0.17.12026-10-17 21:49 UTC8 programs × 2 round(s)16 programs, 12 fired, 12 fixed, 0 findings, 2 rejectedmodel cost $0.0030

Analysis Nemotron 3 Super

Flags 'noqa' directives using deprecated rule codes that have been redirected to canonical replacements.

Fix: Replaces each deprecated rule code in a noqa directive with its current canonical replacement (e.g., PGH001 → S307, S602 → S603, SIM103 → SIM115, RET503 → RET506, RET504 → RET506, RET506 → RET506, G001 → G004, ERA001 → ERA002).

12 hazards
  • The rewrite may incorrectly merge multiple noqa codes if the original line contains a trailing comma after the deprecated code, altering suppression intent.
  • If the noqa directive is split across multiple lines via backslash continuation, the rewrite may fail to match or corrupt the line structure.
  • In a line with multiple noqa codes separated by spaces (not commas), the rewrite may not match due to unexpected delimiter handling.
  • If the deprecated code appears as part of a larger identifier (e.g., in a string or comment), the rewrite could erroneously modify unrelated text.
  • When the noqa directive is embedded within a multiline string or docstring, the rewrite may break string syntax or introduce invalid escape sequences.
  • If the line contains a '#' character inside brackets or quotes (e.g., in a list or regex), the rewrite may mismatch the actual noqa directive due to incorrect comment detection.
  • The rewrite may remove or reorder inline comments that appear after the noqa directive on the same line, changing documentation or intent.
  • If the deprecated code is written with mixed case (e.g., 'pgh001'), the rewrite may not trigger due to case sensitivity, leaving the deprecated code unchanged.
  • In files with non-UTF-8 encoding, the rewrite may corrupt byte sequences when modifying the source, leading to decode errors.
  • If the noqa directive is the only content on a line and the rewrite changes its length, it may affect blank-line-dependent tools or formatters that rely on line count.
  • When the line ends with whitespace after the noqa directive, the rewrite may preserve or drop that whitespace inconsistently across editor configurations.
  • If the deprecated code is part of a larger noqa message (e.g., '# noqa: PGH001 some reason'), the rewrite may produce ambiguous or invalid code by replacing only the code portion.

Programs

idresulttitlehazard
r1-p001fix okClass attribute descriptor interactionclass attributes vs instance attributes, descriptors, properties with side effects
r1-p002fix okNon-UTF-8 encoding corruptionIn files with non-UTF-8 encoding, the rewrite may corrupt byte sequences when modifying the source, leading to decode errors.
r1-p003fix okTrailing whitespace preservationWhen the line ends with whitespace after the noqa directive, the rewrite may preserve or drop that whitespace inconsistently across editor configurations.
r1-p004fix okDict ordering and duplicate keysdict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r1-p005fix okTrailing comma merging noqa codesThe rewrite may incorrectly merge multiple noqa codes if the original line contains a trailing comma after the deprecated code, altering suppression intent.
r1-p006invalidWalrus and late binding in closureswalrus, comprehensions scoping, late binding in closures and lambdas
r1-p007fix okShadowed builtins and redefinitionshadowed builtins and names redefined later in the module
r1-p008fix okExceptions in finally/else clausesexceptions raised inside the rewritten code, finally/else clauses, exception chaining
r2-p001invalidDeprecated code in string literalIf the deprecated code appears as part of a larger identifier (e.g., in a string or comment), the rewrite could erroneously modify unrelated text.
r2-p002fix okInline comment after noqaThe rewrite may remove or reorder inline comments that appear after the noqa directive on the same line, changing documentation or intent.
r2-p003fix okKeyword-only and positional-only argskeyword-only, positional-only, *args/**kwargs forwarding, defaults evaluated once
r2-p004fix okRuntime type annotation evaluationtype annotations evaluated at runtime, typing-only imports
r2-p005fix okFloat coercion and roundingint/float/bool coercion, Decimal, division and rounding
r2-p006silent prediction offMutable default argument aliasingmutable default arguments and aliasing after a rewrite
r2-p007silent prediction offHash inside brackets mistaken for commentIf the line contains a '#' character inside brackets or quotes (e.g., in a list or regex), the rewrite may mismatch the actual noqa directive due to incorrect comment detection.
r2-p008fix okBytes vs str encodingbytes vs str, encoding and newline handling, text vs binary modes

Sources

r1-p001 · Class attribute descriptor interaction
1class C:
2 x = eval('1') # noqa: PGH001
3 def __init__(self):
4 self.y = self.x + 1
5c = C()
6print(c.y)
--- orig.py	2026-10-17 17:50:01.328899933 -0400
+++ fixed.py	2026-10-17 17:50:01.617945167 -0400
@@ -1,5 +1,5 @@
 class C:
-    x = eval('1')  # noqa: PGH001
+    x = eval('1')  # noqa: S307
     def __init__(self):
         self.y = self.x + 1
 c = C()
2
r1-p002 · Non-UTF-8 encoding corruption
1# -*- coding: latin-1 -*-
2x = eval('\xe9') # noqa: PGH001
3print(x)
--- orig.py	2026-10-17 17:50:01.722961602 -0400
+++ fixed.py	2026-10-17 17:50:02.109021993 -0400
@@ -1,3 +1,3 @@
 # -*- coding: latin-1 -*-
-x = eval('\xe9')  # noqa: PGH001
+x = eval('\xe9')  # noqa: S307
 print(x)
r1-p003 · Trailing whitespace preservation
1x = eval('2') # noqa: PGH001
2print(x)
--- orig.py	2026-10-17 17:50:02.315054187 -0400
+++ fixed.py	2026-10-17 17:50:02.481080130 -0400
@@ -1,2 +1,2 @@
-x = eval('2')  # noqa: PGH001   
+x = eval('2')  # noqa: S307   
 print(x)
2
r1-p004 · Dict ordering and duplicate keys
1d = {}
2d[eval('1')] = 'a' # noqa: PGH001
3d[eval('1')] = 'b'
4print(d)
--- orig.py	2026-10-17 17:50:02.580095602 -0400
+++ fixed.py	2026-10-17 17:50:02.743121075 -0400
@@ -1,4 +1,4 @@
 d = {}
-d[eval('1')] = 'a'  # noqa: PGH001
+d[eval('1')] = 'a'  # noqa: S307
 d[eval('1')] = 'b'
 print(d)
{1: 'b'}
r1-p005 · Trailing comma merging noqa codes
1x = eval('3'), # noqa: PGH001,
2print(x[0])
--- orig.py	2026-10-17 17:50:02.843136703 -0400
+++ fixed.py	2026-10-17 17:50:03.005162020 -0400
@@ -1,2 +1,2 @@
-x = eval('3'),  # noqa: PGH001,
+x = eval('3'),  # noqa: S307,
 print(x[0])
3
r1-p006 · Walrus and late binding in closures (generated program does not parse: Traceback (most recent call last):)
1fs = []
2for i in range(2):
3 if (x := eval(str(i))) # noqa: PGH001
4 fs.append(lambda: x)
5print([f() for f in fs])
r1-p007 · Shadowed builtins and redefinition
1eval = lambda s: 99
2x = eval('1') # noqa: PGH001
3print(x)
4eval = __builtins__.eval
5print(eval('2'))
--- orig.py	2026-10-17 17:50:03.236198066 -0400
+++ fixed.py	2026-10-17 17:50:03.396223032 -0400
@@ -1,5 +1,5 @@
 eval = lambda s: 99
-x = eval('1')  # noqa: PGH001
+x = eval('1')  # noqa: S307
 print(x)
 eval = __builtins__.eval
 print(eval('2'))
99
2
r1-p008 · Exceptions in finally/else clauses
1try:
2 x = eval('1/0') # noqa: PGH001
3except ZeroDivisionError as e:
4 print('caught:', e)
5else:
6 print('no error')
7finally:
8 print('finally')
--- orig.py	2026-10-17 17:50:03.502239572 -0400
+++ fixed.py	2026-10-17 17:50:03.656263603 -0400
@@ -1,5 +1,5 @@
 try:
-    x = eval('1/0')  # noqa: PGH001
+    x = eval('1/0')  # noqa: S307
 except ZeroDivisionError as e:
     print('caught:', e)
 else:
caught: division by zero
finally
r2-p001 · Deprecated code in string literal (generated program does not parse: Traceback (most recent call last):)
1import sys
2# Test: does rewrite touch 'PGH001' inside a string?
3s = '\\'eval(cmd)\\' # noqa: PGH001
4print(repr(s))
5if s == "'eval(cmd)'":
6 print('PASS: string unchanged')
7else:
8 print('FAIL: string altered:', repr(s))
r2-p002 · Inline comment after noqa
1# Check if trailing comment survives rewrite
2result = eval('1+1') # noqa: PGH001 # this comment explains why we allow eval
3print(result)
4print('# this comment explains why we allow eval' in open(__file__).readlines()[1])
--- orig.py	2026-10-17 17:50:08.350993254 -0400
+++ fixed.py	2026-10-17 17:50:08.510017876 -0400
@@ -1,4 +1,4 @@
 # Check if trailing comment survives rewrite
-result = eval('1+1')  # noqa: PGH001  # this comment explains why we allow eval
+result = eval('1+1')  # noqa: S307  # this comment explains why we allow eval
 print(result)
 print('# this comment explains why we allow eval' in open(__file__).readlines()[1])
2
True
r2-p003 · Keyword-only and positional-only args
1def f(a, /, b, *, c=eval('1')): # noqa: PGH001
2 return a + b + c
3print(f(10, 20))
4try:
5 f(10, b=20)
6except TypeError as e:
7 print('Expected:', e)
--- orig.py	2026-10-17 17:50:08.611033515 -0400
+++ fixed.py	2026-10-17 17:50:08.774058756 -0400
@@ -1,4 +1,4 @@
-def f(a, /, b, *, c=eval('1')):  # noqa: PGH001
+def f(a, /, b, *, c=eval('1')):  # noqa: S307
     return a + b + c
 print(f(10, 20))
 try:
31
r2-p004 · Runtime type annotation evaluation
1T = eval('int') # noqa: PGH001
2def g(x: T) -> T:
3 return x + 1
4print(g(5))
5print(T)
--- orig.py	2026-10-17 17:50:08.876074550 -0400
+++ fixed.py	2026-10-17 17:50:09.038099627 -0400
@@ -1,4 +1,4 @@
-T = eval('int')  # noqa: PGH001
+T = eval('int')  # noqa: S307
 def g(x: T) -> T:
     return x + 1
 print(g(5))
6
<class 'int'>
r2-p005 · Float coercion and rounding
1from decimal import Decimal
2x = Decimal(eval('10')) / Decimal('3') # noqa: PGH001
3print(round(x, 2))
4print(float(x))
5print(bool(x))
--- orig.py	2026-10-17 17:50:09.142115707 -0400
+++ fixed.py	2026-10-17 17:50:09.308141373 -0400
@@ -1,5 +1,5 @@
 from decimal import Decimal
-x = Decimal(eval('10')) / Decimal('3')  # noqa: PGH001
+x = Decimal(eval('10')) / Decimal('3')  # noqa: S307
 print(round(x, 2))
 print(float(x))
 print(bool(x))
3.33
3.3333333333333335
True
r2-p006 · Mutable default argument aliasing
1def append_val(val, lst=[]): # noqa: RET503
2 lst.append(val)
3 return lst
4print(append_val(1))
5print(append_val(2))
6print(append_val(3))
[1]
[1, 2]
[1, 2, 3]
r2-p007 · Hash inside brackets mistaken for comment
1import re
2pattern = ['a#b', 'c#d'] # noqa: SIM103
3match = re.search(r'#', str(pattern))
4print('Found #' in str(pattern) if match else 'No # found')
5print(pattern)
False
['a#b', 'c#d']
r2-p008 · Bytes vs str encoding
1data = eval('"hello"').encode() # noqa: PGH001
2with open('test.bin', 'wb') as f:
3 f.write(data)
4with open('test.bin', 'rb') as f:
5 read = f.read()
6print(read == b'hello')
7import os
8os.remove('test.bin')
--- orig.py	2026-10-17 17:50:09.683199352 -0400
+++ fixed.py	2026-10-17 17:50:09.841223781 -0400
@@ -1,4 +1,4 @@
-data = eval('"hello"').encode()  # noqa: PGH001
+data = eval('"hello"').encode()  # noqa: S307
 with open('test.bin', 'wb') as f:
     f.write(data)
 with open('test.bin', 'rb') as f:
True