[Pattern.append] don't dirty pattern if append() fails
This commit is contained in:
parent
6a7b3b2259
commit
35b42c397b
2 changed files with 37 additions and 7 deletions
|
|
@ -349,6 +349,16 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
"""
|
||||||
|
annotation_conflicts: set[str] = set()
|
||||||
|
if other_pattern.annotations is not None and self.annotations is not None:
|
||||||
|
annotation_conflicts = set(self.annotations.keys()) & set(other_pattern.annotations.keys())
|
||||||
|
if annotation_conflicts:
|
||||||
|
raise PatternError(f'Annotation keys overlap: {annotation_conflicts}')
|
||||||
|
|
||||||
|
port_conflicts = set(self.ports.keys()) & set(other_pattern.ports.keys())
|
||||||
|
if port_conflicts:
|
||||||
|
raise PatternError(f'Port names overlap: {port_conflicts}')
|
||||||
|
|
||||||
for target, rseq in other_pattern.refs.items():
|
for target, rseq in other_pattern.refs.items():
|
||||||
self.refs[target].extend(rseq)
|
self.refs[target].extend(rseq)
|
||||||
for layer, sseq in other_pattern.shapes.items():
|
for layer, sseq in other_pattern.shapes.items():
|
||||||
|
|
@ -359,14 +369,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
||||||
if other_pattern.annotations is not None:
|
if other_pattern.annotations is not None:
|
||||||
if self.annotations is None:
|
if self.annotations is None:
|
||||||
self.annotations = {}
|
self.annotations = {}
|
||||||
annotation_conflicts = set(self.annotations.keys()) & set(other_pattern.annotations.keys())
|
|
||||||
if annotation_conflicts:
|
|
||||||
raise PatternError(f'Annotation keys overlap: {annotation_conflicts}')
|
|
||||||
self.annotations.update(other_pattern.annotations)
|
self.annotations.update(other_pattern.annotations)
|
||||||
|
|
||||||
port_conflicts = set(self.ports.keys()) & set(other_pattern.ports.keys())
|
|
||||||
if port_conflicts:
|
|
||||||
raise PatternError(f'Port names overlap: {port_conflicts}')
|
|
||||||
self.ports.update(other_pattern.ports)
|
self.ports.update(other_pattern.ports)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,33 @@ def test_pattern_interface() -> None:
|
||||||
assert iface.ports["out_A"].ptype == "test"
|
assert iface.ports["out_A"].ptype == "test"
|
||||||
|
|
||||||
|
|
||||||
|
def test_pattern_append_port_conflict_is_atomic() -> None:
|
||||||
|
pat1 = Pattern()
|
||||||
|
pat1.ports["A"] = Port((0, 0), 0)
|
||||||
|
|
||||||
|
pat2 = Pattern()
|
||||||
|
pat2.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]])
|
||||||
|
pat2.ports["A"] = Port((1, 0), 0)
|
||||||
|
|
||||||
|
with pytest.raises(PatternError, match="Port names overlap"):
|
||||||
|
pat1.append(pat2)
|
||||||
|
|
||||||
|
assert not pat1.shapes
|
||||||
|
assert set(pat1.ports) == {"A"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_pattern_append_annotation_conflict_is_atomic() -> None:
|
||||||
|
pat1 = Pattern(annotations={"k": [1]})
|
||||||
|
pat2 = Pattern(annotations={"k": [2]})
|
||||||
|
pat2.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]])
|
||||||
|
|
||||||
|
with pytest.raises(PatternError, match="Annotation keys overlap"):
|
||||||
|
pat1.append(pat2)
|
||||||
|
|
||||||
|
assert not pat1.shapes
|
||||||
|
assert pat1.annotations == {"k": [1]}
|
||||||
|
|
||||||
|
|
||||||
def test_pattern_deepcopy_does_not_share_shape_repetitions() -> None:
|
def test_pattern_deepcopy_does_not_share_shape_repetitions() -> None:
|
||||||
pat = Pattern()
|
pat = Pattern()
|
||||||
pat.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]], repetition=Grid(a_vector=(10, 0), a_count=2))
|
pat.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]], repetition=Grid(a_vector=(10, 0), a_count=2))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue