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

Skip to content

Commit 32af754

Browse files
Issue #20289: The copy module now uses pickle protocol 4 (PEP 3154) and
supports copying of instances of classes whose __new__ method takes keyword-only arguments.
1 parent 944fbcc commit 32af754

3 files changed

Lines changed: 76 additions & 2 deletions

File tree

Lib/copy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def copy(x):
9494
else:
9595
reductor = getattr(x, "__reduce_ex__", None)
9696
if reductor:
97-
rv = reductor(2)
97+
rv = reductor(4)
9898
else:
9999
reductor = getattr(x, "__reduce__", None)
100100
if reductor:
@@ -171,7 +171,7 @@ def deepcopy(x, memo=None, _nil=[]):
171171
else:
172172
reductor = getattr(x, "__reduce_ex__", None)
173173
if reductor:
174-
rv = reductor(2)
174+
rv = reductor(4)
175175
else:
176176
reductor = getattr(x, "__reduce__", None)
177177
if reductor:

Lib/test/test_copy.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,40 @@ def __eq__(self, other):
146146
x = C(42)
147147
self.assertEqual(copy.copy(x), x)
148148

149+
def test_copy_inst_getnewargs(self):
150+
class C(int):
151+
def __new__(cls, foo):
152+
self = int.__new__(cls)
153+
self.foo = foo
154+
return self
155+
def __getnewargs__(self):
156+
return self.foo,
157+
def __eq__(self, other):
158+
return self.foo == other.foo
159+
x = C(42)
160+
y = copy.copy(x)
161+
self.assertIsInstance(y, C)
162+
self.assertEqual(y, x)
163+
self.assertIsNot(y, x)
164+
self.assertEqual(y.foo, x.foo)
165+
166+
def test_copy_inst_getnewargs_ex(self):
167+
class C(int):
168+
def __new__(cls, *, foo):
169+
self = int.__new__(cls)
170+
self.foo = foo
171+
return self
172+
def __getnewargs_ex__(self):
173+
return (), {'foo': self.foo}
174+
def __eq__(self, other):
175+
return self.foo == other.foo
176+
x = C(foo=42)
177+
y = copy.copy(x)
178+
self.assertIsInstance(y, C)
179+
self.assertEqual(y, x)
180+
self.assertIsNot(y, x)
181+
self.assertEqual(y.foo, x.foo)
182+
149183
def test_copy_inst_getstate(self):
150184
class C:
151185
def __init__(self, foo):
@@ -405,6 +439,42 @@ def __eq__(self, other):
405439
self.assertIsNot(y, x)
406440
self.assertIsNot(y.foo, x.foo)
407441

442+
def test_deepcopy_inst_getnewargs(self):
443+
class C(int):
444+
def __new__(cls, foo):
445+
self = int.__new__(cls)
446+
self.foo = foo
447+
return self
448+
def __getnewargs__(self):
449+
return self.foo,
450+
def __eq__(self, other):
451+
return self.foo == other.foo
452+
x = C([42])
453+
y = copy.deepcopy(x)
454+
self.assertIsInstance(y, C)
455+
self.assertEqual(y, x)
456+
self.assertIsNot(y, x)
457+
self.assertEqual(y.foo, x.foo)
458+
self.assertIsNot(y.foo, x.foo)
459+
460+
def test_deepcopy_inst_getnewargs_ex(self):
461+
class C(int):
462+
def __new__(cls, *, foo):
463+
self = int.__new__(cls)
464+
self.foo = foo
465+
return self
466+
def __getnewargs_ex__(self):
467+
return (), {'foo': self.foo}
468+
def __eq__(self, other):
469+
return self.foo == other.foo
470+
x = C(foo=[42])
471+
y = copy.deepcopy(x)
472+
self.assertIsInstance(y, C)
473+
self.assertEqual(y, x)
474+
self.assertIsNot(y, x)
475+
self.assertEqual(y.foo, x.foo)
476+
self.assertIsNot(y.foo, x.foo)
477+
408478
def test_deepcopy_inst_getstate(self):
409479
class C:
410480
def __init__(self, foo):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ Core and Builtins
2626
Library
2727
-------
2828

29+
- Issue #20289: The copy module now uses pickle protocol 4 (PEP 3154) and
30+
supports copying of instances of classes whose __new__ method takes
31+
keyword-only arguments.
32+
2933
- Issue #23491: Added a zipapp module to support creating executable zip
3034
file archives of Python code. Registered ".pyz" and ".pyzw" extensions
3135
on Windows for these archives (PEP 441).

0 commit comments

Comments
 (0)