Skip to content

[3.7] bpo-36321: Fix misspelled attribute in namedtuple() (GH-12375) #12395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Doc/library/collections.rst
Original file line number Diff line number Diff line change
Expand Up @@ -941,14 +941,14 @@ field names, the method and attribute names start with an underscore.
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

.. attribute:: somenamedtuple._fields_defaults
.. attribute:: somenamedtuple._field_defaults

Dictionary mapping field names to default values.

.. doctest::

>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
>>> Account._fields_defaults
>>> Account._field_defaults
{'balance': 0}
>>> Account('premium')
Account(type='premium', balance=0)
Expand Down
2 changes: 2 additions & 0 deletions Lib/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ def __getnewargs__(self):
'__doc__': f'{typename}({arg_list})',
'__slots__': (),
'_fields': field_names,
'_field_defaults': field_defaults,
# alternate spelling for backward compatiblity
'_fields_defaults': field_defaults,
'__new__': __new__,
'_make': _make,
Expand Down
12 changes: 6 additions & 6 deletions Lib/test/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,18 +249,18 @@ def test_factory(self):

def test_defaults(self):
Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
self.assertEqual(Point._fields_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point(1, 2), (1, 2))
self.assertEqual(Point(1), (1, 20))
self.assertEqual(Point(), (10, 20))

Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
self.assertEqual(Point._fields_defaults, {'y': 20})
self.assertEqual(Point._field_defaults, {'y': 20})
self.assertEqual(Point(1, 2), (1, 2))
self.assertEqual(Point(1), (1, 20))

Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
self.assertEqual(Point._fields_defaults, {})
self.assertEqual(Point._field_defaults, {})
self.assertEqual(Point(1, 2), (1, 2))
with self.assertRaises(TypeError):
Point(1)
Expand All @@ -277,21 +277,21 @@ def test_defaults(self):
Point = namedtuple('Point', 'x y', defaults=False)

Point = namedtuple('Point', 'x y', defaults=None) # default is None
self.assertEqual(Point._fields_defaults, {})
self.assertEqual(Point._field_defaults, {})
self.assertIsNone(Point.__new__.__defaults__, None)
self.assertEqual(Point(10, 20), (10, 20))
with self.assertRaises(TypeError): # catch too few args
Point(10)

Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
self.assertEqual(Point._fields_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point.__new__.__defaults__, (10, 20))
self.assertEqual(Point(1, 2), (1, 2))
self.assertEqual(Point(1), (1, 20))
self.assertEqual(Point(), (10, 20))

Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
self.assertEqual(Point._fields_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
self.assertEqual(Point.__new__.__defaults__, (10, 20))
self.assertEqual(Point(1, 2), (1, 2))
self.assertEqual(Point(1), (1, 20))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
collections.namedtuple() misspelled the name of an attribute. To be
consistent with typing.NamedTuple, the attribute name should have been
"_field_defaults" instead of "_fields_defaults". For backwards
compatibility, both spellings are now created. The misspelled version may
be removed in the future.