fixhunt

ruff UP037

labelled unknown
Runs / 2026-10-17T21-20-30-716Z-3u1v-ruff-UP037ruff 0.17.12026-10-17 21:20 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 2 rejectedmodel cost $0.0046

Analysis Nemotron 3 Super

Removes unnecessary quotes from type annotations when they are made redundant by 'from __future__ import annotations' or typing-only contexts.

Fix: Strips quotation marks from type annotations that are deemed unnecessary due to postponed evaluation or typing-only context, transforming e.g., '"Bar"' to Bar while preserving surrounding syntax and whitespace.

10 hazards
  • Rewriting a quoted forward reference like '"C"' in a class method to C may fail if C is defined later in the same module and the code relies on runtime evaluation without postponed annotations.
  • Removing quotes from an annotation in a default argument like def f(x: "List[]") = [] may cause a NameError if the type is not yet defined at function definition time.
  • The fix may incorrectly unquote annotations inside string literals or comments if the linter misidentifies them as type annotations, altering non-code text.
  • In lambdas assigned to variables, removing quotes from return annotations like lambda: "int" may break if the annotation is evaluated immediately and the type is not in scope.
  • Unquoting annotations in nested scopes (e.g., inside a function) may fail if the referenced type is only defined in an outer scope and not accessible at runtime without postponed evaluation.
  • If the file lacks 'from __future__ import annotations' and the preview flag is off, removing quotes may cause runtime NameErrors for forward references that rely on deferred evaluation.
  • The fix may remove quotes from annotations in __slots__ or other special attributes where string form is required for correct interpretation by the interpreter.
  • In code that uses eval() or exec() on annotations, removing quotes may change the string passed to evaluation, altering behavior if the annotation is inspected dynamically.
  • Unquoting may break code that depends on the annotation being a string for introspection (e.g., via inspect.get_annotations()) when postponed evaluation is not active.
  • If a quoted annotation contains a trailing or leading space inside the quotes (e.g., " int "), the fix may not preserve internal whitespace, potentially changing the string value if used elsewhere.

Programs

idresulttitlehazard
r1-p001invalidString literal confusionFix may strip quotes from type annotations mistaken for actual string content.
r1-p002silent prediction offLambda immediate evaluationUnquoting lambda return annotation fails if type not in scope at definition time.
r1-p003silent prediction offNested scope inaccessibilityUnquoting in inner function fails when type is only in outer scope without postponed eval.
r1-p004silent prediction offIntrospection dependencyUnquoting breaks runtime string inspection when annotations are evaluated eagerly.
r1-p005silent prediction offDescriptor side effectsUnquoting annotation on descriptor attribute may trigger early evaluation with side effects.
r1-p006silent prediction offPath behavior mismatchUnquoting annotation in path-related function may alter runtime type expectations.
r1-p007invalidBytes/str encodingUnquoting annotation changes assumed type for bytes/str handling in I/O.
r1-p008silentCustom truthiness interactionUnquoting annotation on variable with custom __bool__ may affect conditional logic if misparsed.
r2-p001silent prediction offComments/docstring interactioncomments and docstrings attached to the removed or moved code
r2-p002silent prediction offClass/instance attribute descriptor side effectclass attributes vs instance attributes, descriptors, properties with side effects
r2-p003silent prediction offMissing future import causes NameErrorIf the file lacks 'from __future__ import annotations' and the preview flag is off, removing quotes may cause runtime NameErrors for forward references that rely on deferred evaluation.
r2-p004silent prediction offEval/exec on annotations alters behaviorIn code that uses eval() or exec() on annotations, removing quotes may change the string passed to evaluation, altering behavior if the annotation is inspected dynamically.
r2-p005silent__slots__ requires string formThe fix may remove quotes from annotations in __slots__ or other special attributes where string form is required for correct interpretation by the interpreter.
r2-p006silent prediction offLate-defined class in same moduleRewriting a quoted forward reference like '"C"' in a class method to C may fail if C is defined later in the same module and the code relies on runtime evaluation without postponed annotations.
r2-p007silent prediction offLambda immediate evaluation out of scopeIn lambdas assigned to variables, removing quotes from return annotations like lambda: "int" may break if the annotation is evaluated immediately and the type is not in scope.
r2-p008silentInt/float/bool coercion edge caseint/float/bool coercion, Decimal, division and rounding

Sources

r1-p001 · String literal confusion (generated program does not parse: Traceback (most recent call last):)
1def f():
2 s = '"x:" "int"' # Looks like annotated var but is string
3 eval(s)
4 print('string:', s)\
5def g(x: "int") -> None:
6 print('annotated x:', x)
7g(42)
r1-p002 · Lambda immediate evaluation
1class A: pass
2f = lambda: "A" # Rule may unquote to lambda: A
3try:
4 print('lambda result:', f())
5except Exception as e:
6 print(type(e).__name__, ':', e)
lambda result: A
r1-p003 · Nested scope inaccessibility
1class T: pass
2def outer():
3 def inner() -> "T": # Rule may unquote to -> T
4 return T()
5 return inner()
6print('result:', outer().__class__.__name__)
result: T
r1-p004 · Introspection dependency
1import inspect
2def f(x: "int"): pass # Rule may unquote to x: int
3ann = inspect.get_annotations(f)
4print('annotation type:', type(ann['x']))
5print('annotation value:', ann['x'])
annotation type: <class 'str'>
annotation value: int
r1-p005 · Descriptor side effects
1class Desc:
2 def __get__(self, obj, owner):
3 print('Desc accessed')
4 return 42
5class C:
6 x: "Desc" = Desc() # Rule may unquote -> triggers __get__ at class definition
7print('C.x:', C.x)
Desc accessed
C.x: 42
r1-p006 · Path behavior mismatch
1import os
2def p(path: "str"): # Rule may unquote to path: str
3 return os.path.exists(path)
4with open('tmp.txt', 'w') as f:
5 f.write('test')
6print('exists:', p('tmp.txt'))
7os.remove('tmp.txt')
exists: True
r1-p007 · Bytes/str encoding (generated program does not parse: Traceback (most recent call last):)
1def read_file(p: "str"): # Rule may unquote to p: str
2 with open(p, 'rb') as f:
3 return f.read()
4data = b'hello
5world'
6with open('test.bin', 'wb') as f:
7 f.write(data)
8result = read_file('test.bin')
9print('bytes:', result)
10import os
11os.remove('test.bin')
r1-p008 · Custom truthiness interaction
1class Truthy:
2 def __bool__(self):
3 return len(self.data) > 0
4 def __init__(self):
5 self.data = [1]
6t = Truthy()
7if t: # Not an annotation, rule should not trigger
8 print('truthy')
9else:
10 print('falsy')
truthy
r2-p001 · Comments/docstring interaction
1"""
2This module tests quote removal next to docstring.
3"""
4class Node:
5 """A node that references itself via forward ref."""
6 parent: "Node" = None
7 def walk(self):
8 p = self.parent
9 print(p.__class__.__name__ if p else 'None')
10Node().walk()
None
r2-p002 · Class/instance attribute descriptor side effect
1class Tracking:
2 def __get__(self, obj, owner):
3 print('Descriptor accessed')
4 return 42
5 def __set__(self, obj, value):
6 print(f'Descriptor set to {value}')
7
8class Container:
9 attr: "Tracking" = Tracking()
10
11print('Accessing attr')
12val = Container.attr
13print(f'Got {val}')
14Container.attr = 99
Accessing attr
Descriptor accessed
Got 42
r2-p003 · Missing future import causes NameError
1def process(item: "Processor") -> str:
2 return item.name
3
4class Processor:
5 def __init__(self, name):
6 self.name = name
7
8print(process(Processor("test")))
test
r2-p004 · Eval/exec on annotations alters behavior
1import inspect
2
3def func(x: "int") -> "str":
4 return str(x)
5
6ann = inspect.signature(func).parameters['x'].annotation
7print(f'Annotation raw: {repr(ann)}')
8try:
9 result = eval(ann) if isinstance(ann, str) else ann
10 print(f'Eval result: {result}')
11except Exception as e:
12 print(f'Eval error: {type(e).__name__}: {e}')
Annotation raw: 'int'
Eval result: <class 'int'>
r2-p005 · __slots__ requires string form
1class SlotClass:
2 __slots__ = ["x", "y"]
3 x: int = 0
4 y: int = 0
5
6obj = SlotClass()
7obj.x = 1
8obj.y = 2
9print(f'x={obj.x}, y={obj.y}')
r2-p006 · Late-defined class in same module
1class Factory:
2 def make(self) -> "Product":
3 return Product()
4
5class Product:
6 def __init__(self):
7 self.value = "created"
8
9f = Factory()
10p = f.make()
11print(p.value)
created
r2-p007 · Lambda immediate evaluation out of scope
1def make_checker():
2 return lambda: "int" # return annotation
3
4checker = make_checker()
5try:
6 ann = checker.__annotations__['return']
7 print(f'Lambda return annotation: {repr(ann)}')
8 if isinstance(ann, str):
9 print('Annotation is string, safe to eval later')
10 else:
11 print('Annotation resolved, assuming type in scope')
12except KeyError:
13 print('No return annotation')
No return annotation
r2-p008 · Int/float/bool coercion edge case
1value: "int" = "42"
2print(f'Value: {value}, type: {type(value)}')
3try:
4 coerced = int(value)
5 print(f'Coerced to int: {coerced}')
6except Exception as e:
7 print(f'Coercion failed: {type(e).__name__}: {e}')
Value: 42, type: <class 'str'>
Coerced to int: 42