https://github.com/python/cpython/commit/ac9715bf1333f91fbea369ea5646e370780eaa08 commit: ac9715bf1333f91fbea369ea5646e370780eaa08 branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-01-22T11:26:48Z summary:
[3.13] gh-77188: Add pickle tests for objects with slots (GH-144116) (GH-144120) (cherry picked from commit cf71e34940e2314ee7ca00961d86a7172286eeea) Co-authored-by: Serhiy Storchaka <[email protected]> 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 99ae5f9ad64b4f..ae1c8c8aa33015 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -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'") _______________________________________________ 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]
