Backport CPython PR 107584 (#275)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f67da87..8cd9876 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 78fe0c0..e741d69 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -5704,6 +5704,25 @@
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 0978c5f..b0b1bce 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -2570,14 +2570,11 @@
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