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 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 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, [])