Bug: `typing_extensions.Generic` not support `TypeVar` defaults
Work MRE.
Setup
>> python version: 3.13.5 (main, Jun 21 2025, 09:35:00) [GCC 15.1.1 20250425]
MRE
from typing import TypeVar, Generic, get_args
R = TypeVar("R")
T = TypeVar("T", default=int)
class A(Generic[R, T]):
pass
assert get_args(A[str]) == (str, int)
Not work MRE.
Setup
>> python version: 3.10.17 (main, Apr 9 2025, 04:03:39) [Clang 20.1.0 ]
>> uv pip show typing-extensions
Name: typing-extensions
Version: 4.15.0
MRE
from typing_extensions import TypeVar, Generic, get_args
R = TypeVar("R")
T = TypeVar("T", default=int)
class A(Generic[R, T]):
pass
assert get_args(A[str]) == (str,)
The assertions you listed differ in both cases. I would think one wants the same code in both cases? (str, int) is the current behavior on Python 3.13 / 3.14.
Under typing_extensions 4.14.1 it returns only (str,) with 4.15.0 it also returns the default value similar to 3.13 typing.
To my knowledge it is the intended behavior to get the all arguments get_args with defaults substituted in.
This only seems to affect typing_extensions on Python 3.9 and 3.10. This script:
from typing_extensions import TypeVar, Generic, get_args
R = TypeVar("R")
T = TypeVar("T", default=int)
class A(Generic[R, T]): ...
print(f"{get_args(A[str])=} {A[str].__args__=}")
produces:
$ uv run --python 3.11 temp.py
get_args(A[str])=(<class 'str'>, <class 'int'>) A[str].__args__=(<class 'str'>, <class 'int'>)
$ uv run --python 3.10 temp.py
get_args(A[str])=(<class 'str'>,) A[str].__args__=(<class 'str'>,)
Based on a cursor look with a debugger, the behavior difference comes from inside Generic.__class_getitem__. Fixing this might require monkey patching it on Python 3.9 & 3.10
I think we don't need monkey pathing here. It is enough to write your own Generic object that will be able to use TypeVar defaults
At the moment, typing_extensions uses the mechanism of re-exporting the Generic class from the original typing package
Is there any news on this bug? Should I send a pull request with a bug fix?
MRE with the new generics syntax:
# temp.py
from typing_extensions import get_args
class Foo[T = str]:
x: T
f = Foo()
try:
reveal_type(f.x)
except NameError:
pass
print(get_args(f))
$ mypy temp.py
temp.py:9: note: Revealed type is "builtins.str"
Success: no issues found in 1 source file
$ python temp.py
()
@jacksonthall22 that's unrelated (your example doesn't involve typing-extensions). You need to call get_args() on the class, not an instance.
@IvanKirpichnikov PRs welcome! We'll have to see how invasive the fix is; it only affects 3.9 (which is about to go EOL) and 3.10 (which is also getting towards the end of its support).
@IvanKirpichnikov PRs welcome! We'll have to see how invasive the fix is; it only affects 3.9 (which is about to go EOL) and 3.10 (which is also getting towards the end of its support).
I didn't understand the argument about 3.10. Type var defaults appeared in 3.13. That is, you need to make your typing_extensions.Generic to EOL 3.13. No?
If I understand the previous discussion correctly, this bug appears only in 3.9 and 3.10. If it instead appears up to 3.12, that does make it more important to fix.
It appears on versions <3.13(that is 3.10, 3.11, 3.12) because typing_extensions.Generic is literally typing.Generic
I think this option is critical because it requires working with default value options in input extensions.
On Python 3.11 and 3.12 with typing-extensions, get_args() returns the same thing as on 3.13+ with typing (as @brianschubert reported a few comments up). If you think something is still wrong on 3.11 and 3.12, please report exactly what you expect to happen and what is happening instead.
because typing_extensions.Generic is literally typing.Generic
That's an implementation detail; we don't necessarily have to duplicate Generic itself to solve this issue. We care only about the publicly visible behavior.