[library / gdsii] more cleanup
This commit is contained in:
parent
7b589e4f44
commit
e7f7cae8b9
4 changed files with 40 additions and 1 deletions
|
|
@ -47,5 +47,9 @@ class IBorrowing(ABC):
|
||||||
|
|
||||||
The source may use a different name, which is returned alongside it.
|
The source may use a different name, which is returned alongside it.
|
||||||
Port metadata may differ because ports are not layout-file content.
|
Port metadata may differ because ports are not layout-file content.
|
||||||
|
The result is not recursively resolved: consumers must follow further
|
||||||
|
borrowing views themselves and enforce format-specific constraints such
|
||||||
|
as whether the visible and source names must match. `None` means the
|
||||||
|
source cannot be reused safely or no source provenance is available.
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ class _SubtreeLibraryView(ILibraryView, IMaterializable, IBorrowing):
|
||||||
name: set(child_graph.get(name, set()))
|
name: set(child_graph.get(name, set()))
|
||||||
for name in self._order
|
for name in self._order
|
||||||
}
|
}
|
||||||
|
|
||||||
def __getitem__(self, key: str) -> Pattern:
|
def __getitem__(self, key: str) -> Pattern:
|
||||||
if key not in self._names:
|
if key not in self._names:
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
|
|
@ -136,6 +137,7 @@ class _SubtreeLibraryView(ILibraryView, IMaterializable, IBorrowing):
|
||||||
refs = self._source.find_refs_local(name, parent_graph=parent_graph, dangling=dangling)
|
refs = self._source.find_refs_local(name, parent_graph=parent_graph, dangling=dangling)
|
||||||
return {parent: transforms for parent, transforms in refs.items() if parent in self._names}
|
return {parent: transforms for parent, transforms in refs.items() if parent in self._names}
|
||||||
|
|
||||||
|
|
||||||
class Library(ILibrary):
|
class Library(ILibrary):
|
||||||
"""
|
"""
|
||||||
Default implementation for a writeable library.
|
Default implementation for a writeable library.
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ class PortsLibraryView(ILibraryView, IMaterializable, IBorrowing):
|
||||||
self._replace = replace
|
self._replace = replace
|
||||||
self._cache: dict[str, Pattern] = {}
|
self._cache: dict[str, Pattern] = {}
|
||||||
self._lookups_in_progress: list[str] = []
|
self._lookups_in_progress: list[str] = []
|
||||||
|
|
||||||
def __getitem__(self, key: str) -> Pattern:
|
def __getitem__(self, key: str) -> Pattern:
|
||||||
return self.materialize(key, persist=True)
|
return self.materialize(key, persist=True)
|
||||||
|
|
||||||
|
|
@ -160,6 +161,7 @@ class PortsLibraryView(ILibraryView, IMaterializable, IBorrowing):
|
||||||
return cast('dict[str, list[NDArray[numpy.float64]]]', finder(name, parent_graph=parent_graph, dangling=dangling))
|
return cast('dict[str, list[NDArray[numpy.float64]]]', finder(name, parent_graph=parent_graph, dangling=dangling))
|
||||||
return super().find_refs_local(name, parent_graph=parent_graph, dangling=dangling)
|
return super().find_refs_local(name, parent_graph=parent_graph, dangling=dangling)
|
||||||
|
|
||||||
|
|
||||||
class OverlayLibrary(ILibrary, IMaterializable, IBorrowing):
|
class OverlayLibrary(ILibrary, IMaterializable, IBorrowing):
|
||||||
"""
|
"""
|
||||||
Mutable overlay over one or more source libraries.
|
Mutable overlay over one or more source libraries.
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ from numpy.testing import assert_allclose
|
||||||
|
|
||||||
from ..file import gdsii
|
from ..file import gdsii
|
||||||
from ..file.gdsii import lazy as gdsii_lazy
|
from ..file.gdsii import lazy as gdsii_lazy
|
||||||
|
from ..file.gdsii import lazy_write as gdsii_lazy_write
|
||||||
from ..error import LibraryError
|
from ..error import LibraryError
|
||||||
from ..pattern import Pattern
|
from ..pattern import Pattern
|
||||||
from ..ports import Port
|
from ..ports import Port
|
||||||
from ..library import IBorrowing, IMaterializable, LazyLibrary, Library, OverlayLibrary, PortsLibraryView
|
from ..library import IBorrowing, IMaterializable, LazyLibrary, Library, LibraryView, OverlayLibrary, PortsLibraryView
|
||||||
|
|
||||||
|
|
||||||
def _make_lazy_port_library() -> Library:
|
def _make_lazy_port_library() -> Library:
|
||||||
|
|
@ -76,6 +77,19 @@ def test_gdsii_lazy_write_materializes_transiently() -> None:
|
||||||
assert info['name'] == 'transient'
|
assert info['name'] == 'transient'
|
||||||
|
|
||||||
|
|
||||||
|
def test_gdsii_raw_copy_provenance_cycle_falls_back() -> None:
|
||||||
|
class SelfBorrowingView(LibraryView, IBorrowing):
|
||||||
|
def borrowed_sources(self) -> tuple['SelfBorrowingView', ...]:
|
||||||
|
return (self,)
|
||||||
|
|
||||||
|
def source_cell(self, name: str) -> tuple['SelfBorrowingView', str] | None:
|
||||||
|
return self, name
|
||||||
|
|
||||||
|
view = SelfBorrowingView({'top': Pattern()})
|
||||||
|
|
||||||
|
assert gdsii_lazy_write._resolve_raw_struct(view, 'top') is None
|
||||||
|
|
||||||
|
|
||||||
def test_gdsii_lazy_source_exposes_order_and_graph_without_materializing(tmp_path: Path) -> None:
|
def test_gdsii_lazy_source_exposes_order_and_graph_without_materializing(tmp_path: Path) -> None:
|
||||||
gds_file = tmp_path / 'lazy_source.gds'
|
gds_file = tmp_path / 'lazy_source.gds'
|
||||||
src = _make_lazy_port_library()
|
src = _make_lazy_port_library()
|
||||||
|
|
@ -147,6 +161,23 @@ def test_gdsii_lazy_subtree_stays_borrowed_and_preserves_write_metadata(tmp_path
|
||||||
assert set(roundtrip) == {'leaf', 'child', 'top'}
|
assert set(roundtrip) == {'leaf', 'child', 'top'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_gdsii_lazy_borrowed_sources_require_matching_units(tmp_path: Path) -> None:
|
||||||
|
gds_a = tmp_path / 'units_a.gds'
|
||||||
|
gds_b = tmp_path / 'units_b.gds'
|
||||||
|
source = Library({'top': Pattern()})
|
||||||
|
gdsii.writefile(source, gds_a, meters_per_unit=1e-9, library_name='units-a')
|
||||||
|
gdsii.writefile(source, gds_b, meters_per_unit=2e-9, library_name='units-b')
|
||||||
|
|
||||||
|
lazy_a, _ = gdsii_lazy.readfile(gds_a)
|
||||||
|
lazy_b, _ = gdsii_lazy.readfile(gds_b)
|
||||||
|
overlay = OverlayLibrary()
|
||||||
|
overlay.add_source(lazy_a)
|
||||||
|
overlay.add_source(lazy_b, rename_theirs=lambda lib, name: lib.get_name(name))
|
||||||
|
|
||||||
|
with pytest.raises(LibraryError, match='identical units'):
|
||||||
|
gdsii_lazy.write(overlay, io.BytesIO())
|
||||||
|
|
||||||
|
|
||||||
def test_gdsii_lazy_overlay_subtree_preserves_source_laziness(tmp_path: Path) -> None:
|
def test_gdsii_lazy_overlay_subtree_preserves_source_laziness(tmp_path: Path) -> None:
|
||||||
gds_file = tmp_path / 'lazy_overlay_subtree_source.gds'
|
gds_file = tmp_path / 'lazy_overlay_subtree_source.gds'
|
||||||
src = _make_lazy_port_library()
|
src = _make_lazy_port_library()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue