summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-03-24 16:06:42 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-03-24 16:06:42 (GMT)
commit32af7549a7cf8f112c44526a28afa6c99e67269c (patch)
tree0984789f4a78bf02a3ed3713dc115116bfe24e2b /Lib
parent944fbcc478e36523add77574e172caf518647c74 (diff)
downloadcpython-32af7549a7cf8f112c44526a28afa6c99e67269c.zip
cpython-32af7549a7cf8f112c44526a28afa6c99e67269c.tar.gz
cpython-32af7549a7cf8f112c44526a28afa6c99e67269c.tar.bz2
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.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/copy.py4
-rw-r--r--Lib/test/test_copy.py70
2 files changed, 72 insertions, 2 deletions
diff --git a/Lib/copy.py b/Lib/copy.py
index 383609b..3a45fdf 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -94,7 +94,7 @@ def copy(x):
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
- rv = reductor(2)
+ rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
@@ -171,7 +171,7 @@ def deepcopy(x, memo=None, _nil=[]):
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
- rv = reductor(2)
+ rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index eb8d18c..498c270 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -146,6 +146,40 @@ class TestCopy(unittest.TestCase):
x = C(42)
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):
class C:
def __init__(self, foo):
@@ -405,6 +439,42 @@ class TestCopy(unittest.TestCase):
self.assertIsNot(y, x)
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):
class C:
def __init__(self, foo):