[BuildLibrary] eliminate BuiltLibrary and BuiltOverlayLibrary

This commit is contained in:
Jan Petykiewicz 2026-06-19 21:04:18 -07:00
commit 3dea61b05e
6 changed files with 95 additions and 191 deletions

View file

@ -2,11 +2,18 @@ import pytest
from ..builder import Pather
from ..error import BuildError
from ..library import BuildLibrary, BuiltLibrary, Library, cell
from ..library import BuildLibrary, Library, cell
from ..pattern import Pattern
from ..ports import Port
def _owned_by(report, owner: str) -> set[str]:
return {
name for name, prov in report.provenance.items()
if prov.owner_declared_name == owner
}
def test_build_library_traces_declared_dependencies_out_of_order() -> None:
builder = BuildLibrary()
@ -19,12 +26,12 @@ def test_build_library_traces_declared_dependencies_out_of_order() -> None:
builder.cells.parent = cell(make_parent)(builder)
builder["child"] = Pattern(ports={"p": Port((0, 0), 0)})
built = builder.build()
built, report = builder.build()
assert "parent" in built
assert "child" in built
assert built.build_report.dependency_graph["parent"] == frozenset({"child"})
assert built.build_report.provenance["parent"].kind == "declared"
assert report.dependency_graph["parent"] == frozenset({"child"})
assert report.provenance["parent"].kind == "declared"
def test_build_library_tracks_helper_provenance_and_tree_merge_renames() -> None:
@ -40,17 +47,15 @@ def test_build_library_tracks_helper_provenance_and_tree_merge_renames() -> None
return top
builder.cells.top = cell(make_top)(builder)
built = builder.build()
report = built.build_report
_built, report = builder.build()
helpers = [
prov for prov in report.provenance.values()
if prov.owner_declared_name == "top" and prov.kind == "helper"
]
assert "top" in report.owned_cells["top"]
assert "top" in _owned_by(report, "top")
assert len(helpers) == 2
assert all(prov.emitted_via == "tree_merge" for prov in helpers)
assert any(prov.renamed_from == "_helper" for prov in helpers)
@ -64,10 +69,10 @@ def test_build_library_requires_build_session_for_reads_and_freezes_after_build(
with pytest.raises(BuildError, match="write-only"):
_ = builder.cells.leaf
built = builder.build(output="library")
built, report = builder.build(output="library")
assert isinstance(built, BuiltLibrary)
assert built.build_report.requested_roots == ("leaf",)
assert isinstance(built, Library)
assert report.requested_roots == ("leaf",)
with pytest.raises(BuildError, match="frozen"):
builder["later"] = Pattern()
@ -134,6 +139,14 @@ def test_build_library_validate_rejects_removed_output_argument() -> None:
builder.validate(output="library") # type: ignore[call-arg]
def test_build_library_rejects_unknown_build_output_mode() -> None:
builder = BuildLibrary()
builder["leaf"] = Pattern()
with pytest.raises(ValueError, match="Unknown build output mode"):
builder.build(output="bad") # type: ignore[arg-type]
def test_build_library_allows_helper_writes_via_pather() -> None:
builder = BuildLibrary()
builder["leaf"] = Pattern(ports={"a": Port((0, 0), 0)})
@ -147,9 +160,9 @@ def test_build_library_allows_helper_writes_via_pather() -> None:
return top
builder.cells.top = cell(make_top)(builder)
built = builder.build()
_built, report = builder.build()
helper_prov = built.build_report.provenance["_route"]
helper_prov = report.provenance["_route"]
assert helper_prov.kind == "helper"
assert helper_prov.owner_declared_name == "top"
@ -160,11 +173,23 @@ def test_build_library_preserves_source_cells_and_records_source_provenance() ->
builder.add_source(source)
builder.cells.top = cell(lambda: Pattern())()
built = builder.build()
built, report = builder.build()
assert "src" in built
assert built.build_report.provenance["src"].kind == "source"
assert built.build_report.provenance["src"].emitted_via == "source_import"
assert report.provenance["src"].kind == "source"
def test_build_library_rejects_add_source_during_build() -> None:
builder = BuildLibrary()
def make_top(lib: BuildLibrary) -> Pattern:
lib.add_source(Library({"src": Pattern()}))
return Pattern()
builder.cells.top = cell(make_top)(builder)
with pytest.raises(BuildError, match="add_source"):
builder.build()
def test_build_library_can_rename_imported_source_cells_during_authoring() -> None:
@ -178,12 +203,12 @@ def test_build_library_can_rename_imported_source_cells_during_authoring() -> No
builder.add_source(source)
builder.rename("child", "renamed_child")
built = builder.build()
built, report = builder.build()
assert "renamed_child" in built
assert "child" not in built
assert "renamed_child" in built["parent"].refs
assert built.build_report.provenance["renamed_child"].source_name == "child"
assert report.provenance["renamed_child"].source_name == "child"
def test_build_library_rejects_move_references_for_source_rename() -> None:
@ -202,7 +227,7 @@ def test_build_library_rejects_renaming_declared_cells_during_authoring() -> Non
builder.rename("declared", "renamed_declared")
def test_build_library_helper_rename_updates_provenance_and_owned_cells() -> None:
def test_build_library_helper_rename_updates_provenance_owner() -> None:
builder = BuildLibrary()
def make_top(lib: BuildLibrary) -> Pattern:
@ -213,18 +238,17 @@ def test_build_library_helper_rename_updates_provenance_and_owned_cells() -> Non
return top
builder.cells.top = cell(make_top)(builder)
built = builder.build()
report = built.build_report
built, report = builder.build()
assert "final_helper" in built
assert "_helper" not in built
assert "final_helper" in report.owned_cells["top"]
assert "_helper" not in report.owned_cells["top"]
owned = _owned_by(report, "top")
assert "final_helper" in owned
assert "_helper" not in owned
prov = report.provenance["final_helper"]
assert prov.kind == "helper"
assert prov.requested_name == "_helper"
assert prov.renamed_from == "_helper"
assert prov.final_name == "final_helper"
def test_build_library_helper_delete_removes_provenance_and_ownership() -> None:
@ -236,12 +260,11 @@ def test_build_library_helper_delete_removes_provenance_and_ownership() -> None:
return Pattern()
builder.cells.top = cell(make_top)(builder)
built = builder.build()
report = built.build_report
built, report = builder.build()
assert "_helper" not in built
assert "_helper" not in report.provenance
assert report.owned_cells["top"] == ("top",)
assert _owned_by(report, "top") == {"top"}
def test_build_library_helper_rename_after_auto_rename_preserves_requested_name() -> None:
@ -258,8 +281,7 @@ def test_build_library_helper_rename_after_auto_rename_preserves_requested_name(
return top
builder.cells.top = cell(make_top)(builder)
built = builder.build()
report = built.build_report
built, report = builder.build()
assert "final_helper" in built
prov = report.provenance["final_helper"]