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.
This commit is contained in:
Serhiy Storchaka 2015-03-24 18:06:42 +02:00
parent 944fbcc478
commit 32af7549a7
3 changed files with 76 additions and 2 deletions

View file

@ -94,7 +94,7 @@ def copy(x):
else: else:
reductor = getattr(x, "__reduce_ex__", None) reductor = getattr(x, "__reduce_ex__", None)
if reductor: if reductor:
rv = reductor(2) rv = reductor(4)
else: else:
reductor = getattr(x, "__reduce__", None) reductor = getattr(x, "__reduce__", None)
if reductor: if reductor:
@ -171,7 +171,7 @@ def deepcopy(x, memo=None, _nil=[]):
else: else:
reductor = getattr(x, "__reduce_ex__", None) reductor = getattr(x, "__reduce_ex__", None)
if reductor: if reductor:
rv = reductor(2) rv = reductor(4)
else: else:
reductor = getattr(x, "__reduce__", None) reductor = getattr(x, "__reduce__", None)
if reductor: if reductor:

View file

@ -146,6 +146,40 @@ class TestCopy(unittest.TestCase):
x = C(42) x = C(42)
self.assertEqual(copy.copy(x), x) self.assertEqual(copy.copy(x), x)
def test_copy_inst_getnewargs(self):
class C(int):
def __new__(cls, foo):
self = int.__new__(cls)
self.foo = foo
return self
def __getnewargs__(self):
return self.foo,
def __eq__(self, other):
return self.foo == other.foo
x = C(42)
y = copy.copy(x)
self.assertIsInstance(y, C)
self.assertEqual(y, x)
self.assertIsNot(y, x)
self.assertEqual(y.foo, x.foo)
def test_copy_inst_getnewargs_ex(self):
class C(int):
def __new__(cls, *, foo):
self = int.__new__(cls)
self.foo = foo
return self
def __getnewargs_ex__(self):
return (), {'foo': self.foo}
def __eq__(self, other):
return self.foo == other.foo
x = C(foo=42)
y = copy.copy(x)
self.assertIsInstance(y, C)
self.assertEqual(y, x)
self.assertIsNot(y, x)
self.assertEqual(y.foo, x.foo)
def test_copy_inst_getstate(self): def test_copy_inst_getstate(self):
class C: class C:
def __init__(self, foo): def __init__(self, foo):
@ -405,6 +439,42 @@ class TestCopy(unittest.TestCase):
self.assertIsNot(y, x) self.assertIsNot(y, x)
self.assertIsNot(y.foo, x.foo) self.assertIsNot(y.foo, x.foo)
def test_deepcopy_inst_getnewargs(self):
class C(int):
def __new__(cls, foo):
self = int.__new__(cls)
self.foo = foo
return self
def __getnewargs__(self):
return self.foo,
def __eq__(self, other):
return self.foo == other.foo
x = C([42])
y = copy.deepcopy(x)
self.assertIsInstance(y, C)
self.assertEqual(y, x)
self.assertIsNot(y, x)
self.assertEqual(y.foo, x.foo)
self.assertIsNot(y.foo, x.foo)
def test_deepcopy_inst_getnewargs_ex(self):
class C(int):
def __new__(cls, *, foo):
self = int.__new__(cls)
self.foo = foo
return self
def __getnewargs_ex__(self):
return (), {'foo': self.foo}
def __eq__(self, other):
return self.foo == other.foo
x = C(foo=[42])
y = copy.deepcopy(x)
self.assertIsInstance(y, C)
self.assertEqual(y, x)
self.assertIsNot(y, x)
self.assertEqual(y.foo, x.foo)
self.assertIsNot(y.foo, x.foo)
def test_deepcopy_inst_getstate(self): def test_deepcopy_inst_getstate(self):
class C: class C:
def __init__(self, foo): def __init__(self, foo):

View file

@ -26,6 +26,10 @@ Core and Builtins
Library Library
------- -------
- 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.
- Issue #23491: Added a zipapp module to support creating executable zip - Issue #23491: Added a zipapp module to support creating executable zip
file archives of Python code. Registered ".pyz" and ".pyzw" extensions file archives of Python code. Registered ".pyz" and ".pyzw" extensions
on Windows for these archives (PEP 441). on Windows for these archives (PEP 441).