|
31 | 31 | from typing_extensions import Awaitable, AsyncIterator, AsyncContextManager, Required, NotRequired
|
32 | 32 | from typing_extensions import Protocol, runtime, runtime_checkable, Annotated, final, is_typeddict
|
33 | 33 | from typing_extensions import TypeVarTuple, Unpack, dataclass_transform, reveal_type, Never, assert_never, LiteralString
|
34 |
| -from typing_extensions import assert_type, get_type_hints, get_origin, get_args |
| 34 | +from typing_extensions import assert_type, get_type_hints, get_origin, get_args, get_original_bases |
35 | 35 | from typing_extensions import clear_overloads, get_overloads, overload
|
36 | 36 | from typing_extensions import NamedTuple
|
37 | 37 | from typing_extensions import override, deprecated, Buffer
|
@@ -4286,5 +4286,90 @@ def __buffer__(self, flags: int) -> memoryview:
|
4286 | 4286 | self.assertIsSubclass(MySubclassedBuffer, Buffer)
|
4287 | 4287 |
|
4288 | 4288 |
|
| 4289 | +class GetOriginalBasesTests(BaseTestCase): |
| 4290 | + def test_basics(self): |
| 4291 | + T = TypeVar('T') |
| 4292 | + class A: pass |
| 4293 | + class B(Generic[T]): pass |
| 4294 | + class C(B[int]): pass |
| 4295 | + class D(B[str], float): pass |
| 4296 | + self.assertEqual(get_original_bases(A), (object,)) |
| 4297 | + self.assertEqual(get_original_bases(B), (Generic[T],)) |
| 4298 | + self.assertEqual(get_original_bases(C), (B[int],)) |
| 4299 | + self.assertEqual(get_original_bases(int), (object,)) |
| 4300 | + self.assertEqual(get_original_bases(D), (B[str], float)) |
| 4301 | + |
| 4302 | + with self.assertRaisesRegex(TypeError, "Expected an instance of type"): |
| 4303 | + get_original_bases(object()) |
| 4304 | + |
| 4305 | + @skipUnless(TYPING_3_9_0, "PEP 585 is yet to be") |
| 4306 | + def test_builtin_generics(self): |
| 4307 | + class E(list[T]): pass |
| 4308 | + class F(list[int]): pass |
| 4309 | + |
| 4310 | + self.assertEqual(get_original_bases(E), (list[T],)) |
| 4311 | + self.assertEqual(get_original_bases(F), (list[int],)) |
| 4312 | + |
| 4313 | + def test_namedtuples(self): |
| 4314 | + # On 3.12, this should work well with typing.NamedTuple and typing_extensions.NamedTuple |
| 4315 | + # On lower versions, it will only work fully with typing_extensions.NamedTuple |
| 4316 | + if sys.version_info >= (3, 12): |
| 4317 | + namedtuple_classes = (typing.NamedTuple, typing_extensions.NamedTuple) |
| 4318 | + else: |
| 4319 | + namedtuple_classes = (typing_extensions.NamedTuple,) |
| 4320 | + |
| 4321 | + for NamedTuple in namedtuple_classes: # noqa: F402 |
| 4322 | + with self.subTest(cls=NamedTuple): |
| 4323 | + class ClassBasedNamedTuple(NamedTuple): |
| 4324 | + x: int |
| 4325 | + |
| 4326 | + class GenericNamedTuple(NamedTuple, Generic[T]): |
| 4327 | + x: T |
| 4328 | + |
| 4329 | + CallBasedNamedTuple = NamedTuple("CallBasedNamedTuple", [("x", int)]) |
| 4330 | + |
| 4331 | + self.assertIs( |
| 4332 | + get_original_bases(ClassBasedNamedTuple)[0], NamedTuple |
| 4333 | + ) |
| 4334 | + self.assertEqual( |
| 4335 | + get_original_bases(GenericNamedTuple), |
| 4336 | + (NamedTuple, Generic[T]) |
| 4337 | + ) |
| 4338 | + self.assertIs( |
| 4339 | + get_original_bases(CallBasedNamedTuple)[0], NamedTuple |
| 4340 | + ) |
| 4341 | + |
| 4342 | + def test_typeddicts(self): |
| 4343 | + # On 3.12, this should work well with typing.TypedDict and typing_extensions.TypedDict |
| 4344 | + # On lower versions, it will only work fully with typing_extensions.TypedDict |
| 4345 | + if sys.version_info >= (3, 12): |
| 4346 | + typeddict_classes = (typing.TypedDict, typing_extensions.TypedDict) |
| 4347 | + else: |
| 4348 | + typeddict_classes = (typing_extensions.TypedDict,) |
| 4349 | + |
| 4350 | + for TypedDict in typeddict_classes: # noqa: F402 |
| 4351 | + with self.subTest(cls=TypedDict): |
| 4352 | + class ClassBasedTypedDict(TypedDict): |
| 4353 | + x: int |
| 4354 | + |
| 4355 | + class GenericTypedDict(TypedDict, Generic[T]): |
| 4356 | + x: T |
| 4357 | + |
| 4358 | + CallBasedTypedDict = TypedDict("CallBasedTypedDict", {"x": int}) |
| 4359 | + |
| 4360 | + self.assertIs( |
| 4361 | + get_original_bases(ClassBasedTypedDict)[0], |
| 4362 | + TypedDict |
| 4363 | + ) |
| 4364 | + self.assertEqual( |
| 4365 | + get_original_bases(GenericTypedDict), |
| 4366 | + (TypedDict, Generic[T]) |
| 4367 | + ) |
| 4368 | + self.assertIs( |
| 4369 | + get_original_bases(CallBasedTypedDict)[0], |
| 4370 | + TypedDict |
| 4371 | + ) |
| 4372 | + |
| 4373 | + |
4289 | 4374 | if __name__ == '__main__':
|
4290 | 4375 | main()
|
0 commit comments