]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.7] bpo-38405: Make nested subclasses of typing.NamedTuple pickleable. (GH-16641...
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 9 Oct 2019 09:56:32 +0000 (12:56 +0300)
committerGitHub <noreply@github.com>
Wed, 9 Oct 2019 09:56:32 +0000 (12:56 +0300)
(cherry picked from commit 13abda41003daf599587991d8291f0dacf6e9519)

Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2019-10-08-11-18-40.bpo-38405.0-7e7s.rst [new file with mode: 0644]

index 4871fb7c4ddc3f3db6f6a13353299ee6ac94391a..d8abc0ac96a108f4ad072f32e947bbc29937dd8b 100644 (file)
@@ -2441,6 +2441,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)])
@@ -2564,14 +2567,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 IOTests(BaseTestCase):
index 021ef9552e6529bbd0082611b4b3d3f5dcb3fd44..dea7babaf792f656c9f2a5b803bde6805d76bbfd 100644 (file)
@@ -1343,7 +1343,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 (file)
index 0000000..ee346a3
--- /dev/null
@@ -0,0 +1 @@
+Nested subclasses of :class:`typing.NamedTuple` are now pickleable.