From d01fbce154886caa1f890ce5c1ead396a0252ab1 Mon Sep 17 00:00:00 2001 From: hakarrr Date: Sat, 24 Oct 2026 19:02:07 +0530 Subject: [PATCH 1/3] Fix key assignment and YAMLSerializer representation --- benedict/dicts/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benedict/dicts/__init__.py b/benedict/dicts/__init__.py index 92eca8da..22a77b67 100644 --- a/benedict/dicts/__init__.py +++ b/benedict/dicts/__init__.py @@ -92,7 +92,7 @@ def __deepcopy__(self, memo: dict[int, Any]) -> Self: keypath_separator=self._keypath_separator, ) for key, value in self.items(): - obj[key] = _clone(value, memo=memo) + obj[_clone(key, memo=memo)] = _clone(value, memo=memo) if self._frozen: obj.freeze() return obj From a12402a798db60527c0ba80ddac60f5beb4a1a95 Mon Sep 17 00:00:00 2001 From: hakarrr Date: Sat, 24 Oct 2026 19:02:24 +0530 Subject: [PATCH 2/3] Deep-copy BaseDict keys with the value memo --- benedict/dicts/base/base_dict.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benedict/dicts/base/base_dict.py b/benedict/dicts/base/base_dict.py index 204fdcf0..766d50bb 100644 --- a/benedict/dicts/base/base_dict.py +++ b/benedict/dicts/base/base_dict.py @@ -85,7 +85,7 @@ def __contains__(self, o: object) -> bool: def __deepcopy__(self, memo: dict[int, Any]) -> Self: obj = self.__class__() for key, value in self.items(): - obj[key] = _clone(value, memo=memo) + obj[_clone(key, memo=memo)] = _clone(value, memo=memo) if self._frozen: obj.freeze() return obj From ae5cb8cfb493f1e89dcf6383479c2cbd209672d7 Mon Sep 17 00:00:00 2001 From: hakarrr Date: Sat, 24 Oct 2026 19:04:26 +0530 Subject: [PATCH 3/3] Cover copied key aliases, wrapped dictionaries and frozen settings --- tests/dicts/test_deepcopy_keys.py | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/dicts/test_deepcopy_keys.py diff --git a/tests/dicts/test_deepcopy_keys.py b/tests/dicts/test_deepcopy_keys.py new file mode 100644 index 00000000..5b589817 --- /dev/null +++ b/tests/dicts/test_deepcopy_keys.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import copy +import unittest + +from benedict import benedict +from benedict.dicts.base import BaseDict + + +class deepcopy_keys_test_case(unittest.TestCase): + def test_base_deepcopy_custom_keys(self) -> None: + class Key: + def __init__(self) -> None: + self.values: list[int] = [] + + for wrapped in (False, True): + for frozen in (False, True): + with self.subTest(wrapped=wrapped, frozen=frozen): + key = Key() + source = {key: [key]} + original = BaseDict(source) if wrapped else BaseDict() + if not wrapped: + original[key] = source[key] + if frozen: + original.freeze() + cloned = copy.deepcopy(original) + cloned_key = next(iter(cloned)) + self.assertIsNot(cloned_key, key) + self.assertIs(cloned[cloned_key][0], cloned_key) + self.assertEqual(cloned.frozen, frozen) + cloned_key.values.append(1) + self.assertEqual(key.values, []) + self.assertIs(next(iter(original)), key) + + def test_benedict_deepcopy_custom_keys(self) -> None: + class Key: + def __init__(self) -> None: + self.values: list[int] = [] + + for separator in (None, "/"): + for frozen in (False, True): + with self.subTest(separator=separator, frozen=frozen): + key = Key() + original = benedict( + {key: [key]}, + keypath_separator=separator, + keyattr_enabled=False, + keyattr_dynamic=True, + ) + if frozen: + original.freeze() + cloned = original.deepcopy() + cloned_key = next(iter(cloned)) + self.assertIsNot(cloned_key, key) + self.assertIs(cloned[cloned_key][0], cloned_key) + self.assertEqual(cloned.frozen, frozen) + self.assertEqual(cloned.keypath_separator, separator) + self.assertFalse(cloned.keyattr_enabled) + self.assertTrue(cloned.keyattr_dynamic) + cloned_key.values.append(1) + self.assertEqual(key.values, [])