Skip to content

Commit 708e9c9

Browse files
serhiy-storchakamiss-islington
authored andcommitted
gh-77188: Add pickle tests for objects with slots (GH-144116)
(cherry picked from commit cf71e34) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 740db90 commit 708e9c9

2 files changed

Lines changed: 114 additions & 1 deletion

File tree

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
@@ -3617,6 +3617,82 @@ def test_c_methods(self):
36173617
with self.subTest(proto=proto, descr=descr):
36183618
self.assertRaises(TypeError, self.dumps, descr, proto)
36193619

3620+
def test_object_with_attrs(self):
3621+
obj = Object()
3622+
obj.a = 1
3623+
for proto in protocols:
3624+
with self.subTest(proto=proto):
3625+
unpickled = self.loads(self.dumps(obj, proto))
3626+
self.assertEqual(unpickled.a, obj.a)
3627+
3628+
def test_object_with_slots(self):
3629+
obj = WithSlots()
3630+
obj.a = 1
3631+
self.assertRaises(TypeError, self.dumps, obj, 0)
3632+
self.assertRaises(TypeError, self.dumps, obj, 1)
3633+
for proto in protocols[2:]:
3634+
with self.subTest(proto=proto):
3635+
unpickled = self.loads(self.dumps(obj, proto))
3636+
self.assertEqual(unpickled.a, obj.a)
3637+
self.assertNotHasAttr(unpickled, 'b')
3638+
3639+
obj = WithSlotsSubclass()
3640+
obj.a = 1
3641+
obj.c = 2
3642+
self.assertRaises(TypeError, self.dumps, obj, 0)
3643+
self.assertRaises(TypeError, self.dumps, obj, 1)
3644+
for proto in protocols[2:]:
3645+
with self.subTest(proto=proto):
3646+
unpickled = self.loads(self.dumps(obj, proto))
3647+
self.assertEqual(unpickled.a, obj.a)
3648+
self.assertEqual(unpickled.c, obj.c)
3649+
self.assertNotHasAttr(unpickled, 'b')
3650+
3651+
obj = WithSlotsAndDict()
3652+
obj.a = 1
3653+
obj.c = 2
3654+
self.assertRaises(TypeError, self.dumps, obj, 0)
3655+
self.assertRaises(TypeError, self.dumps, obj, 1)
3656+
for proto in protocols[2:]:
3657+
with self.subTest(proto=proto):
3658+
unpickled = self.loads(self.dumps(obj, proto))
3659+
self.assertEqual(unpickled.a, obj.a)
3660+
self.assertEqual(unpickled.c, obj.c)
3661+
self.assertEqual(unpickled.__dict__, obj.__dict__)
3662+
self.assertNotHasAttr(unpickled, 'b')
3663+
3664+
def test_object_with_private_attrs(self):
3665+
obj = WithPrivateAttrs(1)
3666+
for proto in protocols:
3667+
with self.subTest(proto=proto):
3668+
unpickled = self.loads(self.dumps(obj, proto))
3669+
self.assertEqual(unpickled.get(), obj.get())
3670+
3671+
obj = WithPrivateAttrsSubclass(1, 2)
3672+
for proto in protocols:
3673+
with self.subTest(proto=proto):
3674+
unpickled = self.loads(self.dumps(obj, proto))
3675+
self.assertEqual(unpickled.get(), obj.get())
3676+
self.assertEqual(unpickled.get2(), obj.get2())
3677+
3678+
def test_object_with_private_slots(self):
3679+
obj = WithPrivateSlots(1)
3680+
self.assertRaises(TypeError, self.dumps, obj, 0)
3681+
self.assertRaises(TypeError, self.dumps, obj, 1)
3682+
for proto in protocols[2:]:
3683+
with self.subTest(proto=proto):
3684+
unpickled = self.loads(self.dumps(obj, proto))
3685+
self.assertEqual(unpickled.get(), obj.get())
3686+
3687+
obj = WithPrivateSlotsSubclass(1, 2)
3688+
self.assertRaises(TypeError, self.dumps, obj, 0)
3689+
self.assertRaises(TypeError, self.dumps, obj, 1)
3690+
for proto in protocols[2:]:
3691+
with self.subTest(proto=proto):
3692+
unpickled = self.loads(self.dumps(obj, proto))
3693+
self.assertEqual(unpickled.get(), obj.get())
3694+
self.assertEqual(unpickled.get2(), obj.get2())
3695+
36203696
def test_compat_pickle(self):
36213697
if self.py_version < (3, 4):
36223698
self.skipTest("doesn't work in Python < 3.4'")

0 commit comments

Comments
 (0)