Issue #1100562: Fix deep-copying of objects derived from the list and dict types.
Patch by Michele Orrù and Björn Lindqvist.
This commit is contained in:
parent
e5a9101519
commit
3941a8fece
34
Lib/copy.py
34
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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue