Currently, the spec has this to say about creating a generic class by subclassing another generic class in the pre-PEP 695 world:
The
Generic[T]
base class is redundant in simple cases where you subclass some other generic class and specify type variables for its parameters:from typing import TypeVar from collections.abc import Iterator T = TypeVar('T') class MyIter(Iterator[T]): ...
That class definition is equivalent to:
class MyIter(Iterator[T], Generic[T]): ...
It would be nice to clarify what those “simple cases” are, given that typeshed uses this, and it’s currently unclear what cases a type checker needs to support to use typeshed.
As far as I can tell, both mypy and pyright take type variables in order of first appearance, with pyright additionally emitting an error when this doesn’t produce a consistent ordering. Examples:
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
class C1(Generic[T1, T2]): ...
class C2(Generic[T1, T2]): ...
class C3(C2[T1, T3], C1[T2, T3]): ...
c3 = C3[int, str, bool]() # T1 = int, T3 = str, T2 = bool
from typing import Generic, TypeVar
T1 = TypeVar('T1')
T2 = TypeVar('T2')
class C1(Generic[T1, T2]): ...
class C2(C1[T1, T2]): ...
class C3(C2[T1, T2], C1[T2, T1]): # this is an error in pyright but not mypy
...
c3 = C3[int, str]() # T1 = int, T2 = str
I think the simplest thing to do would be to update the spec to say that type checkers should take type variables in order of first appearance, and may warn when the order is inconsistent. Thoughts?