gh-107576: Ensure `__orig_bases__` are our own in `get_original_bases` (#107584)

Co-authored-by: Chris Bouchard <chris@upliftinglemma.net>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
James Hilton-Balfe 2023-08-03 15:19:24 +01:00 committed by GitHub
parent 77e09192b5
commit ed4a978449
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 7 deletions

View File

@ -1397,6 +1397,7 @@ class ClassCreationTests(unittest.TestCase):
class B(typing.Generic[T]): pass class B(typing.Generic[T]): pass
class C(B[int]): pass class C(B[int]): pass
class D(B[str], float): pass class D(B[str], float): pass
self.assertEqual(types.get_original_bases(A), (object,)) self.assertEqual(types.get_original_bases(A), (object,))
self.assertEqual(types.get_original_bases(B), (typing.Generic[T],)) self.assertEqual(types.get_original_bases(B), (typing.Generic[T],))
self.assertEqual(types.get_original_bases(C), (B[int],)) self.assertEqual(types.get_original_bases(C), (B[int],))
@ -1409,6 +1410,18 @@ class ClassCreationTests(unittest.TestCase):
self.assertEqual(types.get_original_bases(E), (list[T],)) self.assertEqual(types.get_original_bases(E), (list[T],))
self.assertEqual(types.get_original_bases(F), (list[int],)) self.assertEqual(types.get_original_bases(F), (list[int],))
class FirstBase(typing.Generic[T]): pass
class SecondBase(typing.Generic[T]): pass
class First(FirstBase[int]): pass
class Second(SecondBase[int]): pass
class G(First, Second): pass
self.assertEqual(types.get_original_bases(G), (First, Second))
class First_(typing.Generic[T]): pass
class Second_(typing.Generic[T]): pass
class H(First_, Second_): pass
self.assertEqual(types.get_original_bases(H), (First_, Second_))
class ClassBasedNamedTuple(typing.NamedTuple): class ClassBasedNamedTuple(typing.NamedTuple):
x: int x: int

View File

@ -165,14 +165,11 @@ def get_original_bases(cls, /):
assert get_original_bases(int) == (object,) assert get_original_bases(int) == (object,)
""" """
try: try:
return cls.__orig_bases__ return cls.__dict__.get("__orig_bases__", cls.__bases__)
except AttributeError: except AttributeError:
try: raise TypeError(
return cls.__bases__ f"Expected an instance of type, not {type(cls).__name__!r}"
except AttributeError: ) from None
raise TypeError(
f'Expected an instance of type, not {type(cls).__name__!r}'
) from None
class DynamicClassAttribute: class DynamicClassAttribute:

View File

@ -0,0 +1,3 @@
Fix :func:`types.get_original_bases` to only return
:attr:`!__orig_bases__` if it is present on ``cls`` directly. Patch by
James Hilton-Balfe.