fixhunt

ruff PIE808

labelled unknown
Runs / 2026-10-17T20-28-54-276Z-w0t1-ruff-PIE808ruff 0.17.12026-10-17 20:28 UTC8 programs × 2 round(s)16 programs, 13 fired, 13 fixed, 0 findings, 1 rejectedmodel cost $0.0026

Analysis Nemotron 3 Super

Flags range() calls where the start argument is explicitly 0, since it is redundant.

Fix: Removes the first argument when it is exactly 0, transforming range(0, y) into range(y).

1 hazards
  • If 'y' contains a side effect like a function call (e.g., range(0, func())), removing the explicit 0 changes nothing but relies on correct parsing; however, if the expression were misparenthesized, it could alter grouping—though this is unlikely given grammar constraints.

Programs

idresulttitlehazard
r1-p001fix okWalrus Operator Scope Leakwalrus, comprehensions scoping, late binding in closures and lambdas
r1-p002fix okGenerator Exhaustion in Sumgenerators vs lists, iterators consumed once, lazy vs eager evaluation
r1-p003fix okProperty with Side Effect in Default Argclass attributes vs instance attributes, descriptors, properties with side effects
r1-p004fix okFunction Call in Stop ArgumentIf 'y' contains a side effect like a function call (e.g., range(0, func())), removing the explicit 0 changes nothing but relies on correct parsing; however, if the expression were misparenthesized, it
r1-p005fix okMutable Default Argument Capturemutable default arguments and aliasing after a rewrite
r1-p006silent prediction offShadowed Built-in Rangeshadowed builtins and names redefined later in the module
r1-p007fix okKeyword-Only Function with Defaultkeyword-only, positional-only, *args/**kwargs forwarding, defaults evaluated once
r1-p008fix okComment Attached to Rewritten Codecomments and docstrings attached to the removed or moved code
r2-p001silent prediction offShadowed Built-in Rangeshadowed builtins and names redefined later in the module
r2-p002fix okComments on Rewritten Codecomments and docstrings attached to the removed or moved code
r2-p003invalidPathlib vs os.path Behaviorpathlib vs os.path behavior on relative paths, symlinks, missing files, bytes paths
r2-p004fix okWalrus Operator Scope Leakwalrus, comprehensions scoping, late binding in closures and lambdas
r2-p005fix okExceptions in Rewritten Codeexceptions raised inside the rewritten code, finally/else clauses, exception chaining
r2-p006fix okDict Ordering and Hashingdict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r2-p007fix okGenerator Exhaustiongenerators vs lists, iterators consumed once, lazy vs eager evaluation
r2-p008fix okTruthy Custom Objectstruthiness of custom __bool__/__len__, None vs falsy, 'is' vs '=='

Sources

r1-p001 · Walrus Operator Scope Leak
1def make_checker(t):
2 xs = []
3 while (n := t) > 0:
4 xs.append(lambda: [i for i in range(0, n)])
5 t -= 1
6 return xs[0]
7
8f = make_checker(2)
9print(f())
--- orig.py	2026-10-17 16:29:00.516569454 -0400
+++ fixed.py	2026-10-17 16:29:00.685569456 -0400
@@ -1,7 +1,7 @@
 def make_checker(t):
     xs = []
     while (n := t) > 0:
-        xs.append(lambda: [i for i in range(0, n)])
+        xs.append(lambda: [i for i in range(n)])
         t -= 1
     return xs[0]
 
[]
r1-p002 · Generator Exhaustion in Sum
1r = range(0, 3)
2gen = (x*2 for x in r)
3print(sum(gen))
4print(sum(gen)) # exhausted
--- orig.py	2026-10-17 16:29:00.792569457 -0400
+++ fixed.py	2026-10-17 16:29:00.959569459 -0400
@@ -1,4 +1,4 @@
-r = range(0, 3)
+r = range(3)
 gen = (x*2 for x in r)
 print(sum(gen))
 print(sum(gen))  # exhausted
6
0
r1-p003 · Property with Side Effect in Default Arg
1class Counter:
2 count = 0
3 @property
4 def value(self):
5 self.count += 1
6 return self.count
7
8c = Counter()
9def f(r=range(0, c.value)):
10 return list(r)
11
12print(f())
13print(f())
--- orig.py	2026-10-17 16:29:01.060569461 -0400
+++ fixed.py	2026-10-17 16:29:01.224569464 -0400
@@ -6,7 +6,7 @@
         return self.count
 
 c = Counter()
-def f(r=range(0, c.value)):
+def f(r=range(c.value)):
     return list(r)
 
 print(f())
[0]
[0]
r1-p004 · Function Call in Stop Argument
1state = 0
2
3def inc():
4 global state
5 state += 1
6 return state
7
8r = range(0, inc())
9print(list(r))
10r = range(0, inc())
11print(list(r))
--- orig.py	2026-10-17 16:29:01.322569466 -0400
+++ fixed.py	2026-10-17 16:29:01.487569469 -0400
@@ -5,7 +5,7 @@
     state += 1
     return state
 
-r = range(0, inc())
+r = range(inc())
 print(list(r))
-r = range(0, inc())
+r = range(inc())
 print(list(r))
[0]
[0, 1]
r1-p005 · Mutable Default Argument Capture
1def f(x=None, r=range(0, 3)):
2 if x is None:
3 x = []
4 x.extend(r)
5 return x
6
7print(f())
8print(f())
--- orig.py	2026-10-17 16:29:01.588569471 -0400
+++ fixed.py	2026-10-17 16:29:01.755569474 -0400
@@ -1,4 +1,4 @@
-def f(x=None, r=range(0, 3)):
+def f(x=None, r=range(3)):
     if x is None:
         x = []
     x.extend(r)
[0, 1, 2]
[0, 1, 2]
r1-p006 · Shadowed Built-in Range
1range = lambda *a: list(__builtins__.range(*a))
2x = range(0, 2)
3print(x)
4del range
5x = range(0, 2) # now built-in
6print(list(x))
[0, 1]
[0, 1]
r1-p007 · Keyword-Only Function with Default
1def f(*, r=range(0, 2)):
2 return sum(r)
3
4print(f())
5print(f())
--- orig.py	2026-10-17 16:29:01.987569479 -0400
+++ fixed.py	2026-10-17 16:29:02.156569483 -0400
@@ -1,4 +1,4 @@
-def f(*, r=range(0, 2)):
+def f(*, r=range(2)):
     return sum(r)
 
 print(f())
1
1
r1-p008 · Comment Attached to Rewritten Code
1def f():
2 # This loop runs twice
3 for i in range(0, 2): # index
4 print(i)
--- orig.py	2026-10-17 16:29:02.261569486 -0400
+++ fixed.py	2026-10-17 16:29:02.428569491 -0400
@@ -1,4 +1,4 @@
 def f():
     # This loop runs twice
-    for i in range(0, 2):  # index
+    for i in range(2):  # index
         print(i)
r2-p001 · Shadowed Built-in Range
1range = lambda s, e=None: (list(range(s if e is not None else 0, e if e is not None else s)), 'redefined')[1]
2for i in range(0, 3):
3 print(f'i={i}', end=' ')
4print()
5print('done')
r2-p002 · Comments on Rewritten Code
1# This loop uses range(0, n) with a comment
2for i in range(0, 2): # iterates twice
3 print(i)
4# End of loop
--- orig.py	2026-10-17 16:29:08.219569765 -0400
+++ fixed.py	2026-10-17 16:29:08.382569776 -0400
@@ -1,4 +1,4 @@
 # This loop uses range(0, n) with a comment
-for i in range(0, 2):  # iterates twice
+for i in range(2):  # iterates twice
     print(i)
 # End of loop
0
1
r2-p003 · Pathlib vs os.path Behavior (generated program does not parse: Traceback (most recent call last):)
1import os
2try:
3 os.symlink('nonexistent', 'link')
4except FileExistsError:
5 pass
6for i in range(0, 1):
7 p = os.path.exists('link')
8 print(f'exists: {p}')
9 try:
10 with open('link') as f:
11 print(f.read())
12 except Exception as e:
13 print(f'error: {type(e).__name__}: {e}')
14finally:
15 try:
16 os.unlink('link')
17 except:
18 pass
r2-p004 · Walrus Operator Scope Leak
1n = 5
2f = lambda: [j for i in range(0, n) if (j := i) is not None]
3print('Before:', f())
4n = 10
5print('After:', f())
--- orig.py	2026-10-17 16:29:08.620569793 -0400
+++ fixed.py	2026-10-17 16:29:08.782569805 -0400
@@ -1,5 +1,5 @@
 n = 5
-f = lambda: [j for i in range(0, n) if (j := i) is not None]
+f = lambda: [j for i in range(n) if (j := i) is not None]
 print('Before:', f())
 n = 10
 print('After:', f())
Before: [0, 1, 2, 3, 4]
After: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
r2-p005 · Exceptions in Rewritten Code
1def f():
2 try:
3 for i in range(0, 1):
4 raise ValueError('bad')
5 except ValueError as e:
6 print(f'caught: {e}')
7 else:
8 print('no ex')
9 finally:
10 print('finally')
11f()
--- orig.py	2026-10-17 16:29:08.882569812 -0400
+++ fixed.py	2026-10-17 16:29:09.046569824 -0400
@@ -1,6 +1,6 @@
 def f():
     try:
-        for i in range(0, 1):
+        for i in range(1):
             raise ValueError('bad')
     except ValueError as e:
         print(f'caught: {e}')
caught: bad
finally
r2-p006 · Dict Ordering and Hashing
1class K:
2 def __init__(self, v): self.v = v
3 def __hash__(self): return hash(self.v)
4 def __eq__(self, other): return self.v == other.v
5 def __repr__(self): return f'K({self.v})'
6d = {}
7for i in range(0, 2):
8 d[K(i)] = i * 10
9print('dict:', d)
10print('keys:', list(d.keys()))
--- orig.py	2026-10-17 16:29:09.144569831 -0400
+++ fixed.py	2026-10-17 16:29:09.308569844 -0400
@@ -4,7 +4,7 @@
     def __eq__(self, other): return self.v == other.v
     def __repr__(self): return f'K({self.v})'
 d = {}
-for i in range(0, 2):
+for i in range(2):
     d[K(i)] = i * 10
 print('dict:', d)
 print('keys:', list(d.keys()))
dict: {K(0): 0, K(1): 10}
keys: [K(0), K(1)]
r2-p007 · Generator Exhaustion
1def gen():
2 for i in range(0, 3):
3 yield i
4 print(f'yielded {i}')
5g = gen()
6print('first sum:', sum(g))
7print('second sum:', sum(g)) # should be 0
--- orig.py	2026-10-17 16:29:09.410569852 -0400
+++ fixed.py	2026-10-17 16:29:09.580569865 -0400
@@ -1,5 +1,5 @@
 def gen():
-    for i in range(0, 3):
+    for i in range(3):
         yield i
         print(f'yielded {i}')
 g = gen()
yielded 0
yielded 1
yielded 2
first sum: 3
second sum: 0
r2-p008 · Truthy Custom Objects
1class T:
2 def __bool__(self): return False
3 def __len__(self): return 0
4 def __repr__(self): return 'T()'
5t = T()
6print(f't bool: {bool(t)}')
7print(f't len: {len(t)}')
8print(f't is None: {t is None}')
9print(f't == None: {t == None}')
10for i in range(0, 1):
11 if t:
12 print('truthy')
13 else:
14 print('falsy')
--- orig.py	2026-10-17 16:29:09.677569873 -0400
+++ fixed.py	2026-10-17 16:29:09.842569886 -0400
@@ -7,7 +7,7 @@
 print(f't len: {len(t)}')
 print(f't is None: {t is None}')
 print(f't == None: {t == None}')
-for i in range(0, 1):
+for i in range(1):
     if t:
         print('truthy')
     else:
t bool: False
t len: 0
t is None: False
t == None: False
falsy