Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 74daa1b

Browse files
committed
Update a copyreg.py to 3.12; Add a test_copyreg.py from 3.12
1 parent 855fa14 commit 74daa1b

File tree

2 files changed

+144
-8
lines changed

2 files changed

+144
-8
lines changed

Lib/copyreg.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ def constructor(object):
2525

2626
# Example: provide pickling support for complex numbers.
2727

28-
try:
29-
complex
30-
except NameError:
31-
pass
32-
else:
28+
def pickle_complex(c):
29+
return complex, (c.real, c.imag)
3330

34-
def pickle_complex(c):
35-
return complex, (c.real, c.imag)
31+
pickle(complex, pickle_complex, complex)
3632

37-
pickle(complex, pickle_complex, complex)
33+
def pickle_union(obj):
34+
import functools, operator
35+
return functools.reduce, (operator.or_, obj.__args__)
36+
37+
pickle(type(int | str), pickle_union)
3838

3939
# Support for pickling new-style objects
4040

@@ -48,6 +48,7 @@ def _reconstructor(cls, base, state):
4848
return obj
4949

5050
_HEAPTYPE = 1<<9
51+
_new_type = type(int.__new__)
5152

5253
# Python code for object.__reduce_ex__ for protocols 0 and 1
5354

@@ -57,6 +58,9 @@ def _reduce_ex(self, proto):
5758
for base in cls.__mro__:
5859
if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
5960
break
61+
new = base.__new__
62+
if isinstance(new, _new_type) and new.__self__ is base:
63+
break
6064
else:
6165
base = object # not really reachable
6266
if base is object:
@@ -79,6 +83,10 @@ def _reduce_ex(self, proto):
7983
except AttributeError:
8084
dict = None
8185
else:
86+
if (type(self).__getstate__ is object.__getstate__ and
87+
getattr(self, "__slots__", None)):
88+
raise TypeError("a class that defines __slots__ without "
89+
"defining __getstate__ cannot be pickled")
8290
dict = getstate()
8391
if dict:
8492
return _reconstructor, args, dict

Lib/test/test_copyreg.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import copyreg
2+
import unittest
3+
4+
from test.pickletester import ExtensionSaver
5+
6+
class C:
7+
pass
8+
9+
def pickle_C(c):
10+
return C, ()
11+
12+
13+
class WithoutSlots(object):
14+
pass
15+
16+
class WithWeakref(object):
17+
__slots__ = ('__weakref__',)
18+
19+
class WithPrivate(object):
20+
__slots__ = ('__spam',)
21+
22+
class _WithLeadingUnderscoreAndPrivate(object):
23+
__slots__ = ('__spam',)
24+
25+
class ___(object):
26+
__slots__ = ('__spam',)
27+
28+
class WithSingleString(object):
29+
__slots__ = 'spam'
30+
31+
class WithInherited(WithSingleString):
32+
__slots__ = ('eggs',)
33+
34+
35+
class CopyRegTestCase(unittest.TestCase):
36+
37+
def test_class(self):
38+
copyreg.pickle(C, pickle_C)
39+
40+
def test_noncallable_reduce(self):
41+
self.assertRaises(TypeError, copyreg.pickle,
42+
C, "not a callable")
43+
44+
def test_noncallable_constructor(self):
45+
self.assertRaises(TypeError, copyreg.pickle,
46+
C, pickle_C, "not a callable")
47+
48+
def test_bool(self):
49+
import copy
50+
self.assertEqual(True, copy.copy(True))
51+
52+
def test_extension_registry(self):
53+
mod, func, code = 'junk1 ', ' junk2', 0xabcd
54+
e = ExtensionSaver(code)
55+
try:
56+
# Shouldn't be in registry now.
57+
self.assertRaises(ValueError, copyreg.remove_extension,
58+
mod, func, code)
59+
copyreg.add_extension(mod, func, code)
60+
# Should be in the registry.
61+
self.assertTrue(copyreg._extension_registry[mod, func] == code)
62+
self.assertTrue(copyreg._inverted_registry[code] == (mod, func))
63+
# Shouldn't be in the cache.
64+
self.assertNotIn(code, copyreg._extension_cache)
65+
# Redundant registration should be OK.
66+
copyreg.add_extension(mod, func, code) # shouldn't blow up
67+
# Conflicting code.
68+
self.assertRaises(ValueError, copyreg.add_extension,
69+
mod, func, code + 1)
70+
self.assertRaises(ValueError, copyreg.remove_extension,
71+
mod, func, code + 1)
72+
# Conflicting module name.
73+
self.assertRaises(ValueError, copyreg.add_extension,
74+
mod[1:], func, code )
75+
self.assertRaises(ValueError, copyreg.remove_extension,
76+
mod[1:], func, code )
77+
# Conflicting function name.
78+
self.assertRaises(ValueError, copyreg.add_extension,
79+
mod, func[1:], code)
80+
self.assertRaises(ValueError, copyreg.remove_extension,
81+
mod, func[1:], code)
82+
# Can't remove one that isn't registered at all.
83+
if code + 1 not in copyreg._inverted_registry:
84+
self.assertRaises(ValueError, copyreg.remove_extension,
85+
mod[1:], func[1:], code + 1)
86+
87+
finally:
88+
e.restore()
89+
90+
# Shouldn't be there anymore.
91+
self.assertNotIn((mod, func), copyreg._extension_registry)
92+
# The code *may* be in copyreg._extension_registry, though, if
93+
# we happened to pick on a registered code. So don't check for
94+
# that.
95+
96+
# Check valid codes at the limits.
97+
for code in 1, 0x7fffffff:
98+
e = ExtensionSaver(code)
99+
try:
100+
copyreg.add_extension(mod, func, code)
101+
copyreg.remove_extension(mod, func, code)
102+
finally:
103+
e.restore()
104+
105+
# Ensure invalid codes blow up.
106+
for code in -1, 0, 0x80000000:
107+
self.assertRaises(ValueError, copyreg.add_extension,
108+
mod, func, code)
109+
110+
def test_slotnames(self):
111+
self.assertEqual(copyreg._slotnames(WithoutSlots), [])
112+
self.assertEqual(copyreg._slotnames(WithWeakref), [])
113+
expected = ['_WithPrivate__spam']
114+
self.assertEqual(copyreg._slotnames(WithPrivate), expected)
115+
expected = ['_WithLeadingUnderscoreAndPrivate__spam']
116+
self.assertEqual(copyreg._slotnames(_WithLeadingUnderscoreAndPrivate),
117+
expected)
118+
self.assertEqual(copyreg._slotnames(___), ['__spam'])
119+
self.assertEqual(copyreg._slotnames(WithSingleString), ['spam'])
120+
expected = ['eggs', 'spam']
121+
expected.sort()
122+
result = copyreg._slotnames(WithInherited)
123+
result.sort()
124+
self.assertEqual(result, expected)
125+
126+
127+
if __name__ == "__main__":
128+
unittest.main()

0 commit comments

Comments
 (0)