From 0c12774adb2d8e7b72f34d0c8aa0a22d51740e75 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Fri, 4 Feb 2022 15:21:03 +0800 Subject: [PATCH 01/11] Remove kwargs syntax for TypedDict --- Doc/library/typing.rst | 8 +++++--- Lib/test/test_typing.py | 31 ++----------------------------- Lib/typing.py | 10 ++-------- 3 files changed, 9 insertions(+), 40 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9007c0daf59a4d..d8162a8c0cc9bb 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1388,10 +1388,9 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__total__``, ``Point2D.__required_keys__``, and ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not - support :pep:`526`, ``TypedDict`` supports two additional equivalent - syntactic forms:: + support :pep:`526`, ``TypedDict`` supports an additional equivalent + syntactic form:: - Point2D = TypedDict('Point2D', x=int, y=int, label=str) Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) By default, all keys must be present in a ``TypedDict``. It is possible to @@ -1402,6 +1401,9 @@ These are not used in annotations. They are building blocks for declaring types. x: int y: int + # Alternative syntax + Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False) + This means that a ``Point2D`` ``TypedDict`` can have any of the keys omitted. A type checker is only expected to support a literal ``False`` or ``True`` as the value of the ``total`` argument. ``True`` is the default, diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 85f74064458f2d..8db0acf38a2a85 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4299,33 +4299,6 @@ def test_basics_functional_syntax(self): self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) self.assertEqual(Emp.__total__, True) - def test_basics_keywords_syntax(self): - Emp = TypedDict('Emp', name=str, id=int) - self.assertIsSubclass(Emp, dict) - self.assertIsSubclass(Emp, typing.MutableMapping) - self.assertNotIsSubclass(Emp, collections.abc.Sequence) - jim = Emp(name='Jim', id=1) - self.assertIs(type(jim), dict) - self.assertEqual(jim['name'], 'Jim') - self.assertEqual(jim['id'], 1) - self.assertEqual(Emp.__name__, 'Emp') - self.assertEqual(Emp.__module__, __name__) - self.assertEqual(Emp.__bases__, (dict,)) - self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) - self.assertEqual(Emp.__total__, True) - - def test_typeddict_special_keyword_names(self): - TD = TypedDict("TD", cls=type, self=object, typename=str, _typename=int, fields=list, _fields=dict) - self.assertEqual(TD.__name__, 'TD') - self.assertEqual(TD.__annotations__, {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) - a = TD(cls=str, self=42, typename='foo', _typename=53, fields=[('bar', tuple)], _fields={'baz', set}) - self.assertEqual(a['cls'], str) - self.assertEqual(a['self'], 42) - self.assertEqual(a['typename'], 'foo') - self.assertEqual(a['_typename'], 53) - self.assertEqual(a['fields'], [('bar', tuple)]) - self.assertEqual(a['_fields'], {'baz', set}) - def test_typeddict_create_errors(self): with self.assertRaises(TypeError): TypedDict.__new__() @@ -4371,7 +4344,7 @@ def test_py36_class_syntax_usage(self): def test_pickle(self): global EmpD # pickle wants to reference the class by name - EmpD = TypedDict('EmpD', name=str, id=int) + EmpD = TypedDict('EmpD', {'name': str, 'id': int}) jane = EmpD({'name': 'jane', 'id': 37}) for proto in range(pickle.HIGHEST_PROTOCOL + 1): z = pickle.dumps(jane, proto) @@ -4383,7 +4356,7 @@ def test_pickle(self): self.assertEqual(EmpDnew({'name': 'jane', 'id': 37}), jane) def test_optional(self): - EmpD = TypedDict('EmpD', name=str, id=int) + EmpD = TypedDict('EmpD', {'name': str, 'id': int}) self.assertEqual(typing.Optional[EmpD], typing.Union[None, EmpD]) self.assertNotEqual(typing.List[EmpD], typing.Tuple[EmpD]) diff --git a/Lib/typing.py b/Lib/typing.py index 0cf9755022e9b8..8239149c2fac6d 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2378,7 +2378,7 @@ def __subclasscheck__(cls, other): __instancecheck__ = __subclasscheck__ -def TypedDict(typename, fields=None, /, *, total=True, **kwargs): +def TypedDict(typename, fields=None, /, *, total=True): """A simple typed namespace. At runtime it is equivalent to a plain dict. TypedDict creates a dictionary type that expects all of its @@ -2399,9 +2399,8 @@ class Point2D(TypedDict): The type info can be accessed via the Point2D.__annotations__ dict, and the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. - TypedDict supports two additional equivalent forms:: + TypedDict supports an additional equivalent form:: - Point2D = TypedDict('Point2D', x=int, y=int, label=str) Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) By default, all keys must be present in a TypedDict. It is possible @@ -2420,11 +2419,6 @@ class body be required. The class syntax is only supported in Python 3.6+, while two other syntax forms work for Python 2.7 and 3.2+ """ - if fields is None: - fields = kwargs - elif kwargs: - raise TypeError("TypedDict takes either a dict or keyword arguments," - " but not both") ns = {'__annotations__': dict(fields)} module = _caller() From f3588ac8ba55ec7d629eac36b7f504d2ba9d3c3b Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Tue, 8 Feb 2022 01:58:41 +0800 Subject: [PATCH 02/11] Add deprecation flag and warning --- Doc/library/typing.rst | 9 +++++++-- Lib/test/test_typing.py | 28 ++++++++++++++++++++++++++++ Lib/typing.py | 14 +++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index d8162a8c0cc9bb..938cf10874b05a 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1388,10 +1388,15 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__total__``, ``Point2D.__required_keys__``, and ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not - support :pep:`526`, ``TypedDict`` supports an additional equivalent - syntactic form:: + support :pep:`526`, ``TypedDict`` supports two additional equivalent + syntactic forms:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + Point2D = TypedDict('Point2D', x=int, y=int, label=str) + + .. deprecated-removed:: 3.11 3.13 + The keyword arguments syntax is deprecated in 3.11 and will be removed + in 3.13. Currently it might not be supported by typecheckers like ``mypy``. By default, all keys must be present in a ``TypedDict``. It is possible to override this by specifying totality. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 8db0acf38a2a85..1ba31ad397606e 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4299,6 +4299,34 @@ def test_basics_functional_syntax(self): self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) self.assertEqual(Emp.__total__, True) + def test_basics_keywords_syntax(self): + with self.assertWarns(DeprecationWarning): + Emp = TypedDict('Emp', name=str, id=int) + self.assertIsSubclass(Emp, dict) + self.assertIsSubclass(Emp, typing.MutableMapping) + self.assertNotIsSubclass(Emp, collections.abc.Sequence) + jim = Emp(name='Jim', id=1) + self.assertIs(type(jim), dict) + self.assertEqual(jim['name'], 'Jim') + self.assertEqual(jim['id'], 1) + self.assertEqual(Emp.__name__, 'Emp') + self.assertEqual(Emp.__module__, __name__) + self.assertEqual(Emp.__bases__, (dict,)) + self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) + self.assertEqual(Emp.__total__, True) + + def test_typeddict_special_keyword_names(self): + TD = TypedDict("TD", {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) + self.assertEqual(TD.__name__, 'TD') + self.assertEqual(TD.__annotations__, {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) + a = TD(cls=str, self=42, typename='foo', _typename=53, fields=[('bar', tuple)], _fields={'baz', set}) + self.assertEqual(a['cls'], str) + self.assertEqual(a['self'], 42) + self.assertEqual(a['typename'], 'foo') + self.assertEqual(a['_typename'], 53) + self.assertEqual(a['fields'], [('bar', tuple)]) + self.assertEqual(a['_fields'], {'baz', set}) + def test_typeddict_create_errors(self): with self.assertRaises(TypeError): TypedDict.__new__() diff --git a/Lib/typing.py b/Lib/typing.py index 8239149c2fac6d..df6c2aabe1c96a 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2378,7 +2378,7 @@ def __subclasscheck__(cls, other): __instancecheck__ = __subclasscheck__ -def TypedDict(typename, fields=None, /, *, total=True): +def TypedDict(typename, fields=None, /, *, total=True, **kwargs): """A simple typed namespace. At runtime it is equivalent to a plain dict. TypedDict creates a dictionary type that expects all of its @@ -2419,6 +2419,18 @@ class body be required. The class syntax is only supported in Python 3.6+, while two other syntax forms work for Python 2.7 and 3.2+ """ + if fields is None: + fields = kwargs + elif kwargs: + raise TypeError("TypedDict takes either a dict or keyword arguments," + " but not both") + if kwargs: + warnings.warn( + "The kwargs-based syntax for TypedDict definition is deprecated " + " in Python 3.11 and will be removed in Python 3.13.", + DeprecationWarning, + stacklevel=2, + ) ns = {'__annotations__': dict(fields)} module = _caller() From 4d988a8570ee8bf09a2b94e53fedb4233d9b5611 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Tue, 8 Feb 2022 16:43:23 +0800 Subject: [PATCH 03/11] Add blurb and address reviews --- Doc/library/typing.rst | 8 ++++++-- Lib/typing.py | 4 ++-- .../next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 938cf10874b05a..ecc19b940f9574 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1389,14 +1389,18 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not support :pep:`526`, ``TypedDict`` supports two additional equivalent - syntactic forms:: + syntactic forms. + Using dict as the second argument:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + + Using keyword arguments:: + Point2D = TypedDict('Point2D', x=int, y=int, label=str) .. deprecated-removed:: 3.11 3.13 The keyword arguments syntax is deprecated in 3.11 and will be removed - in 3.13. Currently it might not be supported by typecheckers like ``mypy``. + in 3.13. Currently it might not be supported by typecheckers. By default, all keys must be present in a ``TypedDict``. It is possible to override this by specifying totality. diff --git a/Lib/typing.py b/Lib/typing.py index df6c2aabe1c96a..5cfbd9bbdfbbb1 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2416,8 +2416,8 @@ class point2D(TypedDict, total=False): the total argument. True is the default, and makes all items defined in the class body be required. - The class syntax is only supported in Python 3.6+, while two other - syntax forms work for Python 2.7 and 3.2+ + The class syntax is only supported in Python 3.6+, while the other + syntax form works for Python 2.7 and 3.2+ """ if fields is None: fields = kwargs diff --git a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst new file mode 100644 index 00000000000000..fce4136864fdf7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst @@ -0,0 +1 @@ +Remove kwargs-based syntax for TypedDict definition From f21c30ae3bfd63e9a3837f9d831f6802ae6ea50d Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Tue, 8 Feb 2022 23:46:28 +0800 Subject: [PATCH 04/11] Change docs Co-authored-by: AlexWaygood --- Doc/library/typing.rst | 10 +++++----- Lib/test/test_typing.py | 24 ++++++++++++------------ Lib/typing.py | 5 +++-- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index ecc19b940f9574..0c13d993b3f65e 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1389,18 +1389,18 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not support :pep:`526`, ``TypedDict`` supports two additional equivalent - syntactic forms. - Using dict as the second argument:: + syntactic forms. Firstly, using a literal :class:`dict` as the + second argument:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) - Using keyword arguments:: + Secondly, using keyword arguments:: Point2D = TypedDict('Point2D', x=int, y=int, label=str) .. deprecated-removed:: 3.11 3.13 - The keyword arguments syntax is deprecated in 3.11 and will be removed - in 3.13. Currently it might not be supported by typecheckers. + The keyword-argument syntax is deprecated in 3.11 and will be removed + in 3.13. It may also be unsupported by third-party type-checking tools. By default, all keys must be present in a ``TypedDict``. It is possible to override this by specifying totality. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 1ba31ad397606e..c15e873cab6cf6 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4302,18 +4302,18 @@ def test_basics_functional_syntax(self): def test_basics_keywords_syntax(self): with self.assertWarns(DeprecationWarning): Emp = TypedDict('Emp', name=str, id=int) - self.assertIsSubclass(Emp, dict) - self.assertIsSubclass(Emp, typing.MutableMapping) - self.assertNotIsSubclass(Emp, collections.abc.Sequence) - jim = Emp(name='Jim', id=1) - self.assertIs(type(jim), dict) - self.assertEqual(jim['name'], 'Jim') - self.assertEqual(jim['id'], 1) - self.assertEqual(Emp.__name__, 'Emp') - self.assertEqual(Emp.__module__, __name__) - self.assertEqual(Emp.__bases__, (dict,)) - self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) - self.assertEqual(Emp.__total__, True) + self.assertIsSubclass(Emp, dict) + self.assertIsSubclass(Emp, typing.MutableMapping) + self.assertNotIsSubclass(Emp, collections.abc.Sequence) + jim = Emp(name='Jim', id=1) + self.assertIs(type(jim), dict) + self.assertEqual(jim['name'], 'Jim') + self.assertEqual(jim['id'], 1) + self.assertEqual(Emp.__name__, 'Emp') + self.assertEqual(Emp.__module__, __name__) + self.assertEqual(Emp.__bases__, (dict,)) + self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) + self.assertEqual(Emp.__total__, True) def test_typeddict_special_keyword_names(self): TD = TypedDict("TD", {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) diff --git a/Lib/typing.py b/Lib/typing.py index 5cfbd9bbdfbbb1..4189771e673a31 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2426,8 +2426,9 @@ class body be required. " but not both") if kwargs: warnings.warn( - "The kwargs-based syntax for TypedDict definition is deprecated " - " in Python 3.11 and will be removed in Python 3.13.", + "The kwargs-based syntax for TypedDict definitions is deprecated " + "in Python 3.11, will be removed in Python 3.13, and may not be " + "understood by third-party type checkers.", DeprecationWarning, stacklevel=2, ) From 3f60fb0bed883eaf7ea011ebb63982ff450fcb07 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Tue, 8 Feb 2022 23:46:50 +0800 Subject: [PATCH 05/11] Add name --- Misc/ACKS | 1 + .../next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Misc/ACKS b/Misc/ACKS index 6df339c3e145bf..9dee7992cde05f 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1976,6 +1976,7 @@ Masayuki Yamamoto Ka-Ping Yee Chi Hsuan Yen Jason Yeo +Jingchen Ye EungJun Yi Bob Yodlowski Danny Yoo diff --git a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst index fce4136864fdf7..1af4dd3997ca5f 100644 --- a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst +++ b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst @@ -1 +1,2 @@ -Remove kwargs-based syntax for TypedDict definition +Deprecate kwargs-based syntax for :class:`typing.TypedDict` definitions. +It was unsupported by type checkers. Patch by Jingchen Ye. \ No newline at end of file From 033cf07be9a90ea17f932c7b6f58df577648b11a Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Wed, 9 Feb 2022 00:26:55 +0800 Subject: [PATCH 06/11] Fix --- Doc/library/typing.rst | 4 ++-- Misc/ACKS | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 0c13d993b3f65e..187747e88581ce 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1393,9 +1393,9 @@ These are not used in annotations. They are building blocks for declaring types. second argument:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) - + Secondly, using keyword arguments:: - + Point2D = TypedDict('Point2D', x=int, y=int, label=str) .. deprecated-removed:: 3.11 3.13 diff --git a/Misc/ACKS b/Misc/ACKS index 9dee7992cde05f..eaaaf7259dc192 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1973,10 +1973,10 @@ Arnon Yaari Alakshendra Yadav Hirokazu Yamamoto Masayuki Yamamoto +Jingchen Ye Ka-Ping Yee Chi Hsuan Yen Jason Yeo -Jingchen Ye EungJun Yi Bob Yodlowski Danny Yoo From eea168f06ae240e5e4f1716e56489ff24fdd1fba Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Wed, 9 Feb 2022 19:25:43 +0800 Subject: [PATCH 07/11] Modify docs --- Doc/library/typing.rst | 2 +- Lib/test/test_typing.py | 3 ++- .../next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 187747e88581ce..6784380b6a8822 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1400,7 +1400,7 @@ These are not used in annotations. They are building blocks for declaring types. .. deprecated-removed:: 3.11 3.13 The keyword-argument syntax is deprecated in 3.11 and will be removed - in 3.13. It may also be unsupported by third-party type-checking tools. + in 3.13. It may also be unsupported by static type checkers. By default, all keys must be present in a ``TypedDict``. It is possible to override this by specifying totality. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index c15e873cab6cf6..b0754c9500edb9 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4316,7 +4316,8 @@ def test_basics_keywords_syntax(self): self.assertEqual(Emp.__total__, True) def test_typeddict_special_keyword_names(self): - TD = TypedDict("TD", {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) + with self.assertWarns(DeprecationWarning): + TD = TypedDict("TD", cls=type, self=object, typename=str, _typename=int, fields=list, _fields=dict) self.assertEqual(TD.__name__, 'TD') self.assertEqual(TD.__annotations__, {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) a = TD(cls=str, self=42, typename='foo', _typename=53, fields=[('bar', tuple)], _fields={'baz', set}) diff --git a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst index 1af4dd3997ca5f..d4681633fa9d83 100644 --- a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst +++ b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst @@ -1,2 +1,3 @@ Deprecate kwargs-based syntax for :class:`typing.TypedDict` definitions. -It was unsupported by type checkers. Patch by Jingchen Ye. \ No newline at end of file +It had confusing semantics when specifying totality, and was largely unused. +Patch by Jingchen Ye. \ No newline at end of file From 15a7930fef47f604ca59acbcf6a6670a9a296dc2 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Sun, 13 Feb 2022 15:16:56 +0800 Subject: [PATCH 08/11] Use bullet list --- Doc/library/typing.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 6784380b6a8822..39adfc917802a1 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1388,13 +1388,13 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__total__``, ``Point2D.__required_keys__``, and ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not - support :pep:`526`, ``TypedDict`` supports two additional equivalent - syntactic forms. Firstly, using a literal :class:`dict` as the - second argument:: + support :pep:`526`, ``TypedDict`` can be created using a functional form: + + * Using a literal :class:`dict` as the second argument:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) - Secondly, using keyword arguments:: + * Using keyword arguments:: Point2D = TypedDict('Point2D', x=int, y=int, label=str) From b9badea8616805fdc8527f3e6fb2e29ea87ecb64 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Sun, 13 Feb 2022 18:09:41 +0800 Subject: [PATCH 09/11] Fix --- Doc/library/typing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 39adfc917802a1..9adc88eed5bb25 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1389,7 +1389,7 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not support :pep:`526`, ``TypedDict`` can be created using a functional form: - + * Using a literal :class:`dict` as the second argument:: Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) From a6a870c6cc6a1a6d6663e1d7389d37d61d5da554 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@gmail.com> Date: Sun, 13 Feb 2022 20:05:08 +0800 Subject: [PATCH 10/11] Fix --- .../next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst index d4681633fa9d83..d13d9421e748b8 100644 --- a/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst +++ b/Misc/NEWS.d/next/Library/2022-02-08-16-42-20.bpo-46066.m32Hl0.rst @@ -1,3 +1,3 @@ Deprecate kwargs-based syntax for :class:`typing.TypedDict` definitions. It had confusing semantics when specifying totality, and was largely unused. -Patch by Jingchen Ye. \ No newline at end of file +Patch by Jingchen Ye. From 8b113dd3b075674e1e4d05f4eead7d4b15c62e05 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Tue, 15 Feb 2022 15:37:44 +0800 Subject: [PATCH 11/11] reverse --- Doc/library/typing.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9adc88eed5bb25..fe0f475a492cd7 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1388,7 +1388,8 @@ These are not used in annotations. They are building blocks for declaring types. ``Point2D.__total__``, ``Point2D.__required_keys__``, and ``Point2D.__optional_keys__``. To allow using this feature with older versions of Python that do not - support :pep:`526`, ``TypedDict`` can be created using a functional form: + support :pep:`526`, ``TypedDict`` supports two additional equivalent + syntactic forms: * Using a literal :class:`dict` as the second argument::