Subclassing Annotated generic class fails · Issue #108394 · python/cpython
Bug report
Checklist
- I am confident this is a bug in CPython, not a bug in a third-party project
- I have searched the CPython issue tracker,
and am confident this bug has not been reported before
CPython versions tested on:
3.9, 3.10, 3.11
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.11.4 (main, Jul 24 2023, 08:22:29) [GCC 8.3.0]
A clear and concise description of the bug:
According to #96771, inheriting from typing.Annotated is a feature and is expected to work. However, it breaks when used with generic classes. Minimal example:
import typing T = typing.TypeVar("T") class C(typing.Generic[T]): pass class D(typing.Annotated[C[int], 123]): pass
fails with
TypeError: _GenericAlias.__init__() takes 3 positional arguments but 4 were given
However, it works if I use C without arguments:
class D(typing.Annotated[C, 123]): pass
AFAICT, the reason is that Annotated[C[int], 123] sets __origin__ to C[int] instead of C like all other generics. This change in _AnnotatedAlias.__init__ fixes the issue:
@@ -2112,7 +2112,7 @@ class _AnnotatedAlias(_NotIterable, _GenericAlias, _root=True): if isinstance(origin, _AnnotatedAlias): metadata = origin.__metadata__ + metadata origin = origin.__origin__ - super().__init__(origin, origin) + super().__init__(getattr(origin, "__origin__", origin), origin) self.__metadata__ = metadata def copy_with(self, params):
but I did not check if it breaks anything else. (This makes __origin__ is C and __args__ == (C[int],), so no information is lost.)