Skip to content

Commit

Permalink
pythongh-126489: Do not call persistent_id() for a persistent id in P…
Browse files Browse the repository at this point in the history
…ython pickle
  • Loading branch information
serhiy-storchaka committed Nov 6, 2024
1 parent b1c4ffc commit e138301
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 4 deletions.
9 changes: 5 additions & 4 deletions Lib/pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,11 @@ def save(self, obj, save_persistent_id=True):
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))
Expand Down
6 changes: 6 additions & 0 deletions Lib/test/test_pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,25 +224,31 @@ def persistent_load(pid):
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):

Expand Down
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit e138301

Please sign in to comment.