From dbb00062dc3afb12c41c87564e6faefe60766b01 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Mon, 14 Dec 2020 14:33:27 -0800 Subject: bpo-42059: Fix required/optional keys for TypedDict(..., total=False) (GH-22736) (GH-23747) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 67b769f5157c9dad1c7dd6b24e067b9fdab5b35d) Co-authored-by: Alex Grönholm --- Lib/test/test_typing.py | 4 ++++ Lib/typing.py | 4 ++-- Misc/NEWS.d/next/Library/2020-10-17-12-42-08.bpo-42059.ZGMZ3D.rst | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-10-17-12-42-08.bpo-42059.ZGMZ3D.rst diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 04dd6df..3b3aa29 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -3891,10 +3891,14 @@ class TypedDictTests(BaseTestCase): self.assertEqual(D(), {}) self.assertEqual(D(x=1), {'x': 1}) self.assertEqual(D.__total__, False) + self.assertEqual(D.__required_keys__, frozenset()) + self.assertEqual(D.__optional_keys__, {'x'}) self.assertEqual(Options(), {}) self.assertEqual(Options(log_level=2), {'log_level': 2}) self.assertEqual(Options.__total__, False) + self.assertEqual(Options.__required_keys__, frozenset()) + self.assertEqual(Options.__optional_keys__, {'log_level', 'log_path'}) def test_optional_keys(self): class Point2Dor3D(Point2D, total=False): diff --git a/Lib/typing.py b/Lib/typing.py index 1d6584d..81e4a2f 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1987,14 +1987,14 @@ def TypedDict(typename, fields=None, /, *, total=True, **kwargs): raise TypeError("TypedDict takes either a dict or keyword arguments," " but not both") - ns = {'__annotations__': dict(fields), '__total__': total} + ns = {'__annotations__': dict(fields)} try: # Setting correct module is necessary to make typed dict classes pickleable. ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): pass - return _TypedDictMeta(typename, (), ns) + return _TypedDictMeta(typename, (), ns, total=total) _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) TypedDict.__mro_entries__ = lambda bases: (_TypedDict,) diff --git a/Misc/NEWS.d/next/Library/2020-10-17-12-42-08.bpo-42059.ZGMZ3D.rst b/Misc/NEWS.d/next/Library/2020-10-17-12-42-08.bpo-42059.ZGMZ3D.rst new file mode 100644 index 0000000..3f18824 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-10-17-12-42-08.bpo-42059.ZGMZ3D.rst @@ -0,0 +1 @@ +:class:`typing.TypedDict` types created using the alternative call-style syntax now correctly respect the ``total`` keyword argument when setting their ``__required_keys__`` and ``__optional_keys__`` class attributes. -- cgit v0.12