fixhunt

ruff RUF077

labelled unknown
Runs / 2026-10-17T21-49-19-402Z-mkpr-ruff-RUF077ruff 0.17.12026-10-17 21:49 UTC8 programs × 2 round(s)16 programs, 8 fired, 0 fixed, 0 findings, 3 rejectedmodel cost $0.0030

Analysis Nemotron 3 Super

Flags methods where the first parameter (receiver) has a default value.

Fix: Removes the default value expression from the receiver parameter (the first parameter of the method definition).

12 hazards
  • If the method is called directly via the class (e.g., C.m()) without providing the receiver argument, removing the default causes a TypeError due to missing positional argument.
  • If the default value is a mutable object (e.g., self=[]), removing it eliminates shared state across calls, changing behavior for callers who relied on that sharing.
  • If the default value has side effects (e.g., self=print('hi') or self=f()), removing it prevents those side effects from occurring at function definition time.
  • If the default value is used elsewhere in the method body (e.g., def f(self=None): return self is None), removing it may cause NameError if the parameter is referenced without being passed.
  • If the method is overridden in a subclass and the subclass relies on the parent's default for dispatch or behavior, removing the default breaks the override contract.
  • If the default value depends on variables from outer scope (e.g., self=x where x is defined later), removing it changes closure capture and may cause NameError if x is not defined when the method is called.
  • If the method is used in a context where the receiver is intentionally omitted and the default provides a sentinel (e.g., for optional chaining or mocking), removing it breaks that pattern.
  • If the default value is an expression that evaluates to a type or class used in annotations or isinstance checks within the method, removing it alters those checks.
  • If the method is part of an API where callers explicitly rely on the ability to omit the receiver (even if unconventional), removing the default constitutes a breaking change.
  • If the default value is a forward reference or string annotation (e.g., self="Self"), removing it may affect tools that inspect defaults for refactoring or documentation.
  • If the method contains nested functions that close over the receiver parameter and rely on its default value for correctness, removing the default alters the captured value in those closures.
  • If the default value is a decorated expression or involves complex operators (e.g., self=a+b), removing it changes evaluation timing and may affect performance or side-effect order.

Programs

idresulttitlehazard
r1-p001silent prediction offBytes vs Str Encoding Hazardbytes vs str, encoding and newline handling, text vs binary modes
r1-p002fired, no fixAsync Await Ordering Hazardasync def/await ordering, async generators
r1-p003invalidSubclass Override Dispatch HazardIf the method is overridden in a subclass and the subclass relies on the parent's default for dispatch or behavior, removing the default breaks the override contract.
r1-p004silent prediction offEvaluation Order Side Effects Hazardevaluation order and side effects when expressions are merged, duplicated or deleted
r1-p005fired, no fixDirect Class Call Missing Arg HazardIf the method is called directly via the class (e.g., C.m()) without providing the receiver argument, removing the default causes a TypeError due to missing positional argument.
r1-p006silent prediction offOmitted Receiver Sentinel HazardIf the method is used in a context where the receiver is intentionally omitted and the default provides a sentinel (e.g., for optional chaining or mocking), removing it breaks that pattern.
r1-p007silentStar Imports Module Side Effects Hazardstar-imports, module-level side effects, __all__
r1-p008silent prediction offShadowed Builtins Redefinition Hazardshadowed builtins and names redefined later in the module
r2-p001fired, no fixType check depends on default receiver valueIf the default value is an expression that evaluates to a type or class used in annotations or isinstance checks within the method, removing it alters those checks.
r2-p002invalidForward reference as default affects toolingIf the default value is a forward reference or string annotation (e.g., self="Self"), removing it may affect tools that inspect defaults for refactoring or documentation.
r2-p003fired, no fixReceiver default used in method body causes NameError after fixIf the default value is used elsewhere in the method body (e.g., def f(self=None): return self is None), removing it may cause NameError if the parameter is referenced without being passed.
r2-p004fired, no fixException in default expression affects finally/else chainingexceptions raised inside the rewritten code, finally/else clauses, exception chaining
r2-p005fired, no fixMutable default receiver causes shared state across callsIf the default value is a mutable object (e.g., self=[]), removing it eliminates shared state across calls, changing behavior for callers who relied on that sharing.
r2-p006fired, no fixGenerator default vs list: exhaustion behavior differsgenerators vs lists, iterators consumed once, lazy vs eager evaluation
r2-p007fired, no fixSide effect in default expression silenced by fixIf the default value has side effects (e.g., self=print('hi') or self=f()), removing it prevents those side effects from occurring at function definition time.
r2-p008invalidComplex expression default changes evaluation timingIf the default value is a decorated expression or involves complex operators (e.g., self=a+b), removing it changes evaluation timing and may affect performance or side-effect order.

Sources

r1-p001 · Bytes vs Str Encoding Hazard
1def read_data(self=b''):
2 data = self.decode() if isinstance(self, bytes) else self
3 return len(data)
4
5print(read_data(b'hello'))
6try:
7 print(read_data('world'))
8except Exception as e:
9 print(type(e).__name__, str(e))
5
5
r1-p002 · Async Await Ordering Hazard
1class AsyncWorker:
2 async def process(self={}):
3 await asyncio.sleep(0)
4 return 'done'
5
6async def main():
7 w = AsyncWorker()
8 result = await w.process()
9 print(result)
10
11asyncio.run(main())
r1-p003 · Subclass Override Dispatch Hazard (generated program is not deterministic)
1class Base:
2 def handle(self='base'):
3 return f'Base: {self}'
4
5class Sub(Base):
6 def handle(self):
7 return super().handle() + ' -> Sub'
8
9b = Base()
10s = Sub()
11print(b.handle())
12print(s.handle())
r1-p004 · Evaluation Order Side Effects Hazard
1counter = 0
2
3def get_default():
4 global counter
5 counter += 1
6 return counter
7
8def method(self=get_default()):
9 return self
10
11print(method())
12print(method())
13print(f'Counter: {counter}')
1
1
Counter: 1
r1-p005 · Direct Class Call Missing Arg Hazard
1class C:
2 def method(self=42):
3 return self * 2
4
5print(C.method())
6try:
7 C().method()
8except Exception as e:
9 print(type(e).__name__, str(e))
84
TypeError unsupported operand type(s) for *: 'C' and 'int'
r1-p006 · Omitted Receiver Sentinel Hazard
1sentinel = object()
2
3def api_call(self=sentinel):
4 if self is sentinel:
5 return 'default_used'
6 return f'value: {self}'
7
8print(api_call())
9print(api_call('actual'))
default_used
value: actual
r1-p007 · Star Imports Module Side Effects Hazard
1__all__ = ['helper']
2
3def helper(self=[]):
4 self.append(1)
5 return self
6
7print(helper())
8print(helper())
[1]
[1, 1]
r1-p008 · Shadowed Builtins Redefinition Hazard
1list = lambda x: x
2
3def process(self=list):
4 return self([1, 2, 3])
5
6print(process())
7print(list([4, 5]))
[1, 2, 3]
[4, 5]
r2-p001 · Type check depends on default receiver value
1import typing
2T = int
3class C:
4 def m(self=T):
5 if isinstance(self, int):
6 return 1
7 return 0
8print(C().m())
0
r2-p002 · Forward reference as default affects tooling (generated program is not deterministic)
1class D:
2 def f(self="D"):
3 return self
4x = D().f()
5print(type(x).__name__ if isinstance(x, str) else x)
r2-p003 · Receiver default used in method body causes NameError after fix
1class E:
2 def m(self=None):
3 return self is None
4try:
5 print(E().m())
6except Exception as ex:
7 print(f'{type(ex).__name__}: {ex}')
False
r2-p004 · Exception in default expression affects finally/else chaining
1def bad():
2 raise ValueError('bad')
3class F:
4 def m(self=bad()):
5 try:
6 return 1
7 except ValueError:
8 return 2
9 finally:
10 return 3
11try:
12 print(F().m())
13except Exception as ex:
14 print(f'{type(ex).__name__}: {ex}')
r2-p005 · Mutable default receiver causes shared state across calls
1class G:
2 def m(self=[]):
3 self.append(1)
4 return len(self)
5a = G()
6print(a.m(), a.m())
r2-p006 · Generator default vs list: exhaustion behavior differs
1def gen():
2 yield 1
3 yield 2
4class H:
5 def m(self=gen()):
6 try:
7 return next(self)
8 except StopIteration:
9 return 0
10print(H().m(), H().m())
r2-p007 · Side effect in default expression silenced by fix
1logs = []
2def side():
3 logs.append('called')
4 return 0
5class I:
6 def m(self=side()):
7 return len(logs)
8print(I().m(), logs)
1 ['called']
r2-p008 · Complex expression default changes evaluation timing (generated program is not deterministic)
1a = 1
2b = 2
3class J:
4 def m(self=a+b):
5 a = 3
6 b = 4
7 return self
8print(J().m())