with self.assertRaises(TypeError):
NamedTuple('Name', x=1, y='a')
+ def test_namedtuple_special_keyword_names(self):
+ NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list)
+ self.assertEqual(NT.__name__, 'NT')
+ self.assertEqual(NT._fields, ('cls', 'self', 'typename', 'fields'))
+ a = NT(cls=str, self=42, typename='foo', fields=[('bar', tuple)])
+ self.assertEqual(a.cls, str)
+ self.assertEqual(a.self, 42)
+ self.assertEqual(a.typename, 'foo')
+ self.assertEqual(a.fields, [('bar', tuple)])
+
+ def test_namedtuple_errors(self):
+ with self.assertRaises(TypeError):
+ NamedTuple.__new__()
+ with self.assertRaises(TypeError):
+ NamedTuple()
+ with self.assertRaises(TypeError):
+ NamedTuple('Emp', [('name', str)], None)
+ with self.assertRaises(ValueError):
+ NamedTuple('Emp', [('_name', str)])
+
+ Emp = NamedTuple(typename='Emp', name=str, id=int)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+
+ Emp = NamedTuple('Emp', fields=[('name', str), ('id', int)])
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+
def test_pickle(self):
global Emp # pickle wants to reference the class by name
Emp = NamedTuple('Emp', [('name', str), ('id', int)])
"""
_root = True
- def __new__(self, typename, fields=None, **kwargs):
+ def __new__(*args, **kwargs):
+ if not args:
+ raise TypeError('NamedTuple.__new__(): not enough arguments')
+ cls, *args = args # allow the "cls" keyword be passed
+ if args:
+ typename, *args = args # allow the "typename" keyword be passed
+ elif 'typename' in kwargs:
+ typename = kwargs.pop('typename')
+ else:
+ raise TypeError("NamedTuple.__new__() missing 1 required positional "
+ "argument: 'typename'")
+ if args:
+ try:
+ fields, = args # allow the "fields" keyword be passed
+ except ValueError:
+ raise TypeError(f'NamedTuple.__new__() takes from 2 to 3 '
+ f'positional arguments but {len(args) + 2} '
+ f'were given') from None
+ elif 'fields' in kwargs and len(kwargs) == 1:
+ fields = kwargs.pop('fields')
+ else:
+ fields = None
+
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)
+ __new__.__text_signature__ = '($cls, typename, fields=None, /, **kwargs)'
def NewType(name, tp):