[3.13] gh-77188: Add pickle tests for objects with slots (GH-144116) (GH-144120)

(cherry picked from commit cf71e34940)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Miss Islington (bot) 2026-01-22 12:26:48 +01:00 committed by GitHub
parent 015b90dc02
commit ac9715bf13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 116 additions and 2 deletions

View file

@ -26,7 +26,7 @@ def __getinitargs__(self):
E.__module__ = "__main__"
# Simple mutable object.
class Object:
class Object(object):
pass
# Hashable immutable key object containing unheshable mutable data.
@ -38,6 +38,43 @@ def __reduce__(self):
# Shouldn't support the recursion itself
return K, (self.value,)
class WithSlots(object):
__slots__ = ('a', 'b')
class WithSlotsSubclass(WithSlots):
__slots__ = ('c',)
class WithSlotsAndDict(object):
__slots__ = ('a', '__dict__')
class WithPrivateAttrs(object):
def __init__(self, a):
self.__private = a
def get(self):
return self.__private
class WithPrivateAttrsSubclass(WithPrivateAttrs):
def __init__(self, a, b):
super().__init__(a)
self.__private = b
def get2(self):
return self.__private
class WithPrivateSlots(object):
__slots__ = ('__private',)
def __init__(self, a):
self.__private = a
def get(self):
return self.__private
class WithPrivateSlotsSubclass(WithPrivateSlots):
__slots__ = ('__private',)
def __init__(self, a, b):
super().__init__(a)
self.__private = b
def get2(self):
return self.__private
# For test_misc
class myint(int):
def __init__(self, x):

View file

@ -33,6 +33,7 @@
from test.support.import_helper import forget
from test.support.os_helper import TESTFN
from test.support import threading_helper
from test.support.testcase import ExtraAssertions
from test.support.warnings_helper import save_restore_warnings_filters
from test import picklecommon
from test.picklecommon import *
@ -2023,7 +2024,7 @@ def check(code, exc):
check(-2**1000, (OverflowError, struct.error))
class AbstractPickleTests:
class AbstractPickleTests(ExtraAssertions):
# Subclass must define self.dumps, self.loads.
py_version = sys.version_info # for test_xpickle
@ -3617,6 +3618,82 @@ def test_c_methods(self):
with self.subTest(proto=proto, descr=descr):
self.assertRaises(TypeError, self.dumps, descr, proto)
def test_object_with_attrs(self):
obj = Object()
obj.a = 1
for proto in protocols:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.a, obj.a)
def test_object_with_slots(self):
obj = WithSlots()
obj.a = 1
self.assertRaises(TypeError, self.dumps, obj, 0)
self.assertRaises(TypeError, self.dumps, obj, 1)
for proto in protocols[2:]:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.a, obj.a)
self.assertNotHasAttr(unpickled, 'b')
obj = WithSlotsSubclass()
obj.a = 1
obj.c = 2
self.assertRaises(TypeError, self.dumps, obj, 0)
self.assertRaises(TypeError, self.dumps, obj, 1)
for proto in protocols[2:]:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.a, obj.a)
self.assertEqual(unpickled.c, obj.c)
self.assertNotHasAttr(unpickled, 'b')
obj = WithSlotsAndDict()
obj.a = 1
obj.c = 2
self.assertRaises(TypeError, self.dumps, obj, 0)
self.assertRaises(TypeError, self.dumps, obj, 1)
for proto in protocols[2:]:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.a, obj.a)
self.assertEqual(unpickled.c, obj.c)
self.assertEqual(unpickled.__dict__, obj.__dict__)
self.assertNotHasAttr(unpickled, 'b')
def test_object_with_private_attrs(self):
obj = WithPrivateAttrs(1)
for proto in protocols:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.get(), obj.get())
obj = WithPrivateAttrsSubclass(1, 2)
for proto in protocols:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.get(), obj.get())
self.assertEqual(unpickled.get2(), obj.get2())
def test_object_with_private_slots(self):
obj = WithPrivateSlots(1)
self.assertRaises(TypeError, self.dumps, obj, 0)
self.assertRaises(TypeError, self.dumps, obj, 1)
for proto in protocols[2:]:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.get(), obj.get())
obj = WithPrivateSlotsSubclass(1, 2)
self.assertRaises(TypeError, self.dumps, obj, 0)
self.assertRaises(TypeError, self.dumps, obj, 1)
for proto in protocols[2:]:
with self.subTest(proto=proto):
unpickled = self.loads(self.dumps(obj, proto))
self.assertEqual(unpickled.get(), obj.get())
self.assertEqual(unpickled.get2(), obj.get2())
def test_compat_pickle(self):
if self.py_version < (3, 4):
self.skipTest("doesn't work in Python < 3.4'")