fixhunt

ruff UP043

labelled unknown
Runs / 2026-10-17T21-26-26-009Z-r0jp-ruff-UP043ruff 0.17.12026-10-17 21:26 UTC8 programs × 2 round(s)8 programs, 0 fired, 0 fixed, 0 findings, 2 rejectedmodel cost $0.0018

Analysis Nemotron 3 Super

Flags explicit default type arguments (`None`) for `Generator` and `AsyncGenerator` when they match the defaults introduced in Python 3.13.

Fix: Removes trailing type arguments that are exactly `None` for the second and/or third parameters of `Generator`, and the second parameter of `AsyncGenerator`, when they match the default values introduced in Python 3.13.

8 hazards
  • Rewriting `Generator[T, None, None]` to `Generator[T]` changes meaning if the code targets Python <3.13 where defaults are not applied.
  • If the annotation contains an inline comment (e.g., `Generator[int, None, None # comment]`), the fix may drop the comment, altering documentation.
  • In a string annotation like `"Generator[int, None, None]"`, the fix does not apply, but if incorrectly applied, it would corrupt the string.
  • If `None` is imported under an alias (e.g., `from types import NoneType as None`), the fixer might not recognize it as the default, leading to unsafe removal.
  • When used in a union like `Union[Generator[int, None, None], str]`, removing the `None`s could change the union's structure if relied upon for overload resolution.
  • In a forward reference evaluated later (e.g., in `TYPE_CHECKING` blocks), the rewritten form may resolve differently if the target scope lacks the updated built-in generics.
  • If the code uses a custom subclass of `Generator` that overrides `__class_getitem__`, the fix assumes standard library semantics and may be incorrect.
  • When the annotation is part of a larger expression (e.g., in a `Callable[[], Generator[int, None, None]]`), the fix only applies to the nested annotation and must not disturb the outer structure.

Programs

idresulttitlehazard
r1-p001silent prediction offException handling with Generator return annotationExceptions raised inside the rewritten code, finally/else clauses, exception chaining
r1-p002invalidDict ordering and hashability with Generator annotationDict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r1-p003silent prediction offForward reference in TYPE_CHECKING blockIn a forward reference evaluated later (e.g., in `TYPE_CHECKING` blocks), the rewritten form may resolve differently if the target scope lacks the updated built-in generics.
r1-p004silent prediction offKeyword-only args with Generator annotationkeyword-only, positional-only, *args/**kwargs forwarding, defaults evaluated once
r1-p005invalidNone imported as alias affecting recognitionIf `None` is imported under an alias (e.g., `from types import NoneType as None`), the fixer might not recognize it as the default, leading to unsafe removal.
r1-p006silent prediction offUnion type relying on explicit None for overload resolutionWhen used in a union like `Union[Generator[int, None, None], str]`, removing the `None`s could change the union's structure if relied upon for overload resolution.
r1-p007silent prediction offRuntime evaluation of Generator annotationtype annotations evaluated at runtime, typing-only imports
r1-p008silent prediction offTruthiness and identity checks with Generator in bool contexttruthiness of custom __bool__/__len__, None vs falsy, 'is' vs '=='

Sources

r1-p001 · Exception handling with Generator return annotation
1def f() -> Generator[int, None, None]:
2 try:
3 raise ValueError('test')
4 except ValueError as e:
5 yield 1
6 else:
7 yield 2
8 finally:
9 yield 3
10gen = f()
11print(list(gen))
[1, 3]
r1-p002 · Dict ordering and hashability with Generator annotation (generated program is not deterministic)
1class Key:
2 def __init__(self, v): self.v = v
3 def __hash__(self): return hash(self.v)
4 def __eq__(self, other): return isinstance(other, Key) and self.v == other.v
5def g() -> Generator[tuple[Key, int], None, None]:
6 yield (Key(1), 10)
7 yield (Key(2), 20)
8d = dict(g())
9print(list(d.items()))
r1-p003 · Forward reference in TYPE_CHECKING block
1from typing import TYPE_CHECKING, Generator
2if TYPE_CHECKING:
3 x: Generator[int, None, None]
4else:
5 x = (i for i in range(3))
6print(type(x).__name__)
generator
r1-p004 · Keyword-only args with Generator annotation
1def f(*, g: Generator[int, None, None] = (i for i in [1])):
2 return sum(g)
3print(f())
1
r1-p005 · None imported as alias affecting recognition (generated program does not parse: Traceback (most recent call last):)
1from types import NoneType as None
2def f() -> Generator[int, None, None]:
3 yield 1
4gen = f()
5print(next(gen))
r1-p006 · Union type relying on explicit None for overload resolution
1from typing import Union, Generator
2def process(x: Union[Generator[int, None, None], str]):
3 if isinstance(x, str):
4 return x.upper()
5 return list(x)
6print(process((i for i in [2])))
7print(process('hello'))
[2]
HELLO
r1-p007 · Runtime evaluation of Generator annotation
1import typing
2t = typing.get_type_hints(lambda: None).__annotations__
3def f() -> Generator[int, None, None]: pass
4t2 = typing.get_type_hints(f).__annotations__['return']
5print(str(t2))
r1-p008 · Truthiness and identity checks with Generator in bool context
1class MyGen:
2 def __bool__(self): return False
3 def __len__(self): return 0
4def f() -> Generator[MyGen, None, None]:
5 yield MyGen()
6g = f()
7print(bool(g))
8print(g is None)
True
False