cpython: 59829d7b7838 (original) (raw)
Mercurial > cpython
changeset 106221:59829d7b7838 3.5
Issue #28556: allow default values in class form of NamedTuple -- Jelle Zijlstra [#28556]
Guido van Rossum guido@python.org | |
---|---|
date | Wed, 18 Jan 2017 08:03:50 -0800 |
parents | f2fe00653d07 |
children | 2159f36ccd6b 87e8139420ed |
files | Lib/test/test_typing.py Lib/typing.py |
diffstat | 2 files changed, 42 insertions(+), 1 deletions(-)[+] [-] Lib/test/test_typing.py 26 Lib/typing.py 17 |
line wrap: on
line diff
--- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1400,6 +1400,10 @@ class G(Generic[T]): class CoolEmployee(NamedTuple): name: str cool: int + +class CoolEmployeeWithDefault(NamedTuple):
""" if PY36: @@ -1960,6 +1964,28 @@ class NamedTupleTests(BaseTestCase): self.assertIs(CoolEmployee._field_types, CoolEmployee.annotations) @skipUnless(PY36, 'Python 3.6 required')
- def test_annotation_usage_with_default(self):
jelle = CoolEmployeeWithDefault('Jelle')[](#l1.19)
self.assertIsInstance(jelle, CoolEmployeeWithDefault)[](#l1.20)
self.assertIsInstance(jelle, tuple)[](#l1.21)
self.assertEqual(jelle.name, 'Jelle')[](#l1.22)
self.assertEqual(jelle.cool, 0)[](#l1.23)
cooler_employee = CoolEmployeeWithDefault('Sjoerd', 1)[](#l1.24)
self.assertEqual(cooler_employee.cool, 1)[](#l1.25)
self.assertEqual(CoolEmployeeWithDefault.__name__, 'CoolEmployeeWithDefault')[](#l1.27)
self.assertEqual(CoolEmployeeWithDefault._fields, ('name', 'cool'))[](#l1.28)
self.assertEqual(CoolEmployeeWithDefault._field_types, dict(name=str, cool=int))[](#l1.29)
self.assertEqual(CoolEmployeeWithDefault._field_defaults, dict(cool=0))[](#l1.30)
with self.assertRaises(TypeError):[](#l1.32)
exec("""[](#l1.33)
+class NonDefaultAfterDefault(NamedTuple):
- @skipUnless(PY36, 'Python 3.6 required') def test_namedtuple_keyword_usage(self): LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int) nick = LocalEmployee('Nick', 25)
--- a/Lib/typing.py +++ b/Lib/typing.py @@ -1959,7 +1959,22 @@ class NamedTupleMeta(type): raise TypeError("Class syntax for NamedTuple is only supported" " in Python 3.6+") types = ns.get('annotations', {})
return _make_nmtuple(typename, types.items())[](#l2.7)
nm_tpl = _make_nmtuple(typename, types.items())[](#l2.8)
defaults = [][](#l2.9)
defaults_dict = {}[](#l2.10)
for field_name in types:[](#l2.11)
if field_name in ns:[](#l2.12)
default_value = ns[field_name][](#l2.13)
defaults.append(default_value)[](#l2.14)
defaults_dict[field_name] = default_value[](#l2.15)
elif defaults:[](#l2.16)
raise TypeError("Non-default namedtuple field {field_name} cannot follow default"[](#l2.17)
" field(s) {default_names}"[](#l2.18)
.format(field_name=field_name,[](#l2.19)
default_names=', '.join(defaults_dict.keys())))[](#l2.20)
nm_tpl.__new__.__defaults__ = tuple(defaults)[](#l2.21)
nm_tpl._field_defaults = defaults_dict[](#l2.22)
return nm_tpl[](#l2.23)
class NamedTuple(metaclass=NamedTupleMeta): """Typed version of namedtuple.