Skip to content

Commit a74709d

Browse files
[3.14] gh-77188: Add pickle tests for objects with slots (GH-144116) (GH-144119)
(cherry picked from commit cf71e34) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 9f1ad56 commit a74709d

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

Lib/test/picklecommon.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __getinitargs__(self):
2626
E.__module__ = "__main__"
2727

2828
# Simple mutable object.
29-
class Object:
29+
class Object(object):
3030
pass
3131

3232
# Hashable immutable key object containing unheshable mutable data.
@@ -38,6 +38,43 @@ def __reduce__(self):
3838
# Shouldn't support the recursion itself
3939
return K, (self.value,)
4040

41+
class WithSlots(object):
42+
__slots__ = ('a', 'b')
43+
44+
class WithSlotsSubclass(WithSlots):
45+
__slots__ = ('c',)
46+
47+
class WithSlotsAndDict(object):
48+
__slots__ = ('a', '__dict__')
49+
50+
class WithPrivateAttrs(object):
51+
def __init__(self, a):
52+
self.__private = a
53+
def get(self):
54+
return self.__private
55+
56+
class WithPrivateAttrsSubclass(WithPrivateAttrs):
57+
def __init__(self, a, b):
58+
super().__init__(a)
59+
self.__private = b
60+
def get2(self):
61+
return self.__private
62+
63+
class WithPrivateSlots(object):
64+
__slots__ = ('__private',)
65+
def __init__(self, a):
66+
self.__private = a
67+
def get(self):
68+
return self.__private
69+
70+
class WithPrivateSlotsSubclass(WithPrivateSlots):
71+
__slots__ = ('__private',)
72+
def __init__(self, a, b):
73+
super().__init__(a)
74+
self.__private = b
75+
def get2(self):
76+
return self.__private
77+
4178
# For test_misc
4279
class myint(int):
4380
def __init__(self, x):

Lib/test/pickletester.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,82 @@ def test_c_methods(self):
39473947
with self.subTest(proto=proto, descr=descr):
39483948
self.assertRaises(TypeError, self.dumps, descr, proto)
39493949

3950+
def test_object_with_attrs(self):
3951+
obj = Object()
3952+
obj.a = 1
3953+
for proto in protocols:
3954+
with self.subTest(proto=proto):
3955+
unpickled = self.loads(self.dumps(obj, proto))
3956+
self.assertEqual(unpickled.a, obj.a)
3957+
3958+
def test_object_with_slots(self):
3959+
obj = WithSlots()
3960+
obj.a = 1
3961+
self.assertRaises(TypeError, self.dumps, obj, 0)
3962+
self.assertRaises(TypeError, self.dumps, obj, 1)
3963+
for proto in protocols[2:]:
3964+
with self.subTest(proto=proto):
3965+
unpickled = self.loads(self.dumps(obj, proto))
3966+
self.assertEqual(unpickled.a, obj.a)
3967+
self.assertNotHasAttr(unpickled, 'b')
3968+
3969+
obj = WithSlotsSubclass()
3970+
obj.a = 1
3971+
obj.c = 2
3972+
self.assertRaises(TypeError, self.dumps, obj, 0)
3973+
self.assertRaises(TypeError, self.dumps, obj, 1)
3974+
for proto in protocols[2:]:
3975+
with self.subTest(proto=proto):
3976+
unpickled = self.loads(self.dumps(obj, proto))
3977+
self.assertEqual(unpickled.a, obj.a)
3978+
self.assertEqual(unpickled.c, obj.c)
3979+
self.assertNotHasAttr(unpickled, 'b')
3980+
3981+
obj = WithSlotsAndDict()
3982+
obj.a = 1
3983+
obj.c = 2
3984+
self.assertRaises(TypeError, self.dumps, obj, 0)
3985+
self.assertRaises(TypeError, self.dumps, obj, 1)
3986+
for proto in protocols[2:]:
3987+
with self.subTest(proto=proto):
3988+
unpickled = self.loads(self.dumps(obj, proto))
3989+
self.assertEqual(unpickled.a, obj.a)
3990+
self.assertEqual(unpickled.c, obj.c)
3991+
self.assertEqual(unpickled.__dict__, obj.__dict__)
3992+
self.assertNotHasAttr(unpickled, 'b')
3993+
3994+
def test_object_with_private_attrs(self):
3995+
obj = WithPrivateAttrs(1)
3996+
for proto in protocols:
3997+
with self.subTest(proto=proto):
3998+
unpickled = self.loads(self.dumps(obj, proto))
3999+
self.assertEqual(unpickled.get(), obj.get())
4000+
4001+
obj = WithPrivateAttrsSubclass(1, 2)
4002+
for proto in protocols:
4003+
with self.subTest(proto=proto):
4004+
unpickled = self.loads(self.dumps(obj, proto))
4005+
self.assertEqual(unpickled.get(), obj.get())
4006+
self.assertEqual(unpickled.get2(), obj.get2())
4007+
4008+
def test_object_with_private_slots(self):
4009+
obj = WithPrivateSlots(1)
4010+
self.assertRaises(TypeError, self.dumps, obj, 0)
4011+
self.assertRaises(TypeError, self.dumps, obj, 1)
4012+
for proto in protocols[2:]:
4013+
with self.subTest(proto=proto):
4014+
unpickled = self.loads(self.dumps(obj, proto))
4015+
self.assertEqual(unpickled.get(), obj.get())
4016+
4017+
obj = WithPrivateSlotsSubclass(1, 2)
4018+
self.assertRaises(TypeError, self.dumps, obj, 0)
4019+
self.assertRaises(TypeError, self.dumps, obj, 1)
4020+
for proto in protocols[2:]:
4021+
with self.subTest(proto=proto):
4022+
unpickled = self.loads(self.dumps(obj, proto))
4023+
self.assertEqual(unpickled.get(), obj.get())
4024+
self.assertEqual(unpickled.get2(), obj.get2())
4025+
39504026
def test_compat_pickle(self):
39514027
if self.py_version < (3, 4):
39524028
self.skipTest("doesn't work in Python < 3.4'")

0 commit comments

Comments
 (0)