From f7b57df0c09c3a04ab27ba06eb2feb989bbb16cb Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 18 Mar 2019 09:53:56 -0700 Subject: [PATCH] bpo-36320: Switch typing.NamedTuple from OrderedDict to regular dict (GH-12396) Also, deprecate the *_field_types* attributes which duplicated the information in *\__annotations__*. https://bugs.python.org/issue36320 --- Doc/library/typing.rst | 18 ++++++++++++++---- Doc/whatsnew/3.8.rst | 4 ++++ Lib/typing.py | 16 +++++++--------- .../2019-03-18-01-08-14.bpo-36320.-06b9_.rst | 3 +++ 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-03-18-01-08-14.bpo-36320.-06b9_.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index de03284dfbb..fad9dc69431 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -838,10 +838,11 @@ The module defines the following classes, functions and decorators: Fields with a default value must come after any fields without a default. - The resulting class has two extra attributes: ``_field_types``, - giving a dict mapping field names to types, and ``_field_defaults``, a dict - mapping field names to default values. (The field names are in the - ``_fields`` attribute, which is part of the namedtuple API.) + The resulting class has an extra attribute ``__annotations__`` giving a + dict that maps the field names to the field types. (The field names are in + the ``_fields`` attribute and the default values are in the + ``_field_defaults`` attribute both of which are part of the namedtuple + API.) ``NamedTuple`` subclasses can also have docstrings and methods:: @@ -863,6 +864,15 @@ The module defines the following classes, functions and decorators: .. versionchanged:: 3.6.1 Added support for default values, methods, and docstrings. + .. versionchanged:: 3.8 + Deprecated the ``_field_types`` attribute in favor of the more + standard ``__annotations__`` attribute which has the same information. + + .. versionchanged:: 3.8 + The ``_field_types`` and ``__annotations__`` attributes are + now regular dictionaries instead of instances of ``OrderedDict``. + + .. function:: NewType(typ) A helper function to indicate a distinct types to a typechecker, diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 31baccd9d68..2e311ab1c1f 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -510,6 +510,10 @@ Deprecated (Contributed by Berker Peksag in :issue:`9372`.) +* The :class:`typing.NamedTuple` class has deprecated the ``_field_types`` + attribute in favor of the ``__annotations__`` attribute which has the same + information. (Contributed by Raymond Hettinger in :issue:`36320`.) + * :mod:`ast` classes ``Num``, ``Str``, ``Bytes``, ``NameConstant`` and ``Ellipsis`` are considered deprecated and will be removed in future Python versions. :class:`~ast.Constant` should be used instead. diff --git a/Lib/typing.py b/Lib/typing.py index 3243e2af111..530d4633fe4 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1325,8 +1325,8 @@ def _make_nmtuple(name, types): types = [(n, _type_check(t, msg)) for n, t in types] nm_tpl = collections.namedtuple(name, [n for n, t in types]) # Prior to PEP 526, only _field_types attribute was assigned. - # Now, both __annotations__ and _field_types are used to maintain compatibility. - nm_tpl.__annotations__ = nm_tpl._field_types = collections.OrderedDict(types) + # Now __annotations__ are used and _field_types is deprecated (remove in 3.9) + nm_tpl.__annotations__ = nm_tpl._field_types = dict(types) try: nm_tpl.__module__ = sys._getframe(2).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): @@ -1361,7 +1361,7 @@ class NamedTupleMeta(type): "follow default field(s) {default_names}" .format(field_name=field_name, default_names=', '.join(defaults_dict.keys()))) - nm_tpl.__new__.__annotations__ = collections.OrderedDict(types) + nm_tpl.__new__.__annotations__ = dict(types) nm_tpl.__new__.__defaults__ = tuple(defaults) nm_tpl._field_defaults = defaults_dict # update from user namespace without overriding special namedtuple attributes @@ -1386,12 +1386,10 @@ class NamedTuple(metaclass=NamedTupleMeta): Employee = collections.namedtuple('Employee', ['name', 'id']) - The resulting class has extra __annotations__ and _field_types - attributes, giving an ordered dict mapping field names to types. - __annotations__ should be preferred, while _field_types - is kept to maintain pre PEP 526 compatibility. (The field names - are in the _fields attribute, which is part of the namedtuple - API.) Alternative equivalent keyword syntax is also accepted:: + The resulting class has an extra __annotations__ attribute, giving a + dict that maps field names to types. (The field names are also in + the _fields attribute, which is part of the namedtuple API.) + Alternative equivalent keyword syntax is also accepted:: Employee = NamedTuple('Employee', name=str, id=int) diff --git a/Misc/NEWS.d/next/Library/2019-03-18-01-08-14.bpo-36320.-06b9_.rst b/Misc/NEWS.d/next/Library/2019-03-18-01-08-14.bpo-36320.-06b9_.rst new file mode 100644 index 00000000000..9e9495f46b7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-18-01-08-14.bpo-36320.-06b9_.rst @@ -0,0 +1,3 @@ +The typing.NamedTuple() class has deprecated the _field_types attribute in +favor of the __annotations__ attribute which carried the same information. +Also, both attributes were converted from OrderedDict to a regular dict.