diff --git a/masque/label.py b/masque/label.py index 3dbbc08..6a2a61f 100644 --- a/masque/label.py +++ b/masque/label.py @@ -65,6 +65,7 @@ class Label(PositionableImpl, RepeatableImpl, AnnotatableImpl, Bounded, Pivotabl memo = {} if memo is None else memo new = copy.copy(self) new._offset = self._offset.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations, memo) return new diff --git a/masque/shapes/arc.py b/masque/shapes/arc.py index e6d49cf..2adfe10 100644 --- a/masque/shapes/arc.py +++ b/masque/shapes/arc.py @@ -187,6 +187,7 @@ class Arc(PositionableImpl, Shape): new._offset = self._offset.copy() new._radii = self._radii.copy() new._angles = self._angles.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/circle.py b/masque/shapes/circle.py index a6f7af1..19f3f2b 100644 --- a/masque/shapes/circle.py +++ b/masque/shapes/circle.py @@ -68,6 +68,7 @@ class Circle(PositionableImpl, Shape): memo = {} if memo is None else memo new = copy.copy(self) new._offset = self._offset.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/ellipse.py b/masque/shapes/ellipse.py index 49f6489..38799da 100644 --- a/masque/shapes/ellipse.py +++ b/masque/shapes/ellipse.py @@ -117,6 +117,7 @@ class Ellipse(PositionableImpl, Shape): new = copy.copy(self) new._offset = self._offset.copy() new._radii = self._radii.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/path.py b/masque/shapes/path.py index 3aa6f07..7038309 100644 --- a/masque/shapes/path.py +++ b/masque/shapes/path.py @@ -235,6 +235,7 @@ class Path(Shape): new._vertices = self._vertices.copy() new._cap = copy.deepcopy(self._cap, memo) new._cap_extensions = copy.deepcopy(self._cap_extensions, memo) + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/poly_collection.py b/masque/shapes/poly_collection.py index 711acc4..cd233ba 100644 --- a/masque/shapes/poly_collection.py +++ b/masque/shapes/poly_collection.py @@ -124,6 +124,7 @@ class PolyCollection(Shape): new = copy.copy(self) new._vertex_lists = self._vertex_lists.copy() new._vertex_offsets = self._vertex_offsets.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/polygon.py b/masque/shapes/polygon.py index 34a784b..a743de2 100644 --- a/masque/shapes/polygon.py +++ b/masque/shapes/polygon.py @@ -135,6 +135,7 @@ class Polygon(Shape): memo = {} if memo is None else memo new = copy.copy(self) new._vertices = self._vertices.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/shapes/text.py b/masque/shapes/text.py index 93f2024..5047dc4 100644 --- a/masque/shapes/text.py +++ b/masque/shapes/text.py @@ -98,6 +98,7 @@ class Text(PositionableImpl, RotatableImpl, Shape): memo = {} if memo is None else memo new = copy.copy(self) new._offset = self._offset.copy() + new._repetition = copy.deepcopy(self._repetition, memo) new._annotations = copy.deepcopy(self._annotations) return new diff --git a/masque/test/test_pattern.py b/masque/test/test_pattern.py index 07e4150..e875641 100644 --- a/masque/test/test_pattern.py +++ b/masque/test/test_pattern.py @@ -1,4 +1,5 @@ import pytest +import copy from typing import cast from numpy.testing import assert_equal, assert_allclose from numpy import pi @@ -148,3 +149,26 @@ def test_pattern_interface() -> None: assert_allclose(iface.ports["out_A"].rotation, 0, atol=1e-10) assert iface.ports["in_A"].ptype == "test" assert iface.ports["out_A"].ptype == "test" + + +def test_pattern_deepcopy_does_not_share_shape_repetitions() -> None: + pat = Pattern() + pat.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]], repetition=Grid(a_vector=(10, 0), a_count=2)) + + pat2 = copy.deepcopy(pat) + pat2.scale_by(2) + + assert_allclose(cast("Polygon", pat.shapes[(1, 0)][0]).repetition.a_vector, [10, 0]) + assert_allclose(cast("Polygon", pat2.shapes[(1, 0)][0]).repetition.a_vector, [20, 0]) + + +def test_pattern_flatten_does_not_mutate_child_repetitions() -> None: + child = Pattern() + child.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]], repetition=Grid(a_vector=(10, 0), a_count=2)) + + parent = Pattern() + parent.ref("child", scale=2) + + parent.flatten({"child": child}) + + assert_allclose(cast("Polygon", child.shapes[(1, 0)][0]).repetition.a_vector, [10, 0])