From 7a81c98be74123c022f813a51668861e2cb8ee8e Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 16:31:35 -0600 Subject: [PATCH 01/11] Add `__orig_bases__` to non-generic TypedDict --- Lib/test/test_typing.py | 3 +++ Lib/typing.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index f983efe956f902..1e581533b6ed66 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -7125,6 +7125,9 @@ class TD(TypedDict): a = A(a = 1) self.assertIs(type(a), dict) self.assertEqual(a, {'a': 1}) + + def test_orig_bases(self): + self.assertEqual(ChildTotalMovie.__orig_bases__, (ParentNontotalMovie,)) class RequiredTests(BaseTestCase): diff --git a/Lib/typing.py b/Lib/typing.py index 7c165562c2b53d..8408edc49a5b6e 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2994,6 +2994,9 @@ def __new__(cls, name, bases, ns, total=True): tp_dict = type.__new__(_TypedDictMeta, name, (*generic_base, dict), ns) + if not hasattr(tp_dict, '__orig_bases__'): + tp_dict.__orig_bases__ = bases + annotations = {} own_annotations = ns.get('__annotations__', {}) msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" From 270cadfcca6bf8a4f2be5cb5062100e7a030ba8b Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 22 Apr 2023 22:37:41 +0000 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst diff --git a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst new file mode 100644 index 00000000000000..5bf9b3ecd6c414 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst @@ -0,0 +1 @@ +Add `__orig_bases__` to non-generic TypedDicts From 29b643d2a93dc3e82998c60afd2c978228abdccd Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 16:38:20 -0600 Subject: [PATCH 03/11] Use double backticks --- .../next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst index 5bf9b3ecd6c414..1bf91d8cf9f863 100644 --- a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst +++ b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst @@ -1 +1 @@ -Add `__orig_bases__` to non-generic TypedDicts +Add ``__orig_bases__`` to non-generic TypedDicts From 4037df12250d4972651793f3d224da8e23ebe271 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 22 Apr 2023 17:37:02 -0600 Subject: [PATCH 04/11] remove whitespace --- Lib/test/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 1e581533b6ed66..bdf5bdc2d64a26 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -7125,7 +7125,7 @@ class TD(TypedDict): a = A(a = 1) self.assertIs(type(a), dict) self.assertEqual(a, {'a': 1}) - + def test_orig_bases(self): self.assertEqual(ChildTotalMovie.__orig_bases__, (ParentNontotalMovie,)) From 19569f901ca2c4711c13c02afde42fd65871f962 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:16:12 -0600 Subject: [PATCH 05/11] add more test cases --- Lib/test/test_typing.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index bdf5bdc2d64a26..86fb801c9129fb 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -7127,7 +7127,40 @@ class TD(TypedDict): self.assertEqual(a, {'a': 1}) def test_orig_bases(self): - self.assertEqual(ChildTotalMovie.__orig_bases__, (ParentNontotalMovie,)) + T = TypeVar('T') + + class Parent(TypedDict): + pass + + class Child(Parent): + pass + + class OtherChild(Parent): + pass + + class MixedChild(Child, OtherChild, Parent): + pass + + class GenericParent(TypedDict, Generic[T]): + pass + + class GenericChild(GenericParent[int]): + pass + + class OtherGenericChild(GenericParent[str]): + pass + + class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): + pass + + self.assertEqual(Parent.__orig_bases__, (TypedDict,)) + self.assertEqual(Child.__orig_bases__, (Parent,)) + self.assertEqual(OtherChild.__orig_bases__, (Parent,)) + self.assertEqual(MixedChild.__orig_bases__, (Child, OtherChild, Parent,)) + self.assertEqual(GenericParent.__orig_bases__, (TypedDict, Generic[T])) + self.assertEqual(GenericChild.__orig_bases__, (GenericParent[int],)) + self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],)) + self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float])) class RequiredTests(BaseTestCase): From b777373b1719331aec2aab2649cb4d804a490f66 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:18:56 -0600 Subject: [PATCH 06/11] one more test --- Lib/test/test_typing.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 86fb801c9129fb..c8ed4ae605f1ef 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -7153,6 +7153,9 @@ class OtherGenericChild(GenericParent[str]): class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): pass + class MultipleGenericBases(GenericParent[int], GenericParent[float]): + pass + self.assertEqual(Parent.__orig_bases__, (TypedDict,)) self.assertEqual(Child.__orig_bases__, (Parent,)) self.assertEqual(OtherChild.__orig_bases__, (Parent,)) @@ -7161,6 +7164,7 @@ class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): self.assertEqual(GenericChild.__orig_bases__, (GenericParent[int],)) self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],)) self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float])) + self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float])) class RequiredTests(BaseTestCase): From 4c9ee8ca0ea7c15a5ba906079dad688db6c1a847 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 23:02:45 -0600 Subject: [PATCH 07/11] Make call-based NamedTuples behave like call-based TypedDicts Co-authored-by: Alex Waygood --- Lib/typing.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/typing.py b/Lib/typing.py index 8408edc49a5b6e..354bc80eb3abfa 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2962,7 +2962,9 @@ class Employee(NamedTuple): elif kwargs: raise TypeError("Either list of fields or keywords" " can be provided to NamedTuple, not both") - return _make_nmtuple(typename, fields, module=_caller()) + nt = _make_nmtuple(typename, fields, module=_caller()) + nt.__orig_bases__ = (NamedTuple,) + return nt _NamedTuple = type.__new__(NamedTupleMeta, 'NamedTuple', (), {}) @@ -3107,7 +3109,9 @@ class body be required. # Setting correct module is necessary to make typed dict classes pickleable. ns['__module__'] = module - return _TypedDictMeta(typename, (), ns, total=total) + td = _TypedDictMeta(typename, (), ns, total=total) + td.__orig_bases__ = (TypedDict,) + return td _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) TypedDict.__mro_entries__ = lambda bases: (_TypedDict,) From 7224ddd2ed79f0d8cbdcf18e3b0444fa3319abab Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 23:07:28 -0600 Subject: [PATCH 08/11] Add (failing) tests --- Lib/test/test_typing.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index c8ed4ae605f1ef..219b0e7b9fc6e3 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -6695,6 +6695,46 @@ def test_copy_and_pickle(self): self.assertEqual(jane2, jane) self.assertIsInstance(jane2, cls) + def test_orig_bases(self): + T = TypeVar('T') + + class Parent(NamedTuple): + pass + + class Child(Parent): + pass + + class OtherChild(Parent): + pass + + class MixedChild(Child, OtherChild, Parent): + pass + + class GenericParent(NamedTuple, Generic[T]): + pass + + class GenericChild(GenericParent[int]): + pass + + class OtherGenericChild(GenericParent[str]): + pass + + class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): + pass + + class MultipleGenericBases(GenericParent[int], GenericParent[float]): + pass + + self.assertEqual(Parent.__orig_bases__, (NamedTuple,)) + self.assertEqual(Child.__orig_bases__, (Parent,)) + self.assertEqual(OtherChild.__orig_bases__, (Parent,)) + self.assertEqual(MixedChild.__orig_bases__, (Child, OtherChild, Parent,)) + self.assertEqual(GenericParent.__orig_bases__, (NamedTuple, Generic[T])) + self.assertEqual(GenericChild.__orig_bases__, (GenericParent[int],)) + self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],)) + self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float])) + self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float])) + class TypedDictTests(BaseTestCase): def test_basics_functional_syntax(self): From 631d428317988c74f1a0277cde0392a19698aa56 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sat, 22 Apr 2023 23:18:41 -0600 Subject: [PATCH 09/11] More tests --- Lib/test/test_typing.py | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 219b0e7b9fc6e3..715710be9e86b8 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -6698,42 +6698,18 @@ def test_copy_and_pickle(self): def test_orig_bases(self): T = TypeVar('T') - class Parent(NamedTuple): + class SimpleNamedTuple(NamedTuple): pass - class Child(Parent): - pass - - class OtherChild(Parent): - pass - - class MixedChild(Child, OtherChild, Parent): + class GenericNamedTuple(NamedTuple, Generic[T]): pass - class GenericParent(NamedTuple, Generic[T]): - pass + self.assertEqual(SimpleNamedTuple.__orig_bases__, (NamedTuple,)) + self.assertEqual(GenericNamedTuple.__orig_bases__, (NamedTuple, Generic[T])) - class GenericChild(GenericParent[int]): - pass + CallNamedTuple = NamedTuple('CallNamedTuple', []) - class OtherGenericChild(GenericParent[str]): - pass - - class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): - pass - - class MultipleGenericBases(GenericParent[int], GenericParent[float]): - pass - - self.assertEqual(Parent.__orig_bases__, (NamedTuple,)) - self.assertEqual(Child.__orig_bases__, (Parent,)) - self.assertEqual(OtherChild.__orig_bases__, (Parent,)) - self.assertEqual(MixedChild.__orig_bases__, (Child, OtherChild, Parent,)) - self.assertEqual(GenericParent.__orig_bases__, (NamedTuple, Generic[T])) - self.assertEqual(GenericChild.__orig_bases__, (GenericParent[int],)) - self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],)) - self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float])) - self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float])) + self.assertEqual(CallNamedTuple.__orig_bases__, (NamedTuple,)) class TypedDictTests(BaseTestCase): @@ -7196,6 +7172,8 @@ class MixedGenericChild(GenericChild, OtherGenericChild, GenericParent[float]): class MultipleGenericBases(GenericParent[int], GenericParent[float]): pass + CallTypedDict = TypedDict('CallTypedDict', {}) + self.assertEqual(Parent.__orig_bases__, (TypedDict,)) self.assertEqual(Child.__orig_bases__, (Parent,)) self.assertEqual(OtherChild.__orig_bases__, (Parent,)) @@ -7205,6 +7183,7 @@ class MultipleGenericBases(GenericParent[int], GenericParent[float]): self.assertEqual(OtherGenericChild.__orig_bases__, (GenericParent[str],)) self.assertEqual(MixedGenericChild.__orig_bases__, (GenericChild, OtherGenericChild, GenericParent[float])) self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float])) + self.assertEqual(CallTypedDict.__orig_bases__, (TypedDict,)) class RequiredTests(BaseTestCase): From 58701ac75799e1c7231d054408314134938b6132 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sun, 23 Apr 2023 00:20:53 -0500 Subject: [PATCH 10/11] Update Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst Co-authored-by: Alex Waygood --- .../Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst index 1bf91d8cf9f863..3d5c1a261962ff 100644 --- a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst +++ b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst @@ -1 +1,2 @@ -Add ``__orig_bases__`` to non-generic TypedDicts +Add ``__orig_bases__`` to non-generic TypedDicts, call-based TypedDicts, and +call-based NamedTuples From 3fe75eb478bc11ade95cf7b7989f60e481e0da36 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sun, 23 Apr 2023 07:13:52 -0600 Subject: [PATCH 11/11] Update Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst Co-authored-by: Jelle Zijlstra --- .../next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst index 3d5c1a261962ff..60547a25a109bc 100644 --- a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst +++ b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst @@ -1,2 +1,2 @@ Add ``__orig_bases__`` to non-generic TypedDicts, call-based TypedDicts, and -call-based NamedTuples +call-based NamedTuples. Other TypedDicts and NamedTuples already had the attribute.