Skip to content

PYI059 fix moves Generic after keyword arguments #18602

@dscorbett

Description

@dscorbett

Summary

The fix for generic-not-last-base-class (PYI059) moves Generic after keyword arguments, which is a syntax error. It should be moved after the other positional arguments but before any keyword arguments.

$ cat >pyi059_1.py <<'# EOF'
from typing import Generic, TypeVar
T = TypeVar("T")
class C1(Generic[T], str, **{"metaclass": type}): ...
class C2(Generic[T], str, metaclass=type): ...
# EOF

$ ruff --isolated check pyi059_1.py --select PYI059 --preview --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.

A starred argument may follow a keyword argument in an inheritance list (cf. star-arg-unpacking-after-keyword-arg (B026)).

$ cat >pyi059_2.py <<'# EOF'
from typing import Generic, TypeVar
T = TypeVar("T")
class C3(Generic[T], metaclass=type, *[str]): ...
# EOF

$ ruff --isolated check pyi059_2.py --select PYI059 --preview --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.

In that case, one way to make Generic be the last base class is to move it after the starred arguments, and then to move the keyword arguments after Generic.

class C3(*[str], Generic[T], metaclass=type): ...

Alternatively, Generic could be moved into its own starred argument after the other starred arguments, leaving the keyword arguments unmoved.

class C3(metaclass=type, *[str], *[Generic[T]]): ...

Version

ruff 0.11.13 (5faf72a 2025-06-05)

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfixesRelated to suggested fixes for violations

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions