diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-09-17 18:22:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-17 18:22:00 (GMT) |
commit | 2bf31ccab3d17f3f35b42dca97f99576dfe2fc7d (patch) | |
tree | f92bdc27f3280f735b5d986bc30ef1e97e65430e /Lib/test/test_typing.py | |
parent | b57481318e3e3cbacd398b898f9849ec8f2d7eec (diff) | |
download | cpython-2bf31ccab3d17f3f35b42dca97f99576dfe2fc7d.zip cpython-2bf31ccab3d17f3f35b42dca97f99576dfe2fc7d.tar.gz cpython-2bf31ccab3d17f3f35b42dca97f99576dfe2fc7d.tar.bz2 |
bpo-38191: Accept arbitrary keyword names in NamedTuple() and TypedDict(). (GH-16222)
This includes such names as "cls", "self", "typename", "_typename",
"fields" and "_fields".
Passing positional arguments by keyword is deprecated.
Diffstat (limited to 'Lib/test/test_typing.py')
-rw-r--r-- | Lib/test/test_typing.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 59b1b4e..5914f31 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -3563,6 +3563,36 @@ class XMethBad2(NamedTuple): 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)]) + + with self.assertWarns(DeprecationWarning): + Emp = NamedTuple(typename='Emp', name=str, id=int) + self.assertEqual(Emp.__name__, 'Emp') + self.assertEqual(Emp._fields, ('name', 'id')) + + with self.assertWarns(DeprecationWarning): + 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)]) @@ -3604,6 +3634,36 @@ class TypedDictTests(BaseTestCase): self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) self.assertEqual(Emp.__total__, True) + def test_typeddict_special_keyword_names(self): + TD = TypedDict("TD", cls=type, self=object, typename=str, _typename=int, fields=list, _fields=dict) + self.assertEqual(TD.__name__, 'TD') + self.assertEqual(TD.__annotations__, {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) + a = TD(cls=str, self=42, typename='foo', _typename=53, fields=[('bar', tuple)], _fields={'baz', set}) + self.assertEqual(a['cls'], str) + self.assertEqual(a['self'], 42) + self.assertEqual(a['typename'], 'foo') + self.assertEqual(a['_typename'], 53) + self.assertEqual(a['fields'], [('bar', tuple)]) + self.assertEqual(a['_fields'], {'baz', set}) + + def test_typeddict_create_errors(self): + with self.assertRaises(TypeError): + TypedDict.__new__() + with self.assertRaises(TypeError): + TypedDict() + with self.assertRaises(TypeError): + TypedDict('Emp', [('name', str)], None) + + with self.assertWarns(DeprecationWarning): + Emp = TypedDict(_typename='Emp', name=str, id=int) + self.assertEqual(Emp.__name__, 'Emp') + self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) + + with self.assertWarns(DeprecationWarning): + Emp = TypedDict('Emp', _fields={'name': str, 'id': int}) + self.assertEqual(Emp.__name__, 'Emp') + self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) + def test_typeddict_errors(self): Emp = TypedDict('Emp', {'name': str, 'id': int}) self.assertEqual(TypedDict.__module__, 'typing') |