Skip to content

Commit 0056701

Browse files
adriangbAlexWaygoodJelleZijlstra
authored
GH-103699: Add __orig_bases__ to various typing classes (#103698)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent e38bebb commit 0056701

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

Lib/test/test_typing.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6695,6 +6695,22 @@ def test_copy_and_pickle(self):
66956695
self.assertEqual(jane2, jane)
66966696
self.assertIsInstance(jane2, cls)
66976697

6698+
def test_orig_bases(self):
6699+
T = TypeVar('T')
6700+
6701+
class SimpleNamedTuple(NamedTuple):
6702+
pass
6703+
6704+
class GenericNamedTuple(NamedTuple, Generic[T]):
6705+
pass
6706+
6707+
self.assertEqual(SimpleNamedTuple.__orig_bases__, (NamedTuple,))
6708+
self.assertEqual(GenericNamedTuple.__orig_bases__, (NamedTuple, Generic[T]))
6709+
6710+
CallNamedTuple = NamedTuple('CallNamedTuple', [])
6711+
6712+
self.assertEqual(CallNamedTuple.__orig_bases__, (NamedTuple,))
6713+
66986714

66996715
class TypedDictTests(BaseTestCase):
67006716
def test_basics_functional_syntax(self):
@@ -7126,6 +7142,49 @@ class TD(TypedDict):
71267142
self.assertIs(type(a), dict)
71277143
self.assertEqual(a, {'a': 1})
71287144

7145+
def test_orig_bases(self):
7146+
T = TypeVar('T')
7147+
7148+
class Parent(TypedDict):
7149+
pass
7150+
7151+
class Child(Parent):
7152+
pass
7153+
7154+
class OtherChild(Parent):
7155+
pass
7156+
7157+
class MixedChild(Child, OtherChild, Parent):
7158+
pass
7159+
7160+
class GenericParent(TypedDict, Generic[T]):
7161+
pass
7162+
7163+
class GenericChild(GenericParent[int]):
7164+
pass
7165+
7166+
class OtherGenericChild(GenericParent[str]):
7167+
pass
7168+
7169+
class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]):
7170+
pass
7171+
7172+
class MultipleGenericBases(GenericParent[int], GenericParent[float]):
7173+
pass
7174+
7175+
CallTypedDict = TypedDict('CallTypedDict', {})
7176+
7177+
self.assertEqual(Parent.__orig_bases__, (TypedDict,))
7178+
self.assertEqual(Child.__orig_bases__, (Parent,))
7179+
self.assertEqual(OtherChild.__orig_bases__, (Parent,))
7180+
self.assertEqual(MixedChild.__orig_bases__, (Child, OtherChild, Parent,))
7181+
self.assertEqual(GenericParent.__orig_bases__, (TypedDict, Generic[T]))
7182+
self.assertEqual(GenericChild.__orig_bases__, (GenericParent[int],))
7183+
self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],))
7184+
self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float]))
7185+
self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float]))
7186+
self.assertEqual(CallTypedDict.__orig_bases__, (TypedDict,))
7187+
71297188

71307189
class RequiredTests(BaseTestCase):
71317190

Lib/typing.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,7 +2962,9 @@ class Employee(NamedTuple):
29622962
elif kwargs:
29632963
raise TypeError("Either list of fields or keywords"
29642964
" can be provided to NamedTuple, not both")
2965-
return _make_nmtuple(typename, fields, module=_caller())
2965+
nt = _make_nmtuple(typename, fields, module=_caller())
2966+
nt.__orig_bases__ = (NamedTuple,)
2967+
return nt
29662968

29672969
_NamedTuple = type.__new__(NamedTupleMeta, 'NamedTuple', (), {})
29682970

@@ -2994,6 +2996,9 @@ def __new__(cls, name, bases, ns, total=True):
29942996

29952997
tp_dict = type.__new__(_TypedDictMeta, name, (*generic_base, dict), ns)
29962998

2999+
if not hasattr(tp_dict, '__orig_bases__'):
3000+
tp_dict.__orig_bases__ = bases
3001+
29973002
annotations = {}
29983003
own_annotations = ns.get('__annotations__', {})
29993004
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
@@ -3104,7 +3109,9 @@ class body be required.
31043109
# Setting correct module is necessary to make typed dict classes pickleable.
31053110
ns['__module__'] = module
31063111

3107-
return _TypedDictMeta(typename, (), ns, total=total)
3112+
td = _TypedDictMeta(typename, (), ns, total=total)
3113+
td.__orig_bases__ = (TypedDict,)
3114+
return td
31083115

31093116
_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
31103117
TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``__orig_bases__`` to non-generic TypedDicts, call-based TypedDicts, and
2+
call-based NamedTuples. Other TypedDicts and NamedTuples already had the attribute.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy