From 99d2c251df4782c52c3e1cb89064374af39ecb46 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 13 Jun 2003 19:28:47 +0000 Subject: SF patch 707900, fixing bug 702858, by Steven Taschuk. Copying a new-style class that had a reference to itself didn't work. (The same thing worked fine for old-style classes.) --- Lib/copy.py | 1 + Lib/test/test_copy.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- Misc/NEWS | 4 ++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Lib/copy.py b/Lib/copy.py index a4a3ceb..02aa46b 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -334,6 +334,7 @@ def _reconstruct(x, info, deep, memo=None): if deep: args = deepcopy(args, memo) y = callable(*args) + memo[id(x)] = y if listiter is not None: for item in listiter: if deep: diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index c734a9a..a53f988 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -174,13 +174,15 @@ class TestCopy(unittest.TestCase): self.assertEqual(y, x) def test_deepcopy_memo(self): + # Tests of reflexive objects are under type-specific sections below. + # This tests only repetitions of objects. x = [] - x.append(x) + x = [x, x] y = copy.deepcopy(x) self.assertEqual(y, x) self.assert_(y is not x) self.assert_(y[0] is not x[0]) - self.assert_(y is y[0]) + self.assert_(y[0] is y[1]) def test_deepcopy_issubclass(self): # XXX Note: there's no way to test the TypeError coming out of @@ -266,6 +268,15 @@ class TestCopy(unittest.TestCase): self.assert_(x is not y) self.assert_(x[0] is not y[0]) + def test_deepcopy_reflexive_list(self): + x = [] + x.append(x) + y = copy.deepcopy(x) + self.assertEqual(y, x) + self.assert_(y is not x) + self.assert_(y[0] is not x[0]) + self.assert_(y is y[0]) + def test_deepcopy_tuple(self): x = ([1, 2], 3) y = copy.deepcopy(x) @@ -273,6 +284,15 @@ class TestCopy(unittest.TestCase): self.assert_(x is not y) self.assert_(x[0] is not y[0]) + def test_deepcopy_reflexive_tuple(self): + x = ([],) + x[0].append(x) + y = copy.deepcopy(x) + self.assertEqual(y, x) + self.assert_(y is not x) + self.assert_(y[0] is not x[0]) + self.assert_(y[0][0] is y) + def test_deepcopy_dict(self): x = {"foo": [1, 2], "bar": 3} y = copy.deepcopy(x) @@ -280,6 +300,15 @@ class TestCopy(unittest.TestCase): self.assert_(x is not y) self.assert_(x["foo"] is not y["foo"]) + def test_deepcopy_reflexive_dict(self): + x = {} + x['foo'] = x + y = copy.deepcopy(x) + self.assertEqual(y, x) + self.assert_(y is not x) + self.assert_(y['foo'] is y) + self.assertEqual(y, {'foo': y}) + def test_deepcopy_keepalive(self): memo = {} x = 42 @@ -369,6 +398,15 @@ class TestCopy(unittest.TestCase): self.assert_(y is not x) self.assert_(y.foo is not x.foo) + def test_deepcopy_reflexive_inst(self): + class C: + pass + x = C() + x.foo = x + y = copy.deepcopy(x) + self.assert_(y is not x) + self.assert_(y.foo is y) + # _reconstruct() def test_reconstruct_string(self): @@ -422,6 +460,15 @@ class TestCopy(unittest.TestCase): self.assertEqual(y, x) self.assert_(y.foo is not x.foo) + def test_reconstruct_reflexive(self): + class C(object): + pass + x = C() + x.foo = x + y = copy.deepcopy(x) + self.assert_(y is not x) + self.assert_(y.foo is y) + # Additions for Python 2.3 and pickle protocol 2 def test_reduce_4tuple(self): diff --git a/Misc/NEWS b/Misc/NEWS index 35b35b8..2ca8e9e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -70,6 +70,10 @@ Extension modules Library ------- +- copy.py: applied SF patch 707900, fixing bug 702858, by Steven + Taschuk. Copying a new-style class that had a reference to itself + didn't work. (The same thing worked fine for old-style classes.) + - difflib.py has two new functions: context_diff() and unified_diff(). - More fixes to urllib (SF 549151): (a) When redirecting, always use -- cgit v0.12