diff --git a/Lib/copy.py b/Lib/copy.py index da2908ef623d8c..6490706732bc7f 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -254,6 +254,33 @@ def _reconstruct(x, memo, func, args, if deep: memo[id(x)] = y + if isinstance(state, list): + if listiter is not None: + if deep: + for item in listiter: + item = deepcopy(item, memo) + y.append(item) + else: + for item in listiter: + y.append(item) + + if state is not None: + if deep: + state = deepcopy(state, memo) + if hasattr(y, '__setstate__'): + y.__setstate__(state) + else: + if isinstance(state, tuple) and len(state) == 2: + state, slotstate = state + else: + slotstate = None + if state is not None: + y.__dict__.update(state) + if slotstate is not None: + for key, value in slotstate.items(): + setattr(y, key, value) + return y + if state is not None: if deep: state = deepcopy(state, memo) diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 826e46824e004c..5b9899804249f6 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -761,6 +761,18 @@ class C(list): self.assertIsNot(x[0], y[0]) self.assertIsNot(x.foo, y.foo) + class L(list): + def __getstate__(self): + return list(self) + + def __setstate__(self, state): + self[:] = state + + l1 = L([1, 2]) + l2 = copy.deepcopy(l1) + self.assertEqual(l1, l2) + self.assertEqual(len(l1), len(l2)) + def test_copy_tuple_subclass(self): class C(tuple): pass diff --git a/Misc/NEWS.d/next/Library/2023-01-31-16-48-54.gh-issue-48962.RvwDsB.rst b/Misc/NEWS.d/next/Library/2023-01-31-16-48-54.gh-issue-48962.RvwDsB.rst new file mode 100644 index 00000000000000..235929e5fbe333 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-31-16-48-54.gh-issue-48962.RvwDsB.rst @@ -0,0 +1 @@ +Fix duplicate values in the list when deepcopying a subclass list in the copy module.