mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-125631: Enable setting persistent_id and persistent_load of pickler and unpickler (GH-125752)
pickle.Pickler.persistent_id and pickle.Unpickler.persistent_load can again be overridden as instance attributes.
This commit is contained in:
parent
2a6b6b33df
commit
223d3dc554
3 changed files with 146 additions and 2 deletions
|
@ -250,6 +250,84 @@ class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests,
|
|||
self.assertEqual(unpickler.load(), 'abc')
|
||||
self.assertEqual(called, ['abc'])
|
||||
|
||||
def test_pickler_instance_attribute(self):
|
||||
def persistent_id(obj):
|
||||
called.append(obj)
|
||||
return obj
|
||||
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
f = io.BytesIO()
|
||||
pickler = self.pickler(f, proto)
|
||||
called = []
|
||||
old_persistent_id = pickler.persistent_id
|
||||
pickler.persistent_id = persistent_id
|
||||
self.assertEqual(pickler.persistent_id, persistent_id)
|
||||
pickler.dump('abc')
|
||||
self.assertEqual(called, ['abc'])
|
||||
self.assertEqual(self.loads(f.getvalue()), 'abc')
|
||||
del pickler.persistent_id
|
||||
self.assertEqual(pickler.persistent_id, old_persistent_id)
|
||||
|
||||
def test_unpickler_instance_attribute(self):
|
||||
def persistent_load(pid):
|
||||
called.append(pid)
|
||||
return pid
|
||||
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
unpickler = self.unpickler(io.BytesIO(self.dumps('abc', proto)))
|
||||
called = []
|
||||
old_persistent_load = unpickler.persistent_load
|
||||
unpickler.persistent_load = persistent_load
|
||||
self.assertEqual(unpickler.persistent_load, persistent_load)
|
||||
self.assertEqual(unpickler.load(), 'abc')
|
||||
self.assertEqual(called, ['abc'])
|
||||
del unpickler.persistent_load
|
||||
self.assertEqual(unpickler.persistent_load, old_persistent_load)
|
||||
|
||||
def test_pickler_super_instance_attribute(self):
|
||||
class PersPickler(self.pickler):
|
||||
def persistent_id(subself, obj):
|
||||
raise AssertionError('should never be called')
|
||||
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 = []
|
||||
old_persistent_id = pickler.persistent_id
|
||||
pickler.persistent_id = pickler._persistent_id
|
||||
self.assertEqual(pickler.persistent_id, pickler._persistent_id)
|
||||
pickler.dump('abc')
|
||||
self.assertEqual(called, ['abc'])
|
||||
self.assertEqual(self.loads(f.getvalue()), 'abc')
|
||||
del pickler.persistent_id
|
||||
self.assertEqual(pickler.persistent_id, old_persistent_id)
|
||||
|
||||
def test_unpickler_super_instance_attribute(self):
|
||||
class PersUnpickler(self.unpickler):
|
||||
def persistent_load(subself, pid):
|
||||
raise AssertionError('should never be called')
|
||||
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 = []
|
||||
old_persistent_load = unpickler.persistent_load
|
||||
unpickler.persistent_load = unpickler._persistent_load
|
||||
self.assertEqual(unpickler.persistent_load, unpickler._persistent_load)
|
||||
self.assertEqual(unpickler.load(), 'abc')
|
||||
self.assertEqual(called, ['abc'])
|
||||
del unpickler.persistent_load
|
||||
self.assertEqual(unpickler.persistent_load, old_persistent_load)
|
||||
|
||||
|
||||
class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase):
|
||||
|
||||
pickler_class = pickle._Pickler
|
||||
|
@ -373,7 +451,7 @@ if has_c_implementation:
|
|||
check_sizeof = support.check_sizeof
|
||||
|
||||
def test_pickler(self):
|
||||
basesize = support.calcobjsize('6P2n3i2n3i2P')
|
||||
basesize = support.calcobjsize('7P2n3i2n3i2P')
|
||||
p = _pickle.Pickler(io.BytesIO())
|
||||
self.assertEqual(object.__sizeof__(p), basesize)
|
||||
MT_size = struct.calcsize('3nP0n')
|
||||
|
@ -390,7 +468,7 @@ if has_c_implementation:
|
|||
0) # Write buffer is cleared after every dump().
|
||||
|
||||
def test_unpickler(self):
|
||||
basesize = support.calcobjsize('2P2nP 2P2n2i5P 2P3n8P2n2i')
|
||||
basesize = support.calcobjsize('2P2n2P 2P2n2i5P 2P3n8P2n2i')
|
||||
unpickler = _pickle.Unpickler
|
||||
P = struct.calcsize('P') # Size of memo table entry.
|
||||
n = struct.calcsize('n') # Size of mark table entry.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue