ruff RUF046
labelled unknown
Analysis Nemotron 3 Super
Flags redundant int() casts around expressions that are already guaranteed to be integers.
Fix: Removes the outer int() call, leaving only the inner expression unchanged.
10 hazards
- Rewriting int(len(x)) to len(x) changes behavior if len(x) returns a non-integer type like a custom class with __len__ returning float, breaking type expectations.
- Rewriting int(abs(y)) to abs(y) is unsafe if abs(y) returns a non-integer (e.g., Decimal or Fraction), altering numeric type and downstream operations.
- Rewriting int(True) to True changes the type from int to bool, which may break isinstance(x, int) checks or arithmetic relying on int subclass behavior.
- Rewriting int(False) to False similarly changes type from int to bool, potentially breaking logic that distinguishes 0 from False via type.
- Rewriting int(__import__('sys').maxsize) to __import__('sys').maxsize is unsafe if the import has side effects or if the attribute lookup is expected to occur in a different context due to refactoring.
- Rewriting int(5 + 3) to 5 + 3 is generally safe but may affect code relying on the explicit int conversion for documentation or type assertion purposes, though no semantic change occurs in standard integers.
- Rewriting int(round(z)) to round(z) is unsafe if z defines __round__ returning a non-integer (e.g., float), as the int() cast would have truncated it to int, but removing it leaves a float, changing value and type.
- Rewriting int(math.floor(w)) to math.floor(w) is unsafe if w defines __floor__ returning a non-integer (e.g., np.float64), as math.floor(w) would return that type, but the original int() cast forced it to int, altering subsequent integer-dependent operations.
- The fix may disrupt formatting-dependent tools or linters that expect the int() call to be present for style consistency, even if semantically equivalent in simple cases.
- If the int() call appears in a larger expression like int(f()) + 1, removing it could alter evaluation order if f() has side effects and the surrounding code relies on left-to-right execution, though pure expression replacement preserves order — hazard arises only if the fix is incorrectly applied to non-isolated calls.
Findings
| program | oracle | label | judge | status | summary |
|---|---|---|---|---|---|
| r1-p005 | fix-changes-behavior | labelled safe | introspection-only · low | related | The fix removes the redundant `int()` call from the lambda's source code, which changes the text returned by `inspect.getsource`. This is purely a source-code … |
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fix ok | Generators vs Lists | Rewriting int(len(x)) when x is a generator consumes it, breaking subsequent use; list preserves it. |
| r1-p002 | silent prediction off | Bool Subtype Hazard | Rewriting int(True) to True changes type from int to bool, breaking isinstance checks expecting int. |
| r1-p003 | silent prediction off | Import Side Effect | Rewriting int(__import__('sys').maxsize) assumes import is pure; but module init may have side effects expected to occur once. |
| r1-p004 | fired, no fix | Round Returns Float | Rewriting int(round(z)) to round(z) is unsafe if __round__ returns float; int() truncates, removing it leaves float. |
| r1-p005 | fix-changes-behavior | Formatting Tool Dependency | Rewriting int(5+3) may break formatters that rely on the int() call for alignment or style metrics, even if value unchanged. |
| r1-p006 | fix ok prediction off | Descriptor Side Effects | Rewriting int(getattr(obj, 'x', 0)) is silent, but if getattr triggers a descriptor with side effects, removing int() doesn't remove those — yet the rule doesn't fire here. Instead, we show a case whe |
| r1-p007 | fix ok | Context Manager Write Only | Rewriting int(len(context_manager)) is nonsensical, but we show a case where int() fires on len() of a list that was meant to be managed, and removing int() doesn't affect cm — but we use a context ma |
| r1-p008 | fix ok prediction off | Pathlib vs os.path | Rewriting int(len(path)) where path is a pathlib.Path or os.path string; but len() behaves same. Instead, we show int() on a path operation that returns int-like but is not, e.g., Path.stat().st_size |
| r2-p001 | fix ok | Documentation intent via int() on literal sum | Rewriting int(5 + 3) to 5 + 3 is generally safe but may affect code relying on the explicit int conversion for documentation or type assertion purposes. |
| r2-p002 | fix ok | String formatting with % operator and int() | string formatting edge cases: %, format, f-strings, repr vs str, nested quotes |
| r2-p003 | fix ok | Dict ordering with duplicate keys and hash | dict ordering, duplicate keys, __hash__/__eq__ overrides, sets |
| r2-p004 | silent prediction off | Evaluation order with side effects in argument | evaluation order and side effects when expressions are merged, duplicated or deleted |
| r2-p005 | fix ok | Generator consumed by len() in int() | generators vs lists, iterators consumed once, lazy vs eager evaluation |
| r2-p006 | silent | Mutable default argument and aliasing | mutable default arguments and aliasing after a rewrite |
| r2-p007 | fired, no fix | Unsafe removal of int() around round() with float return | Rewriting int(round(z)) to round(z) is unsafe if z defines __round__ returning a non-integer (e.g., float), as the int() cast would have truncated it to int, but removing it leaves a float, changing v |
| r2-p008 | silent prediction off | int() in larger expression with side effect | If the int() call appears in a larger expression like int(f()) + 1, removing it could alter evaluation order if f() has side effects and the surrounding code relies on left-to-right execution, though |
Sources
r1-p001 · Generators vs Lists
1def f():
2 yield 1
3 yield 2
4
5g = f()
6lst = list(f())
7a = int(len(g))
8b = len(g)
9c = int(len(lst))
10d = len(lst)
11print('gen len after int:', a, 'remaining:', b)
12print('list len after int:', c, 'remaining:', d)
--- orig.py 2026-10-17 17:45:33.447897457 -0400 +++ fixed.py 2026-10-17 17:45:33.836894952 -0400 @@ -4,9 +4,9 @@ g = f() lst = list(f()) -a = int(len(g)) +a = len(g) b = len(g) -c = int(len(lst)) +c = len(lst) d = len(lst) print('gen len after int:', a, 'remaining:', b) print('list len after int:', c, 'remaining:', d)
r1-p002 · Bool Subtype Hazard
1def check_int(x):
2 return isinstance(x, int) and not isinstance(x, bool)
3
4v = int(True)
5print('int(True) is int?', isinstance(v, int))
6print('int(True) passes check_int?', check_int(v))
7print('type(int(True)):', type(v))
int(True) is int? True int(True) passes check_int? True type(int(True)): <class 'int'>
r1-p003 · Import Side Effect
1import sys
2counter = [0]
3orig_import = __import__
4def side_effect_import(name, *args, **kwargs):
5 if name == 'sys':
6 counter[0] += 1
7 return orig_import(name, *args, **kwargs)
8
9# Temporarily replace __import__ to observe side effects
10builtins = __import__('builtins')
11builtins.__import__ = side_effect_import
12try:
13 v = int(__import__('sys').maxsize)
14 print('sys imported', counter[0], 'times')
15 print('value:', v)
16except Exception as e:
17 print('error:', type(e).__name__, str(e))
18finally:
19 builtins.__import__ = orig_import
sys imported 1 times value: 9223372036854775807
r1-p004 · Round Returns Float
1class FloatRound:
2 def __round__(self, ndigits=0):
3 return 3.14
4
5z = FloatRound()
6v = int(round(z))
7print('int(round(z)):', v, type(v))
8# After fix: round(z) -> 3.14 (float)
9# So we simulate by showing what round(z) gives
10print('round(z):', round(z), type(round(z)))
int(round(z)): 3 <class 'int'> round(z): 3.14 <class 'float'>
r1-p005 · Formatting Tool Dependency
1# This line's length affects flake8 or black line length scoring
2val = int(5 + 3) # kept for formatting
3print('Value:', val)
4# If removed: 'val = 5 + 3' is shorter; tools may reformat differently
5# We show the line length as proxy
6import inspect
7import textwrap
8src = inspect.getsource(lambda: int(5 + 3))
9print('Source length of int(5+3):', len(src.strip()))
--- orig.py 2026-10-17 17:45:34.478890819 -0400 +++ fixed.py 2026-10-17 17:45:34.693889435 -0400 @@ -1,9 +1,9 @@ # This line's length affects flake8 or black line length scoring -val = int(5 + 3) # kept for formatting +val = 5 + 3 # kept for formatting print('Value:', val) # If removed: 'val = 5 + 3' is shorter; tools may reformat differently # We show the line length as proxy import inspect import textwrap -src = inspect.getsource(lambda: int(5 + 3)) +src = inspect.getsource(lambda: (5 + 3)) print('Source length of int(5+3):', len(src.strip()))
Value: 8 Source length of int(5+3): 43
r1-p006 · Descriptor Side Effects
1class Descriptor:
2 def __get__(self, obj, objtype):
3 print('Descriptor accessed')
4 return 42
5
6class Obj:
7 x = Descriptor()
8
9o = Obj()
10# Rule does NOT fire on getattr because argument not plain int-compatible
11# But we show a firing case with side effects in argument: len([descr access])
12def get_list():
13 print('get_list called')
14 return [o.x] # accessing descriptor
15
16try:
17 v = int(len(get_list()))
18 print('Result:', v)
19except Exception as e:
20 print('Error:', type(e).__name__, str(e))
--- orig.py 2026-10-17 17:45:34.814888657 -0400 +++ fixed.py 2026-10-17 17:45:34.984887563 -0400 @@ -14,7 +14,7 @@ return [o.x] # accessing descriptor try: - v = int(len(get_list())) + v = len(get_list()) print('Result:', v) except Exception as e: print('Error:', type(e).__name__, str(e))
get_list called Descriptor accessed Result: 1
r1-p007 · Context Manager Write Only
1class ListManager:
2 def __enter__(self):
3 self.data = [1, 2, 3]
4 return self.data
5 def __exit__(self, *exc):
6 pass
7
8with ListManager() as lm:
9 a = int(len(lm))
10 b = len(lm)
11 print('int(len(lm)):', a, 'type:', type(a))
12 print('len(lm):', b, 'type:', type(b))
13# After fix: a = len(lm) -> same value, but type int either way
14# So we show that without int(), if someone expects bool from non-zero? No.
15# Instead: show that the value is used in a context where type matters
16print('a is int:', isinstance(a, int))
17print('b is int:', isinstance(b, int))
--- orig.py 2026-10-17 17:45:35.078886958 -0400 +++ fixed.py 2026-10-17 17:45:35.247885871 -0400 @@ -6,7 +6,7 @@ pass with ListManager() as lm: - a = int(len(lm)) + a = len(lm) b = len(lm) print('int(len(lm)):', a, 'type:', type(a)) print('len(lm):', b, 'type:', type(b))
int(len(lm)): 3 type: <class 'int'> len(lm): 3 type: <class 'int'> a is int: True b is int: True
r1-p008 · Pathlib vs os.path
1import os
2import pathlib
3# Create a temporary file
4with open('test.txt', 'w') as f:
5 f.write('hello')
6
7# Rule fires on int(len(...)) if we use len on something that is not plain int-compatible? No.
8# Instead, we show int() on a path-derived int that is safe, but we use it in a loop
9for i in range(2):
10 if i == 0:
11 l = int(len(os.path.abspath('test.txt')))
12 else:
13 l = int(len(str(pathlib.Path('test.txt').resolve())))
14 print(f'Iter {i}: length = {l}')
15
16# Cleanup
17os.remove('test.txt')
--- orig.py 2026-10-17 17:45:35.345885241 -0400 +++ fixed.py 2026-10-17 17:45:35.544883961 -0400 @@ -8,9 +8,9 @@ # Instead, we show int() on a path-derived int that is safe, but we use it in a loop for i in range(2): if i == 0: - l = int(len(os.path.abspath('test.txt'))) + l = len(os.path.abspath('test.txt')) else: - l = int(len(str(pathlib.Path('test.txt').resolve()))) + l = len(str(pathlib.Path('test.txt').resolve())) print(f'Iter {i}: length = {l}') # Cleanup
Iter 0: length = 86 Iter 1: length = 86
r2-p001 · Documentation intent via int() on literal sum
1def get_value():
2 return int(5 + 3)
3
4print(get_value(), type(get_value()))
--- orig.py 2026-10-17 17:45:39.971855526 -0400 +++ fixed.py 2026-10-17 17:45:40.132854494 -0400 @@ -1,4 +1,4 @@ def get_value(): - return int(5 + 3) + return 5 + 3 print(get_value(), type(get_value()))
8 <class 'int'>
r2-p002 · String formatting with % operator and int()
1x = 42
2result = '%d' % int(5 + 3)
3print(result)
--- orig.py 2026-10-17 17:45:40.239853808 -0400 +++ fixed.py 2026-10-17 17:45:40.395852807 -0400 @@ -1,3 +1,3 @@ x = 42 -result = '%d' % int(5 + 3) +result = '%d' % (5 + 3) print(result)
8
r2-p003 · Dict ordering with duplicate keys and hash
1class BadHash:
2 def __init__(self, v): self.v = v
3 def __hash__(self): return int(5 + 3)
4 def __eq__(self, other): return self.v == other.v
5
6d = {BadHash(1): 'a', BadHash(2): 'b'}
7print(len(d))
--- orig.py 2026-10-17 17:45:40.500852134 -0400 +++ fixed.py 2026-10-17 17:45:40.658851121 -0400 @@ -1,6 +1,6 @@ class BadHash: def __init__(self, v): self.v = v - def __hash__(self): return int(5 + 3) + def __hash__(self): return 5 + 3 def __eq__(self, other): return self.v == other.v d = {BadHash(1): 'a', BadHash(2): 'b'}
2
r2-p004 · Evaluation order with side effects in argument
1counter = 0
2
3def side_effect():
4 global counter
5 counter += 1
6 return 5
7
8print(int(side_effect() + 3), counter)
8 1
r2-p005 · Generator consumed by len() in int()
1def gen():
2 yield 1
3 yield 2
4 yield 3
5
6g = gen()
7print(int(len(list(g))))
8print(list(g))
--- orig.py 2026-10-17 17:45:40.888849646 -0400 +++ fixed.py 2026-10-17 17:45:41.050848608 -0400 @@ -4,5 +4,5 @@ yield 3 g = gen() -print(int(len(list(g)))) +print(len(list(g))) print(list(g))
3 []
r2-p006 · Mutable default argument and aliasing
1def f(x=[]):
2 x.append(1)
3 return len(x)
4
5print(f())
6print(f())
1 2
r2-p007 · Unsafe removal of int() around round() with float return
1class FloatRound:
2 def __round__(self, ndigits):
3 return 3.5
4
5z = FloatRound()
6print(int(round(z)), type(int(round(z))))
7print(round(z), type(round(z)))
r2-p008 · int() in larger expression with side effect
1counter = 0
2
3def f():
4 global counter
5 counter += 1
6 return 5
7
8print(int(f()) + 1, counter)
6 1