https://github.com/python/cpython/commit/dd64e4260e0d114f8259f15bc86fb17c5b08c80b
commit: dd64e4260e0d114f8259f15bc86fb17c5b08c80b
branch: main
author: Pieter Eendebak <[email protected]>
committer: vstinner <[email protected]>
date: 2026-02-18T12:30:26+01:00
summary:

gh-141510: Implement copy and deepcopy for frozendict (#144905)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst
M Lib/copy.py
M Lib/test/test_copy.py

diff --git a/Lib/copy.py b/Lib/copy.py
index 4c024ab5311d2d..33dabb3395a7c0 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -101,7 +101,7 @@ def copy(x):
 
 
 _copy_atomic_types = frozenset({types.NoneType, int, float, bool, complex, 
str, tuple,
-          bytes, frozenset, type, range, slice, property,
+          bytes, frozendict, frozenset, type, range, slice, property,
           types.BuiltinFunctionType, types.EllipsisType,
           types.NotImplementedType, types.FunctionType, types.CodeType,
           weakref.ref, super})
@@ -203,6 +203,11 @@ def _deepcopy_dict(x, memo, deepcopy=deepcopy):
     return y
 d[dict] = _deepcopy_dict
 
+def _deepcopy_frozendict(x, memo, deepcopy=deepcopy):
+    y = _deepcopy_dict(x, memo, deepcopy)
+    return frozendict(y)
+d[frozendict] = _deepcopy_frozendict
+
 def _deepcopy_method(x, memo): # Copy instance methods
     return type(x)(x.__func__, deepcopy(x.__self__, memo))
 d[types.MethodType] = _deepcopy_method
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index cfef24727e8c82..858e5e089d5aba 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -133,6 +133,12 @@ def test_copy_dict(self):
         self.assertEqual(y, x)
         self.assertIsNot(y, x)
 
+    def test_copy_frozendict(self):
+        x = frozendict(x=1, y=2)
+        self.assertIs(copy.copy(x), x)
+        x = frozendict()
+        self.assertIs(copy.copy(x), x)
+
     def test_copy_set(self):
         x = {1, 2, 3}
         y = copy.copy(x)
@@ -419,6 +425,13 @@ def test_deepcopy_dict(self):
         self.assertIsNot(x, y)
         self.assertIsNot(x["foo"], y["foo"])
 
+    def test_deepcopy_frozendict(self):
+        x = frozendict({"foo": [1, 2], "bar": 3})
+        y = copy.deepcopy(x)
+        self.assertEqual(y, x)
+        self.assertIsNot(x, y)
+        self.assertIsNot(x["foo"], y["foo"])
+
     @support.skip_emscripten_stack_overflow()
     @support.skip_wasi_stack_overflow()
     def test_deepcopy_reflexive_dict(self):
diff --git 
a/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst 
b/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst
new file mode 100644
index 00000000000000..5b604124c6d7cc
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst
@@ -0,0 +1,2 @@
+The :mod:`copy` module now supports the :class:`frozendict` type. Patch by
+Pieter Eendebak based on work by Victor Stinner.

_______________________________________________
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]

Reply via email to