diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 6e036b600330c1..4ce50a84dcb422 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -5621,6 +5621,14 @@ class A: with self.assertRaises(TypeError): a[int] + def test_orig_class_init(self): + # See gh-123777 + T = TypeVar("T") + class OrigClassInit(Generic[T]): + def __init__(self): + self.attr = self.__orig_class__ + self.assertEqual(OrigClassInit[int]().attr, OrigClassInit[int]) + class ClassVarTests(BaseTestCase): diff --git a/Lib/typing.py b/Lib/typing.py index bcb7bec23a9aa1..a7709414c40979 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1290,13 +1290,36 @@ def __call__(self, *args, **kwargs): if not self._inst: raise TypeError(f"Type {self._name} cannot be instantiated; " f"use {self.__origin__.__name__}() instead") - result = self.__origin__(*args, **kwargs) + clas = self.__origin__ + safe_new = (clas.__new__ is object.__new__) or isinstance(clas.__new__, types.FunctionType) + + if safe_new: + # GH-123777: Some types try and access __orig_class__ in their __init__ + try: + result = clas.__new__(clas, *args, **kwargs) + except Exception: + # Something about the type doesn't like calling __new__ + # (For example, _GenericAlias) + safe_new = False + result = clas(*args, **kwargs) + else: + # This is a C type with a custom __new__ + # + # I'm worried that trying to set attributes on C types before they've been + # fully initialized will be problematic, so let's just disallow them + # from using the __orig_class__ in the initializer for now. + result = clas(*args, **kwargs) + try: result.__orig_class__ = self # Some objects raise TypeError (or something even more exotic) # if you try to set attributes on them; we guard against that here except Exception: pass + + if safe_new: + result.__init__(*args, **kwargs) + return result def __mro_entries__(self, bases): diff --git a/Misc/NEWS.d/next/Library/2024-09-09-16-21-12.gh-issue-123777.sdyP3n.rst b/Misc/NEWS.d/next/Library/2024-09-09-16-21-12.gh-issue-123777.sdyP3n.rst new file mode 100644 index 00000000000000..df1412213275f3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-09-16-21-12.gh-issue-123777.sdyP3n.rst @@ -0,0 +1,2 @@ +Allowed the ``__orig_class__`` attribute to be used in the ``__init__`` of +pure-Python types.