152 lines
3.7 KiB
Python
152 lines
3.7 KiB
Python
import pytest
|
|
from typing import cast, TYPE_CHECKING
|
|
from ..library import Library, LazyLibrary
|
|
from ..pattern import Pattern
|
|
from ..error import LibraryError, PatternError
|
|
from ..ports import Port
|
|
from ..repetition import Grid
|
|
|
|
if TYPE_CHECKING:
|
|
from ..shapes import Polygon
|
|
|
|
|
|
def test_library_basic() -> None:
|
|
lib = Library()
|
|
pat = Pattern()
|
|
lib["cell1"] = pat
|
|
|
|
assert "cell1" in lib
|
|
assert lib["cell1"] is pat
|
|
assert len(lib) == 1
|
|
|
|
with pytest.raises(LibraryError):
|
|
lib["cell1"] = Pattern() # Overwriting not allowed
|
|
|
|
|
|
def test_library_tops() -> None:
|
|
lib = Library()
|
|
lib["child"] = Pattern()
|
|
lib["parent"] = Pattern()
|
|
lib["parent"].ref("child")
|
|
|
|
assert set(lib.tops()) == {"parent"}
|
|
assert lib.top() == "parent"
|
|
|
|
|
|
def test_library_dangling() -> None:
|
|
lib = Library()
|
|
lib["parent"] = Pattern()
|
|
lib["parent"].ref("missing")
|
|
|
|
assert lib.dangling_refs() == {"missing"}
|
|
|
|
|
|
def test_library_flatten() -> None:
|
|
lib = Library()
|
|
child = Pattern()
|
|
child.polygon((1, 0), vertices=[[0, 0], [1, 0], [0, 1]])
|
|
lib["child"] = child
|
|
|
|
parent = Pattern()
|
|
parent.ref("child", offset=(10, 10))
|
|
lib["parent"] = parent
|
|
|
|
flat_lib = lib.flatten("parent")
|
|
flat_parent = flat_lib["parent"]
|
|
|
|
assert not flat_parent.has_refs()
|
|
assert len(flat_parent.shapes[(1, 0)]) == 1
|
|
# Transformations are baked into vertices for Polygon
|
|
assert_vertices = cast("Polygon", flat_parent.shapes[(1, 0)][0]).vertices
|
|
assert tuple(assert_vertices[0]) == (10.0, 10.0)
|
|
|
|
|
|
def test_library_flatten_preserves_ports_only_child() -> None:
|
|
lib = Library()
|
|
child = Pattern(ports={"P1": Port((1, 2), 0)})
|
|
lib["child"] = child
|
|
|
|
parent = Pattern()
|
|
parent.ref("child", offset=(10, 10))
|
|
lib["parent"] = parent
|
|
|
|
flat_parent = lib.flatten("parent", flatten_ports=True)["parent"]
|
|
|
|
assert set(flat_parent.ports) == {"P1"}
|
|
assert cast("Port", flat_parent.ports["P1"]).rotation == 0
|
|
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
|
|
|
|
def make_pat() -> Pattern:
|
|
nonlocal called
|
|
called += 1
|
|
return Pattern()
|
|
|
|
lib["lazy"] = make_pat
|
|
assert called == 0
|
|
|
|
pat = lib["lazy"]
|
|
assert called == 1
|
|
assert isinstance(pat, Pattern)
|
|
|
|
# Second access should be cached
|
|
pat2 = lib["lazy"]
|
|
assert called == 1
|
|
assert pat is pat2
|
|
|
|
|
|
def test_library_rename() -> None:
|
|
lib = Library()
|
|
lib["old"] = Pattern()
|
|
lib["parent"] = Pattern()
|
|
lib["parent"].ref("old")
|
|
|
|
lib.rename("old", "new", move_references=True)
|
|
|
|
assert "old" not in lib
|
|
assert "new" in lib
|
|
assert "new" in lib["parent"].refs
|
|
assert "old" not in lib["parent"].refs
|
|
|
|
|
|
def test_library_subtree() -> None:
|
|
lib = Library()
|
|
lib["a"] = Pattern()
|
|
lib["b"] = Pattern()
|
|
lib["c"] = Pattern()
|
|
lib["a"].ref("b")
|
|
|
|
sub = lib.subtree("a")
|
|
assert "a" in sub
|
|
assert "b" in sub
|
|
assert "c" not in sub
|
|
|
|
|
|
def test_library_get_name() -> None:
|
|
lib = Library()
|
|
lib["cell"] = Pattern()
|
|
|
|
name1 = lib.get_name("cell")
|
|
assert name1 != "cell"
|
|
assert name1.startswith("cell")
|
|
|
|
name2 = lib.get_name("other")
|
|
assert name2 == "other"
|