https://github.com/python/cpython/commit/646bd86e3b2f4f484129bd4a926cf73fafc9f874
commit: 646bd86e3b2f4f484129bd4a926cf73fafc9f874
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-02-21T15:30:40Z
summary:
gh-141510: Fix copy.deepcopy() for recursive frozendict (#145027)
files:
M Lib/copy.py
M Lib/test/test_copy.py
diff --git a/Lib/copy.py b/Lib/copy.py
index 33dabb3395a7c0..6149301ad1389e 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -204,7 +204,17 @@ def _deepcopy_dict(x, memo, deepcopy=deepcopy):
d[dict] = _deepcopy_dict
def _deepcopy_frozendict(x, memo, deepcopy=deepcopy):
- y = _deepcopy_dict(x, memo, deepcopy)
+ y = {}
+ for key, value in x.items():
+ y[deepcopy(key, memo)] = deepcopy(value, memo)
+
+ # We're not going to put the frozendict in the memo, but it's still
+ # important we check for it, in case the frozendict contains recursive
+ # mutable structures.
+ try:
+ return memo[id(x)]
+ except KeyError:
+ pass
return frozendict(y)
d[frozendict] = _deepcopy_frozendict
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index 858e5e089d5aba..98f56b5ae87f96 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -432,6 +432,23 @@ def test_deepcopy_frozendict(self):
self.assertIsNot(x, y)
self.assertIsNot(x["foo"], y["foo"])
+ # recursive frozendict
+ x = frozendict(foo=[])
+ x['foo'].append(x)
+ y = copy.deepcopy(x)
+ self.assertEqual(y.keys(), x.keys())
+ self.assertIsNot(x, y)
+ self.assertIsNot(x["foo"], y["foo"])
+ self.assertIs(y['foo'][0], y)
+
+ x = frozendict(foo=[])
+ x['foo'].append(x)
+ x = x['foo']
+ y = copy.deepcopy(x)
+ self.assertIsNot(x, y)
+ self.assertIsNot(x[0], y[0])
+ self.assertIs(y[0]['foo'], y)
+
@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_deepcopy_reflexive_dict(self):
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]