From 99fa708df2af1ab5ecde47968d71dc5b0447fc5d Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 3 Aug 2023 17:07:10 +0100 Subject: [PATCH] Backport CPython PR 107584 (#275) --- CHANGELOG.md | 4 ++++ src/test_typing_extensions.py | 19 +++++++++++++++++++ src/typing_extensions.py | 11 ++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f67da871..8cd98764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Release 4.8.0 (???) - Drop support for Python 3.7 (including PyPy-3.7). Patch by Alex Waygood. +- Fix bug where `get_original_bases()` would return incorrect results when + called on a concrete subclass of a generic class. Patch by Alex Waygood + (backporting https://github.com/python/cpython/pull/107584, by James + Hilton-Balfe). # Release 4.7.1 (July 2, 2023) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 78fe0c0f..e741d699 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -5704,6 +5704,25 @@ class F(list[int]): pass self.assertEqual(get_original_bases(E), (list[T],)) self.assertEqual(get_original_bases(F), (list[int],)) + @skipIf( + sys.version_info[:3] == (3, 12, 0) and sys.version_info[3] in {"alpha", "beta"}, + "Early versions of py312 had a bug" + ) + def test_concrete_subclasses_of_generic_classes(self): + T = TypeVar("T") + + class FirstBase(Generic[T]): pass + class SecondBase(Generic[T]): pass + class First(FirstBase[int]): pass + class Second(SecondBase[int]): pass + class G(First, Second): pass + self.assertEqual(get_original_bases(G), (First, Second)) + + class First_(Generic[T]): pass + class Second_(Generic[T]): pass + class H(First_, Second_): pass + self.assertEqual(get_original_bases(H), (First_, Second_)) + def test_namedtuples(self): # On 3.12, this should work well with typing.NamedTuple and typing_extensions.NamedTuple # On lower versions, it will only work fully with typing_extensions.NamedTuple diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 0978c5f3..b0b1bceb 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -2570,14 +2570,11 @@ class Baz(list[str]): ... assert get_original_bases(int) == (object,) """ try: - return cls.__orig_bases__ + return cls.__dict__.get("__orig_bases__", cls.__bases__) except AttributeError: - try: - return cls.__bases__ - except AttributeError: - raise TypeError( - f'Expected an instance of type, not {type(cls).__name__!r}' - ) from None + raise TypeError( + f'Expected an instance of type, not {type(cls).__name__!r}' + ) from None # NewType is a class on Python 3.10+, making it pickleable