From bb96461594ee6f9a7ca58fee826b913a9d8f9535 Mon Sep 17 00:00:00 2001 From: Jakub Krajewski Date: Thu, 6 Jun 2024 21:06:15 +0200 Subject: [PATCH 1/2] Add copy and deepcopy --- catalystwan/tests/test_typed_list.py | 25 +++++++++++++++++++++++++ catalystwan/typed_list.py | 12 +++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/catalystwan/tests/test_typed_list.py b/catalystwan/tests/test_typed_list.py index 9fcba301..3585f05c 100644 --- a/catalystwan/tests/test_typed_list.py +++ b/catalystwan/tests/test_typed_list.py @@ -1,3 +1,4 @@ +# Copyright 2024 Cisco Systems, Inc. and its affiliates # Copyright 2023 Cisco Systems, Inc. and its affiliates # type: ignore @@ -397,6 +398,30 @@ def test_find_no_match(self): with self.assertRaises(InvalidOperationError): self.data_sequence.find(username="NonExistingUser") + def test_deepcopy_basemodel(self): + # Arrange + user = User(username="admin") + ds = DataSequence(User, [user]) + # Act + ds_deepcopy = copy.deepcopy(ds) + user_deepcopied = ds_deepcopy[0] + # Assert + self.assertIsNot(ds, ds_deepcopy) + self.assertIsNot(user, user_deepcopied) + self.assertEqual(user.username, user_deepcopied.username) + + def test_deepcopy_dataclass(self): + # Arrange + fu = FakeUser(name="admin", weight=87.5) + ds = DataSequence(FakeUser, [fu]) + # Act + ds_deepcopy = copy.deepcopy(ds) + fd_deepcopied = ds_deepcopy[0] + # Assert + self.assertIsNot(ds, ds_deepcopy) + self.assertIsNot(fu, fd_deepcopied) + self.assertEqual(fu.name, fd_deepcopied.name) + if __name__ == "__main__": unittest.main() diff --git a/catalystwan/typed_list.py b/catalystwan/typed_list.py index ba7792a2..ecd09101 100644 --- a/catalystwan/typed_list.py +++ b/catalystwan/typed_list.py @@ -1,7 +1,8 @@ -# Copyright 2023 Cisco Systems, Inc. and its affiliates +# Copyright 2024 Cisco Systems, Inc. and its affiliates from __future__ import annotations +import copy from typing import Any, Generic, Iterable, MutableSequence, Type, TypeVar, overload from pydantic import BaseModel @@ -186,6 +187,15 @@ def __iadd__(self, __value: Iterable[T]) -> DataSequence[T]: self.data = DataSequence(self._type, self.data + [*__value.__iter__()]).data return self + def __copy__(self) -> DataSequence[T]: + return DataSequence(self._type, self.data) + + def __deepcopy__(self, memo) -> DataSequence[T]: + if issubclass(self._type, BaseModel): + return DataSequence(self._type, [o.model_copy(deep=True) for o in self]) # type: ignore + else: + return DataSequence(self._type, [copy.deepcopy(o, memo) for o in self]) + @overload def single_or_default(self) -> T: ... From 28f1c6cce10bff8a462029f7af4265ab55647b78 Mon Sep 17 00:00:00 2001 From: Jakub Krajewski Date: Thu, 6 Jun 2024 21:23:27 +0200 Subject: [PATCH 2/2] Remove 2023 license --- catalystwan/tests/test_typed_list.py | 1 - 1 file changed, 1 deletion(-) diff --git a/catalystwan/tests/test_typed_list.py b/catalystwan/tests/test_typed_list.py index 3585f05c..ff8f7661 100644 --- a/catalystwan/tests/test_typed_list.py +++ b/catalystwan/tests/test_typed_list.py @@ -1,5 +1,4 @@ # Copyright 2024 Cisco Systems, Inc. and its affiliates -# Copyright 2023 Cisco Systems, Inc. and its affiliates # type: ignore import copy