[library / gdsii] add materialize_detached and do some more cleanup
This commit is contained in:
parent
29947c6c01
commit
93dd3503ca
11 changed files with 930 additions and 23 deletions
|
|
@ -497,6 +497,36 @@ def test_gdsii_lazy_cached_source_cell_disables_only_its_raw_copy(
|
|||
assert set(roundtrip['leaf'].labels) == {(10, 0), (30, 0)}
|
||||
|
||||
|
||||
def test_gdsii_lazy_detached_processing_copies_only_cached_patterns(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
gds_file = tmp_path / 'classic_detached_source.gds'
|
||||
gdsii.writefile(_make_lazy_port_library(), gds_file, meters_per_unit=1e-9)
|
||||
raw, _ = gdsii_lazy.readfile(gds_file)
|
||||
mapped = LayerMappedView(raw, lambda layer: layer)
|
||||
|
||||
original_deepcopy = Pattern.deepcopy
|
||||
copied: list[Pattern] = []
|
||||
|
||||
def count_deepcopy(pattern: Pattern) -> Pattern:
|
||||
copied.append(pattern)
|
||||
return original_deepcopy(pattern)
|
||||
|
||||
monkeypatch.setattr(Pattern, 'deepcopy', count_deepcopy)
|
||||
fresh = mapped.materialize_detached('top')
|
||||
assert not copied
|
||||
assert not raw._cache
|
||||
assert not mapped._cache
|
||||
|
||||
cached = raw['top']
|
||||
copied.clear()
|
||||
detached = mapped.materialize_detached('top')
|
||||
assert copied == [cached]
|
||||
assert detached is not cached
|
||||
assert detached is not fresh
|
||||
|
||||
|
||||
def test_gdsii_lazy_materialized_cell_disables_only_its_raw_copy(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
|
|
|
|||
|
|
@ -193,6 +193,32 @@ def test_gdsii_lazy_arrow_ref_queries_match_eager_reader(tmp_path: Path) -> None
|
|||
assert _global_refs_key(lazy.find_refs_global(name)) == _global_refs_key(eager.find_refs_global(name))
|
||||
|
||||
|
||||
def test_gdsii_lazy_arrow_detached_batch_preserves_native_batching(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
gds_file = tmp_path / 'lazy_arrow_detached_batch.gds'
|
||||
gdsii.writefile(_make_small_library(), gds_file, meters_per_unit=1e-9)
|
||||
raw, _ = gdsii_lazy_arrow.readfile(gds_file)
|
||||
mapped = LayerMappedView(raw, lambda layer: layer)
|
||||
|
||||
original_read = gdsii_arrow._read_selected_cells_to_arrow
|
||||
call_count = 0
|
||||
|
||||
def count_read(*args, **kwargs) -> object:
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return original_read(*args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(gdsii_arrow, '_read_selected_cells_to_arrow', count_read)
|
||||
detached = mapped.materialize_many_detached(('leaf', 'mid', 'leaf'))
|
||||
|
||||
assert tuple(detached) == ('leaf', 'mid')
|
||||
assert call_count == 1
|
||||
assert not raw._cache
|
||||
assert not mapped._cache
|
||||
|
||||
|
||||
def test_gdsii_lazy_arrow_invalid_input_raises_klamath_error(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'invalid.gds'
|
||||
gds_file.write_bytes(b'not-a-gds')
|
||||
|
|
|
|||
|
|
@ -825,6 +825,74 @@ def test_library_materialization_and_borrowing_capabilities() -> None:
|
|||
assert not isinstance(plain_view, IMaterializable | IBorrowing)
|
||||
|
||||
|
||||
def test_detached_materialization_default_is_owned_and_deduplicated() -> None:
|
||||
shared_a = Pattern()
|
||||
shared_b = Pattern()
|
||||
lazy = LazyLibrary()
|
||||
lazy['a'] = lambda: shared_a
|
||||
lazy['b'] = lambda: shared_b
|
||||
|
||||
detached = lazy.materialize_many_detached(('b', 'a', 'b'))
|
||||
|
||||
assert tuple(detached) == ('b', 'a')
|
||||
assert detached['a'] is not shared_a
|
||||
assert detached['b'] is not shared_b
|
||||
detached['a'].polygon('L', vertices=[[0, 0], [1, 0], [0, 1]])
|
||||
assert not shared_a.shapes
|
||||
assert not lazy.cache
|
||||
|
||||
|
||||
def test_nested_detached_views_copy_plain_source_once(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
source_pattern = Pattern()
|
||||
source_pattern.polygon('A', vertices=[[0, 0], [1, 0], [0, 1]])
|
||||
source = Library({'top': source_pattern})
|
||||
ports = PortLoadView(source, ports={'top': {'P': Port((1, 2), 0)}})
|
||||
mapped = LayerMappedView(ports, lambda _layer: 'B')
|
||||
overlay = OverlayLibrary()
|
||||
overlay.add_source(mapped)
|
||||
|
||||
original_deepcopy = Pattern.deepcopy
|
||||
copied: list[Pattern] = []
|
||||
|
||||
def count_deepcopy(pattern: Pattern) -> Pattern:
|
||||
copied.append(pattern)
|
||||
return original_deepcopy(pattern)
|
||||
|
||||
monkeypatch.setattr(Pattern, 'deepcopy', count_deepcopy)
|
||||
detached = overlay.materialize_detached('top')
|
||||
|
||||
assert copied == [source_pattern]
|
||||
assert set(detached.shapes) == {'B'}
|
||||
assert set(detached.ports) == {'P'}
|
||||
assert not source_pattern.ports
|
||||
assert not ports._cache
|
||||
assert not mapped._cache
|
||||
assert overlay.source_cell('top') == (mapped, 'top')
|
||||
|
||||
|
||||
def test_nested_detached_views_copy_cached_pattern_once(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
source_pattern = Pattern()
|
||||
source = Library({'top': source_pattern})
|
||||
ports = PortLoadView(source, ports={'top': {'P': Port((1, 2), 0)}})
|
||||
cached = ports['top']
|
||||
mapped = LayerMappedView(ports, lambda layer: layer)
|
||||
|
||||
original_deepcopy = Pattern.deepcopy
|
||||
copied: list[Pattern] = []
|
||||
|
||||
def count_deepcopy(pattern: Pattern) -> Pattern:
|
||||
copied.append(pattern)
|
||||
return original_deepcopy(pattern)
|
||||
|
||||
monkeypatch.setattr(Pattern, 'deepcopy', count_deepcopy)
|
||||
detached = mapped.materialize_detached('top')
|
||||
|
||||
assert copied == [cached]
|
||||
assert detached is not cached
|
||||
detached.ports.clear()
|
||||
assert set(cached.ports) == {'P'}
|
||||
|
||||
|
||||
def test_borrowed_source_cell_tracks_persistent_materialization() -> None:
|
||||
source = Library({"top": Pattern()})
|
||||
source.library_info = {"name": "not-forwarded"} # type: ignore[attr-defined]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue