diff options
author | Guido van Rossum <guido@python.org> | 2016-11-15 17:48:06 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2016-11-15 17:48:06 (GMT) |
commit | 2f841442354f41f2490cef76e9ba24bfef9dfbea (patch) | |
tree | 9b1aeee58baadad475ce4f69cc782e3a237224f5 /Lib/typing.py | |
parent | 49e8f2d2040d3c15d61a713dcbe14caae41c4f0d (diff) | |
download | cpython-2f841442354f41f2490cef76e9ba24bfef9dfbea.zip cpython-2f841442354f41f2490cef76e9ba24bfef9dfbea.tar.gz cpython-2f841442354f41f2490cef76e9ba24bfef9dfbea.tar.bz2 |
Issue #28556: Allow keyword syntax for NamedTuple (Ivan Levkivskyi) (upstream #321)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 76 |
1 files changed, 39 insertions, 37 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 7a64e07..fe22b2b 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1875,6 +1875,8 @@ class Type(Generic[CT_co], extra=type): def _make_nmtuple(name, types): + msg = "NamedTuple('Name', [(f0, t0), (f1, t1), ...]); each t must be a type" + types = [(n, _type_check(t, msg)) for n, t in types] nm_tpl = collections.namedtuple(name, [n for n, t in types]) nm_tpl._field_types = dict(types) try: @@ -1884,55 +1886,55 @@ def _make_nmtuple(name, types): return nm_tpl -if sys.version_info[:2] >= (3, 6): - class NamedTupleMeta(type): +_PY36 = sys.version_info[:2] >= (3, 6) - def __new__(cls, typename, bases, ns, *, _root=False): - if _root: - return super().__new__(cls, typename, bases, ns) - types = ns.get('__annotations__', {}) - return _make_nmtuple(typename, types.items()) - class NamedTuple(metaclass=NamedTupleMeta, _root=True): - """Typed version of namedtuple. +class NamedTupleMeta(type): - Usage:: + def __new__(cls, typename, bases, ns): + if ns.get('_root', False): + return super().__new__(cls, typename, bases, ns) + if not _PY36: + raise TypeError("Class syntax for NamedTuple is only supported" + " in Python 3.6+") + types = ns.get('__annotations__', {}) + return _make_nmtuple(typename, types.items()) - class Employee(NamedTuple): - name: str - id: int +class NamedTuple(metaclass=NamedTupleMeta): + """Typed version of namedtuple. - This is equivalent to:: + Usage in Python versions >= 3.6:: - Employee = collections.namedtuple('Employee', ['name', 'id']) + class Employee(NamedTuple): + name: str + id: int - The resulting class has one extra attribute: _field_types, - giving a dict mapping field names to types. (The field names - are in the _fields attribute, which is part of the namedtuple - API.) Backward-compatible usage:: + This is equivalent to:: - Employee = NamedTuple('Employee', [('name', str), ('id', int)]) - """ - - def __new__(self, typename, fields): - return _make_nmtuple(typename, fields) -else: - def NamedTuple(typename, fields): - """Typed version of namedtuple. + Employee = collections.namedtuple('Employee', ['name', 'id']) - Usage:: + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) Alternative equivalent keyword syntax is also accepted:: - Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + Employee = NamedTuple('Employee', name=str, id=int) - This is equivalent to:: + In Python versions <= 3.5 use:: - Employee = collections.namedtuple('Employee', ['name', 'id']) - - The resulting class has one extra attribute: _field_types, - giving a dict mapping field names to types. (The field names - are in the _fields attribute, which is part of the namedtuple - API.) - """ + Employee = NamedTuple('Employee', [('name', str), ('id', int)]) + """ + _root = True + + def __new__(self, typename, fields=None, **kwargs): + if kwargs and not _PY36: + raise TypeError("Keyword syntax for NamedTuple is only supported" + " in Python 3.6+") + if fields is None: + fields = kwargs.items() + elif kwargs: + raise TypeError("Either list of fields or keywords" + " can be provided to NamedTuple, not both") return _make_nmtuple(typename, fields) |