@@ -1875,6 +1875,8 @@ def new_user(user_class: Type[U]) -> U:
1875
1875
1876
1876
1877
1877
def _make_nmtuple (name , types ):
1878
+ msg = "NamedTuple('Name', [(f0, t0), (f1, t1), ...]); each t must be a type"
1879
+ types = [(n , _type_check (t , msg )) for n , t in types ]
1878
1880
nm_tpl = collections .namedtuple (name , [n for n , t in types ])
1879
1881
nm_tpl ._field_types = dict (types )
1880
1882
try :
@@ -1884,55 +1886,55 @@ def _make_nmtuple(name, types):
1884
1886
return nm_tpl
1885
1887
1886
1888
1887
- if sys .version_info [:2 ] >= (3 , 6 ):
1888
- class NamedTupleMeta (type ):
1889
+ _PY36 = sys .version_info [:2 ] >= (3 , 6 )
1889
1890
1890
- def __new__ (cls , typename , bases , ns , * , _root = False ):
1891
- if _root :
1892
- return super ().__new__ (cls , typename , bases , ns )
1893
- types = ns .get ('__annotations__' , {})
1894
- return _make_nmtuple (typename , types .items ())
1895
1891
1896
- class NamedTuple (metaclass = NamedTupleMeta , _root = True ):
1897
- """Typed version of namedtuple.
1892
+ class NamedTupleMeta (type ):
1898
1893
1899
- Usage::
1894
+ def __new__ (cls , typename , bases , ns ):
1895
+ if ns .get ('_root' , False ):
1896
+ return super ().__new__ (cls , typename , bases , ns )
1897
+ if not _PY36 :
1898
+ raise TypeError ("Class syntax for NamedTuple is only supported"
1899
+ " in Python 3.6+" )
1900
+ types = ns .get ('__annotations__' , {})
1901
+ return _make_nmtuple (typename , types .items ())
1900
1902
1901
- class Employee(NamedTuple):
1902
- name: str
1903
- id: int
1903
+ class NamedTuple (metaclass = NamedTupleMeta ):
1904
+ """Typed version of namedtuple.
1904
1905
1905
- This is equivalent to ::
1906
+ Usage in Python versions >= 3.6 ::
1906
1907
1907
- Employee = collections.namedtuple('Employee', ['name', 'id'])
1908
+ class Employee(NamedTuple):
1909
+ name: str
1910
+ id: int
1908
1911
1909
- The resulting class has one extra attribute: _field_types,
1910
- giving a dict mapping field names to types. (The field names
1911
- are in the _fields attribute, which is part of the namedtuple
1912
- API.) Backward-compatible usage::
1912
+ This is equivalent to::
1913
1913
1914
- Employee = NamedTuple('Employee', [('name', str), ('id', int)])
1915
- """
1916
-
1917
- def __new__ (self , typename , fields ):
1918
- return _make_nmtuple (typename , fields )
1919
- else :
1920
- def NamedTuple (typename , fields ):
1921
- """Typed version of namedtuple.
1914
+ Employee = collections.namedtuple('Employee', ['name', 'id'])
1922
1915
1923
- Usage::
1916
+ The resulting class has one extra attribute: _field_types,
1917
+ giving a dict mapping field names to types. (The field names
1918
+ are in the _fields attribute, which is part of the namedtuple
1919
+ API.) Alternative equivalent keyword syntax is also accepted::
1924
1920
1925
- Employee = typing. NamedTuple('Employee', [(' name', str), 'id', int)] )
1921
+ Employee = NamedTuple('Employee', name= str, id= int)
1926
1922
1927
- This is equivalent to ::
1923
+ In Python versions <= 3.5 use ::
1928
1924
1929
- Employee = collections.namedtuple('Employee', ['name', 'id'])
1930
-
1931
- The resulting class has one extra attribute: _field_types,
1932
- giving a dict mapping field names to types. (The field names
1933
- are in the _fields attribute, which is part of the namedtuple
1934
- API.)
1935
- """
1925
+ Employee = NamedTuple('Employee', [('name', str), ('id', int)])
1926
+ """
1927
+ _root = True
1928
+
1929
+ def __new__ (self , typename , fields = None , ** kwargs ):
1930
+ if kwargs and not _PY36 :
1931
+ raise TypeError ("Keyword syntax for NamedTuple is only supported"
1932
+ " in Python 3.6+" )
1933
+ if fields is None :
1934
+ fields = kwargs .items ()
1935
+ elif kwargs :
1936
+ raise TypeError ("Either list of fields or keywords"
1937
+ " can be provided to NamedTuple, not both" )
1936
1938
return _make_nmtuple (typename , fields )
1937
1939
1938
1940
0 commit comments