fixhunt

ruff UP018

labelled unknown
Runs / 2026-10-17T21-17-21-549Z-ajve-ruff-UP018ruff 0.17.12026-10-17 21:17 UTC8 programs × 2 round(s)16 programs, 7 fired, 7 fixed, 1 findings, 0 rejectedmodel cost $0.02

Analysis Nemotron 3 Super

Flags redundant constructor calls like str(x), bytes(b), int(n), float(f), bool(v), complex(c) where x is already of the target type.

Fix: Replace the constructor call with its literal equivalent: e.g., str(s) → s when s is a string literal, bytes(b) → b when b is a bytes literal, etc.

12 hazards
  • Rewriting str(expr) to expr changes behavior if expr has side effects (e.g., str(print("x")) vs print("x"))
  • Rewriting bytes(expr) to expr alters evaluation if expr is a function call with side effects
  • Rewriting int(expr) to expr fails if expr is a float (e.g., int(3.9) → 3.9 changes value and type)
  • Rewriting float(expr) to expr breaks if expr is an integer string (e.g., float("4") → "4" raises TypeError in numeric contexts)
  • Rewriting bool(expr) to expr changes truthiness semantics (e.g., bool([]) → [] is falsy but not equivalent in explicit bool checks)
  • Rewriting complex(expr) to expr fails if expr is a real number (e.g., complex(5) → 5 loses imaginary part and changes type)
  • The fix may drop inline comments attached to the constructor call (e.g., str("hi") # comment → "hi" # comment becomes detached or lost)
  • If the constructor name is shadowed locally (e.g., str = lambda x: x; str("a")), the rewrite to "a" ignores the custom behavior
  • In eval or exec contexts, replacing str(...) with its argument may alter namespace resolution if the argument is a variable
  • The rewrite is invalid if the argument is a tuple needing parentheses for disambiguation (e.g., str((1,2)) → (1,2) is fine, but str(1,2) is a syntax error so not fired)
  • If the constructor is used as a callable in higher-order code (e.g., map(str, [...]))
  • Rewriting may interfere with debugging or profiling tools that rely on constructor call sites

Findings

programoraclelabeljudgestatussummary
r1-p003fix-changes-behaviorlabelled safereal · mediumno matchThe rule rewrites the string literal 'int(5)' inside a type annotation to '5', changing the annotation's stored value from 'int(5)' to '5'. Since annotations a…

Programs

idresulttitlehazard
r1-p001silent prediction offcomplex_reduction_loses_imaginary_partRewriting complex(expr) to expr fails if expr is a real number because it discards the imaginary part and changes the type from complex to int/float.
r1-p002fix okbytes_str_mode_mismatchRewriting bytes(b'data') to b'data' interacts with I/O mode; writing bytes to a text-mode file raises TypeError while str would encode implicitly.
r1-p003fix-changes-behaviortype_annotation_runtime_evalRewriting int(5) to 5 removes a constructor call that might be used in a forward reference or string annotation evaluated at runtime via typing.get_type_hints().
r1-p004silentstar_import_side_effects_allRewriting bool(True) to True affects module-level execution under star imports if the constructor call had side effects (though bool doesn't, we simulate via a wrapper that logs).
r1-p005fix okdict_ordering_duplicate_keysRewriting float(3.14) to 3.14 changes nothing for value, but if used in a dict key construction during comprehension, order and deduplication could be affected by evaluation timing.
r1-p006fix okcomments_docstrings_attachedRemoving str('hello') also removes any inline comment or docstring attached to that line, which may be relied upon by tools or documentation.
r1-p007fix okstring_formatting_edge_casesRewriting repr vs str matters: str(42) vs repr(42) are same for int, but for str, str('"hi"') vs repr('"hi"') differ in quotes.
r1-p008silent prediction offdebugging_profiler_call_sitesRewriting complex(1+2j) to (1+2j) removes a call site that profilers or debuggers might break on or trace; line numbers shift.
r2-p001fix okstar_imports_sideeffects_all_hazardstar-imports, module-level side effects, __all__
r2-p002silentbool_truthiness_semantics_hazardRewriting bool(expr) to expr changes truthiness semantics (e.g., bool([]) → [] is falsy but not equivalent in explicit bool checks)
r2-p003silent prediction offstr_sideeffects_hazardRewriting str(expr) to expr changes behavior if expr has side effects (e.g., str(print("x")) vs print("x"))
r2-p004silent prediction offeval_order_sideeffects_merge_hazardevaluation order and side effects when expressions are merged, duplicated or deleted
r2-p005silent prediction offeval_exec_namespace_resolution_hazardIn eval or exec contexts, replacing str(...) with its argument may alter namespace resolution if the argument is a variable
r2-p006silent prediction offmutable_default_args_aliasing_hazardmutable default arguments and aliasing after a rewrite
r2-p007silent prediction offint_float_truncation_hazardRewriting int(expr) to expr fails if expr is a float (e.g., int(3.9) → 3.9 changes value and type)
r2-p008fix okcomments_docstrings_attached_hazardcomments and docstrings attached to the removed or moved code

Sources

r1-p001 · complex_reduction_loses_imaginary_part
1def f():
2 z = complex(5)
3 return z.real, z.imag
4print(f())
(5.0, 0.0)
r1-p002 · bytes_str_mode_mismatch
1with open('test.bin', 'wb') as f:
2 f.write(bytes(b'hello\n'))
3with open('test.bin', 'rb') as f:
4 print(f.read())
--- orig.py	2026-10-17 17:17:29.275647485 -0400
+++ fixed.py	2026-10-17 17:17:29.439637653 -0400
@@ -1,4 +1,4 @@
 with open('test.bin', 'wb') as f:
-    f.write(bytes(b'hello\n'))
+    f.write(b'hello\n')
 with open('test.bin', 'rb') as f:
     print(f.read())
b'hello\n'
r1-p003 · type_annotation_runtime_eval
1from __future__ import annotations
2def f(x: 'int(5)'):
3 return x
4print(f.__annotations__['x'])
--- orig.py	2026-10-17 17:17:29.537631778 -0400
+++ fixed.py	2026-10-17 17:17:29.697622187 -0400
@@ -1,4 +1,4 @@
 from __future__ import annotations
-def f(x: 'int(5)'):
+def f(x: '5'):
     return x
 print(f.__annotations__['x'])
'int(5)'
r1-p004 · star_import_side_effects_all
1LOG = []
2def bool(x):
3 LOG.append(('bool', x))
4 return __builtins__.bool(x)
5print(bool(True))
6print(LOG)
True
[('bool', True)]
r1-p005 · dict_ordering_duplicate_keys
1keys = [float(3.14), float(3.14)]
2d = {k: None for k in keys}
3print(list(d.keys()))
--- orig.py	2026-10-17 17:17:29.929608279 -0400
+++ fixed.py	2026-10-17 17:17:30.107597620 -0400
@@ -1,3 +1,3 @@
-keys = [float(3.14), float(3.14)]
+keys = [3.14, 3.14]
 d = {k: None for k in keys}
 print(list(d.keys()))
[3.14]
r1-p006 · comments_docstrings_attached
1msg = str('hello') # This is a greeting
2print(msg)
--- orig.py	2026-10-17 17:17:30.212591337 -0400
+++ fixed.py	2026-10-17 17:17:30.373581703 -0400
@@ -1,2 +1,2 @@
-msg = str('hello')  # This is a greeting
+msg = 'hello'  # This is a greeting
 print(msg)
hello
r1-p007 · string_formatting_edge_cases
1s = str('"hi"')
2print(repr(s))
3print(s)
--- orig.py	2026-10-17 17:17:30.475575599 -0400
+++ fixed.py	2026-10-17 17:17:30.640565725 -0400
@@ -1,3 +1,3 @@
-s = str('"hi"')
+s = '"hi"'
 print(repr(s))
 print(s)
'"hi"'
"hi"
r1-p008 · debugging_profiler_call_sites
1import traceback
2def g():
3 return complex(1+2j)
4def f():
5 return g()
6try:
7 raise ValueError
8except:
9 tb = traceback.format_exc()
10 print('complex' in tb)
False
r2-p001 · star_imports_sideeffects_all_hazard
1__all__ = ['value']
2value = str('hello') # This is the exported value
3def get_value():
4 return value
5print(get_value())
--- orig.py	2026-10-17 17:18:04.515599907 -0400
+++ fixed.py	2026-10-17 17:18:04.680590622 -0400
@@ -1,5 +1,5 @@
 __all__ = ['value']
-value = str('hello')  # This is the exported value
+value = 'hello'  # This is the exported value
 def get_value():
     return value
 print(get_value())
hello
r2-p002 · bool_truthiness_semantics_hazard
1lst = []
2if bool(lst):
3 print('truthy')
4else:
5 print('falsy')
6if lst: # same as bool(lst) but different identity
7 print('list truthy')
8else:
9 print('list falsy')
falsy
list falsy
r2-p003 · str_sideeffects_hazard
1def f():
2 print('side effect')
3 return 'ok'
4result = str(f())
5print('result:', result)
side effect
result: ok
r2-p004 · eval_order_sideeffects_merge_hazard
1i = 0
2def inc():
3 global i
4 i += 1
5 return i
6vals = [str(inc()), str(inc())]
7print('vals:', vals, 'i:', i)
vals: ['1', '2'] i: 2
r2-p005 · eval_exec_namespace_resolution_hazard
1x = 'hidden'
2def test():
3 x = 'local'
4 return str(x)
5print(test())
6exec('print(str(x))') # uses global x
local
hidden
r2-p006 · mutable_default_args_aliasing_hazard
1def append_to(val, lst=str([])): # rule triggers here
2 lst.append(val)
3 return lst
4print(append_to(1))
5print(append_to(2))
r2-p007 · int_float_truncation_hazard
1f = 3.9
2n = int(f)
3print(f'int({f}) = {n}, type: {type(n)}')
4if n == f:
5 print('equal')
6else:
7 print('not equal')
int(3.9) = 3, type: <class 'int'>
not equal
r2-p008 · comments_docstrings_attached_hazard
1def process_data():
2 """Process input data.
3 This function uses str('ready') to signal readiness.
4 """
5 status = str('ready') # ready signal
6 return status
--- orig.py	2026-10-17 17:18:05.790528239 -0400
+++ fixed.py	2026-10-17 17:18:05.950519252 -0400
@@ -2,5 +2,5 @@
     """Process input data.
     This function uses str('ready') to signal readiness.
     """
-    status = str('ready')  # ready signal
+    status = 'ready'  # ready signal
     return status