fixhunt

ruff UP004

labelled unknown
Runs / 2026-10-17T21-10-12-626Z-z2ng-ruff-UP004ruff 0.17.12026-10-17 21:10 UTC8 programs × 2 round(s)16 programs, 14 fired, 14 fixed, 1 findings, 1 rejectedmodel cost $0.02

Analysis Nemotron 3 Super

Flags class definitions that explicitly inherit from object, which is redundant in Python 3.

Fix: Removes 'object' from the base class list; if object is the only base, the entire inheritance list is deleted leaving just 'class Name:'; if object is among multiple bases, it is stripped out while preserving order and spacing of remaining bases.

8 hazards
  • Rewriting 'class C(object, Mixin): pass' to 'class C(Mixin): pass' changes the method resolution order (MRO) if Mixin defines methods also present in later bases, altering which method is called via super().
  • If a class uses a metaclass via '__metaclass__' attribute (Python 2) or '__classcell__' in nested scopes, removing 'object' may affect class creation semantics in edge cases involving class cell closure capture.
  • In rare cases where 'object' is used as a placeholder for a dynamically assigned base via metaprogramming (e.g., class decorators that inspect bases), removing it breaks the decorator's assumption about the base list.
  • If the class definition contains a trailing comment after the colon (e.g., 'class Foo(object): # comment'), the autofix may drop the comment when reformatting the line, violating comment preservation safety.
  • When 'object' is the first base and followed by a newline-indented block, removing it may cause the linter/formatter to reindent the block incorrectly if the tool does not preserve whitespace exactly, altering readability though not semantics.
  • In code that relies on the string representation of the class's bases (e.g., for serialization or debugging), removing 'object' changes the output of __bases__, potentially breaking introspection-dependent logic.
  • If a class is defined inside a function and uses 'object' to avoid a name conflict with a local variable named 'object', removing it could cause unintended binding (though this is extremely unlikely and non-standard).
  • When using Python 2 compatibility layers like 'six' or 'future', some code may rely on explicit 'object' inheritance to trigger new-style class behavior; removing it in Py2 would break the code, but the rule only applies in Py3+ contexts—still, if the file is run under Py2 due to misconfiguration, the fix introduces a regression.

Findings

programoraclelabeljudgestatussummary
r1-p003fix-changes-behaviorlabelled safereal · highrelatedThe fix removes 'object' from the base class list of a class that also inherits from Mixin and Base, changing the MRO and resolving a previously unresolvable d…

Programs

idresulttitlehazard
r1-p001fix okClass Attributes vs Instance AttributesRemoving 'object' has no effect on attribute lookup semantics in Python 3, but this program verifies descriptor/__set_name__ behavior remains unchanged after rewrite.
r1-p002fix okType Annotations Evaluated at RuntimeEnsures that removing 'object' does not affect runtime evaluation of type annotations in class body, especially when using typing-only imports.
r1-p003fix-changes-behaviorMethod Resolution Order ChangeRewriting 'class C(object, Mixin)' to 'class C(Mixin)' alters MRO when Mixin and a later base define the same method, changing which method is called via super().
r1-p004fix okGenerators vs ListsTests that removing 'object' does not affect lazy evaluation in generators defined in class scope, ensuring iteration behavior is preserved.
r1-p005fix okContext Managers Not FilesVerifies that removing 'object' does not break context manager protocol (__enter__, __exit__) for non-file objects with custom write-like behavior.
r1-p006fix okWalrus and Comprehensions ScopingChecks that removing 'object' does not affect scoping in comprehensions or walrus usage inside methods, ensuring closure capture is stable.
r1-p007fix okWhitespace Sensitivity After object RemovalWhen 'object' is first base and followed by indented block, ensuring linters/formatters do not corrupt indentation upon removal (semantics preserved, readability tested via structure).
r1-p008invalidString Formatting Edge CasesEnsures that removing 'object' does not interfere with string formatting methods (% , format, f-strings) or repr/str behavior in class hierarchy.
r2-p001fix okStar Imports and Module-Level Side Effectsstar-imports, module-level side effects, __all__
r2-p002fix okRuntime Type Annotations with typing-only importstype annotations evaluated at runtime, typing-only imports
r2-p003fix okCustom __bool__ and Truthiness Semanticstruthiness of custom __bool__/__len__, None vs falsy, 'is' vs '=='
r2-p004fix okMutable Default Arguments and Aliasingmutable default arguments and aliasing after a rewrite
r2-p005fix okDict Ordering, Hash, and Eq Overridesdict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r2-p006fix okEvaluation Order and Side Effects in Merged Expressionsevaluation order and side effects when expressions are merged, duplicated or deleted
r2-p007fix okMetaclass and __classcell__ InteractionIf a class uses a metaclass via '__metaclass__' attribute (Python 2) or '__classcell__' in nested scopes, removing 'object' may affect class creation semantics in edge cases involving class cell closu
r2-p008silent prediction offNested Class and Local Variable Name ConflictIf a class is defined inside a function and uses 'object' to avoid a name conflict with a local variable named 'object', removing it could cause unintended binding (though this is extremely unlikely a

Sources

r1-p001 · Class Attributes vs Instance Attributes
1class Descr:
2 def __set_name__(self, owner, name):
3 self.name = name
4 def __get__(self, obj, objtype=None):
5 return getattr(obj, '_' + self.name, None)
6 def __set__(self, obj, value):
7 setattr(obj, '_' + self.name, value * 2)
8
9class A(object):
10 x = Descr()
11 def __init__(self):
12 self.x = 5
13
14a = A()
15print(a.x)
--- orig.py	2026-10-17 17:10:22.461483987 -0400
+++ fixed.py	2026-10-17 17:10:22.627485710 -0400
@@ -6,7 +6,7 @@
     def __set__(self, obj, value):
         setattr(obj, '_' + self.name, value * 2)
 
-class A(object):
+class A:
     x = Descr()
     def __init__(self):
         self.x = 5
10
r1-p002 · Type Annotations Evaluated at Runtime
1from typing import List, TYPE_CHECKING
2if TYPE_CHECKING:
3 class _Tmp: pass
4
5class B(object):
6 attr: 'List[int]' = [1, 2, 3]
7 def method(self) -> int:
8 return len(self.attr)
9
10b = B()
11print(b.method())
--- orig.py	2026-10-17 17:10:22.733486810 -0400
+++ fixed.py	2026-10-17 17:10:22.918488730 -0400
@@ -2,7 +2,7 @@
 if TYPE_CHECKING:
     class _Tmp: pass
 
-class B(object):
+class B:
     attr: 'List[int]' = [1, 2, 3]
     def method(self) -> int:
         return len(self.attr)
3
r1-p003 · Method Resolution Order Change
1class Mixin:
2 def ping(self):
3 return 'from Mixin'
4
5class Base:
6 def ping(self):
7 return 'from Base'
8
9class C(object, Mixin, Base):
10 def ping(self):
11 return super().ping()
12
13c = C()
14print(c.ping())
--- orig.py	2026-10-17 17:10:23.023489820 -0400
+++ fixed.py	2026-10-17 17:10:23.444494188 -0400
@@ -6,7 +6,7 @@
     def ping(self):
         return 'from Base'
 
-class C(object, Mixin, Base):
+class C(Mixin, Base):
     def ping(self):
         return super().ping()
 
r1-p004 · Generators vs Lists
1class D(object):
2 def gen(self):
3 yield 1
4 yield 2
5
6 @property
7 def values(self):
8 return list(self.gen())
9
10d = D()
11print(d.values)
--- orig.py	2026-10-17 17:10:23.542495205 -0400
+++ fixed.py	2026-10-17 17:10:23.700496845 -0400
@@ -1,4 +1,4 @@
-class D(object):
+class D:
     def gen(self):
         yield 1
         yield 2
[1, 2]
r1-p005 · Context Managers Not Files
1class Echo:
2 def __enter__(self):
3 self.buffer = []
4 return self
5 def __exit__(self, *exc):
6 return False
7 def write(self, data):
8 self.buffer.append(data)
9
10class F(object):
11 def log(self):
12 with Echo() as e:
13 e.write('test')
14 return ''.join(e.buffer)
15
16f = F()
17print(f.log())
--- orig.py	2026-10-17 17:10:23.806497945 -0400
+++ fixed.py	2026-10-17 17:10:23.974499688 -0400
@@ -7,7 +7,7 @@
     def write(self, data):
         self.buffer.append(data)
 
-class F(object):
+class F:
     def log(self):
         with Echo() as e:
             e.write('test')
test
r1-p006 · Walrus and Comprehensions Scoping
1class G(object):
2 def process(self, data):
3 return [(y := x * 2) for x in data if (y := x * 2) > 4]
4
5g = G()
6print(g.process([1, 2, 3]))
--- orig.py	2026-10-17 17:10:24.072500705 -0400
+++ fixed.py	2026-10-17 17:10:24.231502354 -0400
@@ -1,4 +1,4 @@
-class G(object):
+class G:
     def process(self, data):
         return [(y := x * 2) for x in data if (y := x * 2) > 4]
 
[6]
r1-p007 · Whitespace Sensitivity After object Removal
1class H(object):
2 x = 1
3 def get_x(self):
4 return self.x
5
6h = H()
7print(h.get_x())
--- orig.py	2026-10-17 17:10:24.330503381 -0400
+++ fixed.py	2026-10-17 17:10:24.493505072 -0400
@@ -1,4 +1,4 @@
-class H(object):
+class H:
     x = 1
     def get_x(self):
         return self.x
1
r1-p008 · String Formatting Edge Cases (generated program does not parse: Traceback (most recent call last):)
1class I(object):
2 value = 42
3 def __str__(self):
4 return f'Value: {self.value}'
5 def __repr__(self):
6 return f'I({self.value!r})
7'
8
9i = I()
10print(str(i))
11print(repr(i))
r2-p001 · Star Imports and Module-Level Side Effects
1__all__ = []
2
3class _Hidden(object):
4 value = 42
5
6def init():
7 globals().update(_Hidden.__dict__)
8 __all__.append('value')
9
10init()
11print(value)
--- orig.py	2026-10-17 17:10:35.673620945 -0400
+++ fixed.py	2026-10-17 17:10:35.849622768 -0400
@@ -1,6 +1,6 @@
 __all__ = []
 
-class _Hidden(object):
+class _Hidden:
     value = 42
 
 def init():
42
r2-p002 · Runtime Type Annotations with typing-only imports
1from typing import List
2
3class Parser(object):
4 def parse(self, data: List[int]) -> List[str]:
5 return [str(x) for x in data]
6
7p = Parser()
8result = p.parse([1, 2, 3])
9print(result)
--- orig.py	2026-10-17 17:10:35.950623814 -0400
+++ fixed.py	2026-10-17 17:10:36.132625698 -0400
@@ -1,6 +1,6 @@
 from typing import List
 
-class Parser(object):
+class Parser:
     def parse(self, data: List[int]) -> List[str]:
         return [str(x) for x in data]
 
['1', '2', '3']
r2-p003 · Custom __bool__ and Truthiness Semantics
1class Flag(object):
2 def __init__(self, v):
3 self.v = v
4 def __bool__(self):
5 return self.v is not None
6
7f = Flag(None)
8print(bool(f))
9f.v = 0
10print(bool(f))
--- orig.py	2026-10-17 17:10:36.251626930 -0400
+++ fixed.py	2026-10-17 17:10:36.415628627 -0400
@@ -1,4 +1,4 @@
-class Flag(object):
+class Flag:
     def __init__(self, v):
         self.v = v
     def __bool__(self):
False
True
r2-p004 · Mutable Default Arguments and Aliasing
1class Container(object):
2 def __init__(self, items=None):
3 self.items = items or []
4 self.items.append(len(self.items))
5
6c1 = Container()
7c2 = Container()
8print(c1.items, c2.items)
--- orig.py	2026-10-17 17:10:36.517629684 -0400
+++ fixed.py	2026-10-17 17:10:36.679631361 -0400
@@ -1,4 +1,4 @@
-class Container(object):
+class Container:
     def __init__(self, items=None):
         self.items = items or []
         self.items.append(len(self.items))
[0] [0]
r2-p005 · Dict Ordering, Hash, and Eq Overrides
1class Key(object):
2 def __init__(self, val):
3 self.val = val
4 def __hash__(self):
5 return hash(self.val)
6 def __eq__(self, other):
7 return isinstance(other, Key) and self.val == other.val
8
9k1 = Key(1)
10k2 = Key(1)
11d = {k1: 'first', k2: 'second'}
12print(len(d), d[k1])
--- orig.py	2026-10-17 17:10:36.785632458 -0400
+++ fixed.py	2026-10-17 17:10:36.952634187 -0400
@@ -1,4 +1,4 @@
-class Key(object):
+class Key:
     def __init__(self, val):
         self.val = val
     def __hash__(self):
1 second
r2-p006 · Evaluation Order and Side Effects in Merged Expressions
1counter = 0
2
3def inc():
4 global counter
5 counter += 1
6 return counter
7
8class Test(object):
9 x = inc()
10 y = inc()
11
12print(Test.x, Test.y, counter)
--- orig.py	2026-10-17 17:10:37.053635232 -0400
+++ fixed.py	2026-10-17 17:10:37.227637034 -0400
@@ -5,7 +5,7 @@
     counter += 1
     return counter
 
-class Test(object):
+class Test:
     x = inc()
     y = inc()
 
1 2 2
r2-p007 · Metaclass and __classcell__ Interaction
1def outer():
2 class_cell = None
3
4 class Meta(type):
5 def __new__(mcls, name, bases, namespace, **kw):
6 if '__classcell__' in namespace:
7 namespace['__classcell__'] = namespace.pop('__classcell__')
8 return super().__new__(mcls, name, bases, namespace, **kw)
9
10 class Base(object, metaclass=Meta):
11 pass
12
13 class Derived(Base):
14 x = 1
15
16 return Derived.x
17
18print(outer())
--- orig.py	2026-10-17 17:10:37.318637975 -0400
+++ fixed.py	2026-10-17 17:10:37.484639694 -0400
@@ -7,7 +7,7 @@
                 namespace['__classcell__'] = namespace.pop('__classcell__')
             return super().__new__(mcls, name, bases, namespace, **kw)
 
-    class Base(object, metaclass=Meta):
+    class Base(metaclass=Meta):
         pass
 
     class Derived(Base):
1
r2-p008 · Nested Class and Local Variable Name Conflict
1def make_class():
2 object = 42 # local variable named 'object'
3 class Local(object): # inherits from built-in object, not the local var
4 def get(self):
5 return object # refers to local var due to scoping
6 return Local()
7
8inst = make_class()
9print(inst.get())