[ILibraryView / Pattern] flatten() should raise PatternError if asked to preserve ports from a repeated ref

This commit is contained in:
Jan Petykiewicz 2026-03-30 21:17:33 -07:00
commit c32168dc64
4 changed files with 36 additions and 0 deletions

View file

@ -308,6 +308,11 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta):
continue
for ref in pat.refs[target]:
if flatten_ports and ref.repetition is not None and target_pat.ports:
raise PatternError(
f'Cannot flatten ports from repeated ref to {target!r}; '
'flatten with flatten_ports=False or expand/rename the ports manually first.'
)
p = ref.as_pattern(pattern=target_pat)
if not flatten_ports:
p.ports.clear()

View file

@ -1082,6 +1082,11 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
continue
for ref in refs:
if flatten_ports and ref.repetition is not None and target_pat.ports:
raise PatternError(
f'Cannot flatten ports from repeated ref to {target!r}; '
'flatten with flatten_ports=False or expand/rename the ports manually first.'
)
p = ref.as_pattern(pattern=target_pat)
if not flatten_ports:
p.ports.clear()

View file

@ -77,6 +77,20 @@ def test_library_flatten_preserves_ports_only_child() -> None:
assert tuple(flat_parent.ports["P1"].offset) == (11.0, 12.0)
def test_library_flatten_repeated_ref_with_ports_raises() -> None:
lib = Library()
child = Pattern(ports={"P1": Port((1, 2), 0)})
child.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]])
lib["child"] = child
parent = Pattern()
parent.ref("child", repetition=Grid(a_vector=(10, 0), a_count=2))
lib["parent"] = parent
with pytest.raises(PatternError, match='Cannot flatten ports from repeated ref'):
lib.flatten("parent", flatten_ports=True)
def test_lazy_library() -> None:
lib = LazyLibrary()
called = 0

View file

@ -114,6 +114,18 @@ def test_pattern_flatten_preserves_ports_only_child() -> None:
assert parent.ports["P1"].rotation == 0
assert tuple(parent.ports["P1"].offset) == (11.0, 12.0)
def test_pattern_flatten_repeated_ref_with_ports_raises() -> None:
child = Pattern(ports={"P1": Port((1, 2), 0)})
child.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]])
parent = Pattern()
parent.ref("child", repetition=Grid(a_vector=(10, 0), a_count=2))
with pytest.raises(PatternError, match='Cannot flatten ports from repeated ref'):
parent.flatten({"child": child}, flatten_ports=True)
def test_pattern_interface() -> None:
source = Pattern()
source.ports["A"] = Port((10, 20), 0, ptype="test")