https://github.com/python/cpython/commit/cf71e34940e2314ee7ca00961d86a7172286eeea
commit: cf71e34940e2314ee7ca00961d86a7172286eeea
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-21T19:21:02+02:00
summary:
gh-77188: Add pickle tests for objects with slots (GH-144116)
files:
M Lib/test/picklecommon.py
M Lib/test/pickletester.py
diff --git a/Lib/test/picklecommon.py b/Lib/test/picklecommon.py
index fece50f17fecca..4c19b6c421fc61 100644
--- a/Lib/test/picklecommon.py
+++ b/Lib/test/picklecommon.py
@@ -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):
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 2e362ac1b02ac9..d2b8d036bfd9e7 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -4118,6 +4118,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'")
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]