]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-126489: Do not call persistent_id() for a persistent id in Python pickle (GH-126490)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 6 Nov 2024 20:25:14 +0000 (22:25 +0200)
committerGitHub <noreply@github.com>
Wed, 6 Nov 2024 20:25:14 +0000 (22:25 +0200)
Lib/pickle.py
Lib/test/test_pickle.py
Misc/NEWS.d/next/Library/2024-11-06-13-41-38.gh-issue-126489.toaf-0.rst [new file with mode: 0644]

index 965e1952fb8c5ea9b99b704a050c8088a13fd725..25dadb3f75a5731142486dcbbb93a2849f8dba8f 100644 (file)
@@ -548,10 +548,11 @@ class _Pickler:
         self.framer.commit_frame()
 
         # Check for persistent id (defined by a subclass)
-        pid = self.persistent_id(obj)
-        if pid is not None and save_persistent_id:
-            self.save_pers(pid)
-            return
+        if save_persistent_id:
+            pid = self.persistent_id(obj)
+            if pid is not None:
+                self.save_pers(pid)
+                return
 
         # Check the memo
         x = self.memo.get(id(obj))
index c84e507cdf645f5872b347baadd604bc810f8ce1..9ec2eb97147fae79b793b6242e06129496067836 100644 (file)
@@ -224,25 +224,31 @@ class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests,
     def test_pickler_super(self):
         class PersPickler(self.pickler):
             def persistent_id(subself, obj):
+                called.append(obj)
                 self.assertIsNone(super().persistent_id(obj))
                 return obj
 
         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
             f = io.BytesIO()
             pickler = PersPickler(f, proto)
+            called = []
             pickler.dump('abc')
+            self.assertEqual(called, ['abc'])
             self.assertEqual(self.loads(f.getvalue()), 'abc')
 
     def test_unpickler_super(self):
         class PersUnpickler(self.unpickler):
             def persistent_load(subself, pid):
+                called.append(pid)
                 with self.assertRaises(self.persistent_load_error):
                     super().persistent_load(pid)
                 return pid
 
         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
             unpickler = PersUnpickler(io.BytesIO(self.dumps('abc', proto)))
+            called = []
             self.assertEqual(unpickler.load(), 'abc')
+            self.assertEqual(called, ['abc'])
 
 class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase):
 
diff --git a/Misc/NEWS.d/next/Library/2024-11-06-13-41-38.gh-issue-126489.toaf-0.rst b/Misc/NEWS.d/next/Library/2024-11-06-13-41-38.gh-issue-126489.toaf-0.rst
new file mode 100644 (file)
index 0000000..8a6573c
--- /dev/null
@@ -0,0 +1,3 @@
+The Python implementation of :mod:`pickle` no longer calls
+:meth:`pickle.Pickler.persistent_id` for the result of
+:meth:`!persistent_id`.