aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-10-08 07:12:38 -0700
committerGitHub <noreply@github.com>2019-10-08 07:12:38 -0700
commit10b475a151dc35c8ca4047331d591130973e914d (patch)
tree8861f8da3840798184882208a0bfc80ee31559b1
parent364532fb4962991d278da6470c3aec4e443e533d (diff)
downloadcpython3-10b475a151dc35c8ca4047331d591130973e914d.tar.gz
bpo-38405: Make nested subclasses of typing.NamedTuple pickleable. (GH-16641)
(cherry picked from commit 13abda41003daf599587991d8291f0dacf6e9519) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Lib/test/test_typing.py28
-rw-r--r--Lib/typing.py2
-rw-r--r--Misc/NEWS.d/next/Library/2019-10-08-11-18-40.bpo-38405.0-7e7s.rst1
3 files changed, 23 insertions, 8 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 3013f8ec41..104b7c035c 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -3468,6 +3468,9 @@ class NewTypeTests(BaseTestCase):
class NamedTupleTests(BaseTestCase):
+ class NestedEmployee(NamedTuple):
+ name: str
+ cool: int
def test_basics(self):
Emp = NamedTuple('Emp', [('name', str), ('id', int)])
@@ -3593,14 +3596,25 @@ class XMethBad2(NamedTuple):
self.assertEqual(Emp.__name__, 'Emp')
self.assertEqual(Emp._fields, ('name', 'id'))
- def test_pickle(self):
+ def test_copy_and_pickle(self):
global Emp # pickle wants to reference the class by name
- Emp = NamedTuple('Emp', [('name', str), ('id', int)])
- jane = Emp('jane', 37)
- for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- z = pickle.dumps(jane, proto)
- jane2 = pickle.loads(z)
- self.assertEqual(jane2, jane)
+ Emp = NamedTuple('Emp', [('name', str), ('cool', int)])
+ for cls in Emp, CoolEmployee, self.NestedEmployee:
+ with self.subTest(cls=cls):
+ jane = cls('jane', 37)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(jane, proto)
+ jane2 = pickle.loads(z)
+ self.assertEqual(jane2, jane)
+ self.assertIsInstance(jane2, cls)
+
+ jane2 = copy(jane)
+ self.assertEqual(jane2, jane)
+ self.assertIsInstance(jane2, cls)
+
+ jane2 = deepcopy(jane)
+ self.assertEqual(jane2, jane)
+ self.assertIsInstance(jane2, cls)
class TypedDictTests(BaseTestCase):
diff --git a/Lib/typing.py b/Lib/typing.py
index 825be10812..eeebd85772 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1593,7 +1593,7 @@ _prohibited = ('__new__', '__init__', '__slots__', '__getnewargs__',
'_fields', '_field_defaults', '_field_types',
'_make', '_replace', '_asdict', '_source')
-_special = ('__module__', '__name__', '__qualname__', '__annotations__')
+_special = ('__module__', '__name__', '__annotations__')
class NamedTupleMeta(type):
diff --git a/Misc/NEWS.d/next/Library/2019-10-08-11-18-40.bpo-38405.0-7e7s.rst b/Misc/NEWS.d/next/Library/2019-10-08-11-18-40.bpo-38405.0-7e7s.rst
new file mode 100644
index 0000000000..ee346a30ec
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-10-08-11-18-40.bpo-38405.0-7e7s.rst
@@ -0,0 +1 @@
+Nested subclasses of :class:`typing.NamedTuple` are now pickleable.