diff --git a/tests/test_components.py b/tests/test_components.py index 87bce592d6..745abe049f 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -836,3 +836,54 @@ def test_mode_object_syms(): ) ], ) + + +def test_deep_copy(): + """Make sure deep copying works as expceted with defaults.""" + b = Box(size=(1, 1, 1)) + m = Medium(permittivity=1) + + s = Structure( + geometry=b, + medium=m, + ) + + s_shallow = s.copy(deep=False) + + # with shallow copy, these should be the same objects + assert id(s.geometry) == id(s_shallow.geometry) + assert id(s.medium) == id(s_shallow.medium) + + s_deep = s.copy(deep=True) + + # with deep copy, these should be different objects + assert id(s.geometry) != id(s_deep.geometry) + assert id(s.medium) != id(s_deep.medium) + + # default should be deep + s_default = s.copy() + assert id(s.geometry) != id(s_default.geometry) + assert id(s.medium) != id(s_default.medium) + + # make sure other kwargs work, here we update the geometry to a sphere and shallow copy medium + s_kwargs = s.copy(deep=False, update={"geometry": Sphere(radius=1.0)}) + assert id(s.medium) == id(s_kwargs.medium) + assert id(s.geometry) != id(s_kwargs.geometry) + + # behavior of modifying attributes + s_default = s.copy() + s_default.geometry = Sphere(radius=1.0) + assert id(s.geometry) != id(s_default.geometry) + + s_shallow = s.copy(deep=False) + s_shallow.geometry = Sphere(radius=1.0) + assert id(s.geometry) != id(s_shallow.geometry) + + # behavior of modifying attributes of attributes + s_default = s.copy() + s_default.geometry.size = (2, 2, 2) + assert id(s.geometry) != id(s_default.geometry) + + s_shallow = s.copy(deep=False) + s_shallow.geometry.size = (2, 2, 2) + assert id(s.geometry) == id(s_shallow.geometry) diff --git a/tidy3d/components/base.py b/tidy3d/components/base.py index 8b4a03f4f0..12eec55071 100644 --- a/tidy3d/components/base.py +++ b/tidy3d/components/base.py @@ -61,6 +61,10 @@ class Config: # pylint: disable=too-few-public-methods complex: lambda x: ComplexNumber(real=x.real, imag=x.imag), } + def copy(self, deep: bool = True, **kwargs) -> "Self": + """Copy a Tidy3dBaseModel. With ``deep=True`` as default.""" + return super().copy(deep=deep, **kwargs) + def help(self, methods: bool = False) -> None: """Prints message describing the fields and methods of a :class:`Tidy3dBaseModel`.