fixhunt

ruff E703

labelled unknown
Runs / 2026-10-17T20-47-32-925Z-77sq-ruff-E703ruff 0.17.12026-10-17 20:47 UTC8 programs × 2 round(s)16 programs, 14 fired, 14 fixed, 0 findings, 2 rejectedmodel cost $0.0025

Analysis Nemotron 3 Super

Flags statements ending with unnecessary semicolons.

Fix: Removes the trailing semicolon at the end of the statement, leaving the preceding code unchanged.

8 hazards
  • Rewriting 'x = 1;' to 'x = 1' changes nothing as the semicolon is purely syntactic and has no semantic effect in simple statements.
  • In compound statements like 'if True: pass;', removing the semicolon after the suite does not alter behavior because the semicolon only terminates the simple statement 'pass'.
  • For 'for i in range(10): print(i);', the semicolon after the loop body is irrelevant to execution and its removal preserves all side effects.
  • In function definitions like 'def f(): return None;', the trailing semicolon after the function body is ignored by the parser and its removal does not affect the function's behavior.
  • For class definitions like 'class C: x = 1;', the semicolon after the class suite is non-functional and deleting it does not alter class creation or attribute binding.
  • In import statements such as 'import os;', the semicolon is redundant and its removal does not affect the import mechanism or module availability.
  • For 'from sys import stdin;', the semicolon after the import statement is extraneous and deleting it preserves the imported name's availability.
  • In try-except blocks like 'try: pass; except: pass;', the semicolons after each suite are meaningless and their removal does not impact exception handling or control flow.

Programs

idresulttitlehazard
r1-p001fix okCompound statement - ifIn compound statements like 'if True: pass;', removing the semicolon after the suite does not alter behavior because the semicolon only terminates the simple statement 'pass'.
r1-p002fix okClass definitionFor class definitions like 'class C: x = 1;', the semicolon after the class suite is non-functional and deleting it does not alter class creation or attribute binding.
r1-p003invalidExceptions/finally/else/chainingexceptions raised inside the rewritten code, finally/else clauses, exception chaining
r1-p004fix okAsync def/await/ordering, async generatorsasync def/await ordering, async generators
r1-p005fix okInt/float/bool coercion, Decimal, division and roundingint/float/bool coercion, Decimal, division and rounding
r1-p006fix okClass vs instance attributes, descriptors, properties with side effectsclass attributes vs instance attributes, descriptors, properties with side effects
r1-p007fix okImport statementsIn import statements such as 'import os;', the semicolon is redundant and its removal does not affect the import mechanism or module availability.
r1-p008fix okMutable default arguments and aliasing after a rewritemutable default arguments and aliasing after a rewrite
r2-p001fix okType annotation evaluated via ForwardRef resolutiontype annotations evaluated at runtime, typing-only imports
r2-p002fix okKeyword-only arg with default evaluated oncekeyword-only, positional-only, *args/**kwargs forwarding, defaults evaluated once
r2-p003fix okFrom import availability after semicolon removalFor 'from sys import stdin;', the semicolon after the import statement is extraneous and deleting it preserves the imported name's availability.
r2-p004fix okFloat division rounding behaviorint/float/bool coercion, Decimal, division and rounding
r2-p005fix okClass attribute binding orderFor class definitions like 'class C: x = 1;', the semicolon after the class suite is non-functional and deleting it does not alter class creation or attribute binding.
r2-p006fix okPathlib vs os.path symlink resolutionpathlib vs os.path behavior on relative paths, symlinks, missing files, bytes paths
r2-p007invalidGenerator exhaustion in loopgenerators vs lists, iterators consumed once, lazy vs eager evaluation
r2-p008fix okFile write truncation with bytesfile modes and truncation, partial writes, non-str data passed to write

Sources

r1-p001 · Compound statement - if
1x = []
2for _ in range(2):
3 if len(x) < 2:
4 x.append(len(x));
5print(x)
--- orig.py	2026-10-17 16:47:40.484134587 -0400
+++ fixed.py	2026-10-17 16:47:40.648138379 -0400
@@ -1,5 +1,5 @@
 x = []
 for _ in range(2):
   if len(x) < 2:
-    x.append(len(x));
+    x.append(len(x))
 print(x)
[0, 1]
r1-p002 · Class definition
1class C:
2 attr = [];
3def f():
4 C.attr.append(1)
5f()
6f()
7print(C.attr)
--- orig.py	2026-10-17 16:47:40.758140921 -0400
+++ fixed.py	2026-10-17 16:47:40.921144689 -0400
@@ -1,5 +1,5 @@
 class C:
-  attr = [];
+  attr = []
 def f():
   C.attr.append(1)
 f()
[1, 1]
r1-p003 · Exceptions/finally/else/chaining (generated program does not parse: Traceback (most recent call last):)
1try:
2 raise ValueError('bad')
3except Exception as e:
4 try:
5 raise TypeError('worse') from e;
6except TypeError as te:
7 print(te.__cause__)
r1-p004 · Async def/await/ordering, async generators
1async def gen():
2 yield 1;
3async def main():
4 async for v in gen():
5 print(v);
6import asyncio
7asyncio.run(main())
--- orig.py	2026-10-17 16:47:41.170150440 -0400
+++ fixed.py	2026-10-17 16:47:41.459157113 -0400
@@ -1,7 +1,7 @@
 async def gen():
-  yield 1;
+  yield 1
 async def main():
   async for v in gen():
-    print(v);
+    print(v)
 import asyncio
 asyncio.run(main())
1
r1-p005 · Int/float/bool coercion, Decimal, division and rounding
1from decimal import Decimal, getcontext
2getcontext().prec = 3
3x = Decimal('1') / Decimal('3');
4print(round(float(x), 2))
--- orig.py	2026-10-17 16:47:41.630161062 -0400
+++ fixed.py	2026-10-17 16:47:41.801165010 -0400
@@ -1,4 +1,4 @@
 from decimal import Decimal, getcontext
 getcontext().prec = 3
-x = Decimal('1') / Decimal('3');
+x = Decimal('1') / Decimal('3')
 print(round(float(x), 2))
0.33
r1-p006 · Class vs instance attributes, descriptors, properties with side effects
1class C:
2 shared = [];
3 @property
4 def log(self):
5 self.shared.append(len(self.shared));
6 return len(self.shared)
7c = C()
8print(c.log);
9print(c.log)
--- orig.py	2026-10-17 16:47:41.905167411 -0400
+++ fixed.py	2026-10-17 16:47:42.067171150 -0400
@@ -1,9 +1,9 @@
 class C:
-  shared = [];
+  shared = []
   @property
   def log(self):
-    self.shared.append(len(self.shared));
+    self.shared.append(len(self.shared))
     return len(self.shared)
 c = C()
-print(c.log);
+print(c.log)
 print(c.log)
1
2
r1-p007 · Import statements
1import os;
2import sys;
3print(hasattr(os, 'path'))
4print(hasattr(sys, 'stdout'))
--- orig.py	2026-10-17 16:47:42.167173456 -0400
+++ fixed.py	2026-10-17 16:47:42.331177238 -0400
@@ -1,4 +1,4 @@
-import os;
-import sys;
+import os
+import sys
 print(hasattr(os, 'path'))
 print(hasattr(sys, 'stdout'))
True
True
r1-p008 · Mutable default arguments and aliasing after a rewrite
1def f(a=[]):
2 a.append(1);
3 return a
4print(f())
5print(f())
--- orig.py	2026-10-17 16:47:42.439179729 -0400
+++ fixed.py	2026-10-17 16:47:42.598183396 -0400
@@ -1,5 +1,5 @@
 def f(a=[]):
-  a.append(1);
+  a.append(1)
   return a
 print(f())
 print(f())
[1]
[1, 1]
r2-p001 · Type annotation evaluated via ForwardRef resolution
1from __future__ import annotations
2T = list
3def f(x: T) -> T:
4 return x
5print(f.__annotations__) # Shows stringized annotation
6f([1]);
--- orig.py	2026-10-17 16:47:47.877304762 -0400
+++ fixed.py	2026-10-17 16:47:48.045308613 -0400
@@ -3,4 +3,4 @@
 def f(x: T) -> T:
   return x
 print(f.__annotations__)  # Shows stringized annotation
-f([1]);
+f([1])
{'x': 'T', 'return': 'T'}
r2-p002 · Keyword-only arg with default evaluated once
1L = []
2def f(*, x=L.append(1) or 0):
3 return x
4print(f(), f()) # Second call sees mutated L
5f();
--- orig.py	2026-10-17 16:47:48.148310972 -0400
+++ fixed.py	2026-10-17 16:47:48.313314751 -0400
@@ -2,4 +2,4 @@
 def f(*, x=L.append(1) or 0):
   return x
 print(f(), f())  # Second call sees mutated L
-f();
+f()
0 0
r2-p003 · From import availability after semicolon removal
1from sys import stdin;
2print(stdin is not None)
3from sys import stdout;
4print(stdout is not None)
--- orig.py	2026-10-17 16:47:48.415317087 -0400
+++ fixed.py	2026-10-17 16:47:48.577320798 -0400
@@ -1,4 +1,4 @@
-from sys import stdin;
+from sys import stdin
 print(stdin is not None)
-from sys import stdout;
+from sys import stdout
 print(stdout is not None)
True
True
r2-p004 · Float division rounding behavior
1x = 1;
2y = 3;
3print(x / y == 0.3333333333333333); # Semicolon on x line
4print(round(x / y, 2))
--- orig.py	2026-10-17 16:47:48.687323317 -0400
+++ fixed.py	2026-10-17 16:47:48.849327027 -0400
@@ -1,4 +1,4 @@
-x = 1;
-y = 3;
-print(x / y == 0.3333333333333333);  # Semicolon on x line
+x = 1
+y = 3
+print(x / y == 0.3333333333333333)  # Semicolon on x line
 print(round(x / y, 2))
True
0.33
r2-p005 · Class attribute binding order
1class C:
2 x = 1;
3 y = x + 1
4print(C.x, C.y)
5print(hasattr(C, 'z')) # z not defined
--- orig.py	2026-10-17 16:47:48.947329272 -0400
+++ fixed.py	2026-10-17 16:47:49.114333094 -0400
@@ -1,5 +1,5 @@
 class C:
-  x = 1;
+  x = 1
   y = x + 1
 print(C.x, C.y)
 print(hasattr(C, 'z'))  # z not defined
1 2
False
r2-p006 · Pathlib vs os.path symlink resolution
1import os
2import pathlib
3open('tmp.txt', 'w').write('hi')
4os.symlink('tmp.txt', 'link')
5print(os.path.exists('link')); # Semicolon on import os line
6print(pathlib.Path('link').exists())
7os.unlink('link'); os.remove('tmp.txt')
--- orig.py	2026-10-17 16:47:49.208335244 -0400
+++ fixed.py	2026-10-17 16:47:49.428340277 -0400
@@ -2,6 +2,6 @@
 import pathlib
 open('tmp.txt', 'w').write('hi')
 os.symlink('tmp.txt', 'link')
-print(os.path.exists('link'));  # Semicolon on import os line
+print(os.path.exists('link'))  # Semicolon on import os line
 print(pathlib.Path('link').exists())
 os.unlink('link'); os.remove('tmp.txt')
True
True
r2-p007 · Generator exhaustion in loop (generated program does not parse: Traceback (most recent call last):)
1def gen():
2 yield 1
3 yield 2
4 g = gen();
5print(list(g)); # Semicolon on g = gen() line
6print(list(g)) # Now empty
r2-p008 · File write truncation with bytes
1with open('test.bin', 'wb') as f:
2 f.write(b'hello'); # Semicolon on write line
3 f.truncate(2)
4with open('test.bin', 'rb') as f:
5 print(f.read())
6import os
7os.remove('test.bin')
--- orig.py	2026-10-17 16:47:49.699346477 -0400
+++ fixed.py	2026-10-17 16:47:49.866350298 -0400
@@ -1,5 +1,5 @@
 with open('test.bin', 'wb') as f:
-  f.write(b'hello');  # Semicolon on write line
+  f.write(b'hello')  # Semicolon on write line
   f.truncate(2)
 with open('test.bin', 'rb') as f:
   print(f.read())
b'he'