diff --git a/Lib/copy.py b/Lib/copy.py index 59886cbe8ff..18452849511 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -297,15 +297,34 @@ def _reconstruct(x, info, deep, memo=None): if memo is None: memo = {} n = len(info) - assert n in (2, 3) + assert n in (2, 3, 4, 5) callable, args = info[:2] if n > 2: state = info[2] else: state = {} + if n > 3: + listiter = info[3] + else: + listiter = None + if n > 4: + dictiter = info[4] + else: + dictiter = None if deep: args = deepcopy(args, memo) y = callable(*args) + if listiter is not None: + for item in listiter: + if deep: + item = deepcopy(item, memo) + y.append(item) + if dictiter is not None: + for key, value in dictiter: + if deep: + key = deepcopy(key, memo) + value = deepcopy(value, memo) + y[key] = value if state: if deep: state = deepcopy(state, memo) diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 90ef3fae3ee..a42b1499ad7 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -375,6 +375,42 @@ class TestCopy(unittest.TestCase): self.assertEqual(y, x) self.assert_(y.foo is not x.foo) + # Additions for Python 2.3 and pickle protocol 2 + + def test_reduce_4tuple(self): + class C(list): + def __reduce__(self): + return (C, (), self.__dict__, iter(self)) + def __cmp__(self, other): + return (cmp(list(self), list(other)) or + cmp(self.__dict__, other.__dict__)) + x = C([[1, 2], 3]) + y = copy.copy(x) + self.assertEqual(x, y) + self.assert_(x is not y) + self.assert_(x[0] is y[0]) + y = copy.deepcopy(x) + self.assertEqual(x, y) + self.assert_(x is not y) + self.assert_(x[0] is not y[0]) + + def test_reduce_5tuple(self): + class C(dict): + def __reduce__(self): + return (C, (), self.__dict__, None, self.iteritems()) + def __cmp__(self, other): + return (cmp(dict(self), list(dict)) or + cmp(self.__dict__, other.__dict__)) + x = C([("foo", [1, 2]), ("bar", 3)]) + y = copy.copy(x) + self.assertEqual(x, y) + self.assert_(x is not y) + self.assert_(x["foo"] is y["foo"]) + y = copy.deepcopy(x) + self.assertEqual(x, y) + self.assert_(x is not y) + self.assert_(x["foo"] is not y["foo"]) + def test_main(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCopy))