Consider the subclassing rule in the typing spec with PEP 696 type parameter defaults:
from typing_extensions import Generic, TypeVar
T = TypeVar("T")
DefaultStrT = TypeVar("DefaultStrT", default=str)
class SubclassMe(Generic[T, DefaultStrT]):
x: DefaultStrT
class Foo(SubclassMe[float]): ...
Foo[str] # Invalid: Foo cannot be further subscripted
Notably, Foo cannot be further subscripted, since non-overridden defaults should be substituted.
However, using another type parameter within scope as default behaves differently at runtime:
StartT = TypeVar("StartT", default=int)
StopT = TypeVar("StopT", default=StartT)
StepT = TypeVar("StepT", default=int | None)
class slice(Generic[StartT, StopT, StepT]): ...
class int_slice(slice[int]): ...
int_slice[int] # Should be invalid, but OK at runtime
Here, slice[int] substitutes StartT with int and StopT with StartT, but int_slice still keep StartT in__parameters__, making it further subscriptable at runtime. There are cases where a subclass explicitly specifies it can be further parameterized, say,
class from_int_slice(slice[int, StopT]): ...
but AFAIK there is no way to distinguish from_int_slice from int_slice at runtime as they both contain effectively subscriptable type parameter.
While I don’t expect typing implementation to also resolve default type parameters to their value within scope, the subclassing rule seems to imply that non-overridden defaults should be excluded from __parameters__ in subclasses as well. Hoping to clarify if this is intended behavior!