summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-09-04 17:40:21 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-09-04 17:40:21 (GMT)
commit3941a8fece7e714583965565795f2986aa203cb1 (patch)
treee021f726f4c243bd475371e7300b82b8d16106d9
parente5a9101519ded4efc38611d2f93594f3fe04147f (diff)
downloadcpython-3941a8fece7e714583965565795f2986aa203cb1.zip
cpython-3941a8fece7e714583965565795f2986aa203cb1.tar.gz
cpython-3941a8fece7e714583965565795f2986aa203cb1.tar.bz2
Issue #1100562: Fix deep-copying of objects derived from the list and dict types.
Patch by Michele Orrù and Björn Lindqvist.
-rw-r--r--Lib/copy.py34
-rw-r--r--Lib/test/test_copy.py20
-rw-r--r--Misc/NEWS3
3 files changed, 46 insertions, 11 deletions
diff --git a/Lib/copy.py b/Lib/copy.py
index 789488c..07f1d23 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -283,17 +283,7 @@ def _reconstruct(x, info, deep, memo=None):
args = deepcopy(args, memo)
y = callable(*args)
memo[id(x)] = y
- 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)
@@ -309,6 +299,18 @@ def _reconstruct(x, info, deep, memo=None):
if slotstate is not None:
for key, value in slotstate.items():
setattr(y, key, value)
+
+ 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
return y
del d
@@ -370,6 +372,16 @@ def _test():
print(map(reprlib.repr, l1))
print(map(reprlib.repr, l2))
print(map(reprlib.repr, l3))
+ class odict(dict):
+ def __init__(self, d = {}):
+ self.a = 99
+ dict.__init__(self, d)
+ def __setitem__(self, k, i):
+ dict.__setitem__(self, k, i)
+ self.a
+ o = odict({"A" : "B"})
+ x = deepcopy(o)
+ print(o, x)
if __name__ == '__main__':
_test()
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index 732b4f4..a84c109 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -532,6 +532,26 @@ class TestCopy(unittest.TestCase):
self.assertEqual(x.foo, y.foo)
self.assertTrue(x.foo is not y.foo)
+ def test_deepcopy_dict_subclass(self):
+ class C(dict):
+ def __init__(self, d=None):
+ if not d:
+ d = {}
+ self._keys = list(d.keys())
+ super().__init__(d)
+ def __setitem__(self, key, item):
+ super().__setitem__(key, item)
+ if key not in self._keys:
+ self._keys.append(key)
+ x = C(d={'foo':0})
+ y = copy.deepcopy(x)
+ self.assertEqual(x, y)
+ self.assertEqual(x._keys, y._keys)
+ self.assertTrue(x is not y)
+ x['bar'] = 1
+ self.assertNotEqual(x, y)
+ self.assertNotEqual(x._keys, y._keys)
+
def test_copy_list_subclass(self):
class C(list):
pass
diff --git a/Misc/NEWS b/Misc/NEWS
index 1433598..4673e02 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -158,6 +158,9 @@ Extensions
Library
-------
+- Issue #1100562: Fix deep-copying of objects derived from the list and
+ dict types. Patch by Michele Orrù and Björn Lindqvist.
+
- Issue #9753: Fixed socket.dup, which did not always work correctly
on Windows.