[gdsii] cleanup

This commit is contained in:
Jan Petykiewicz 2026-07-14 21:24:34 -07:00
commit 29947c6c01
14 changed files with 153 additions and 901 deletions

View file

@ -78,3 +78,8 @@ def test_gdsii_check_valid_names_validates_generator_lengths() -> None:
with pytest.raises(LibraryError, match="invalid names"):
gdsii.check_valid_names(names)
def test_gdsii_does_not_export_codec_helpers() -> None:
assert not hasattr(gdsii, 'read_elements')
assert not hasattr(gdsii, 'rint_cast')

View file

@ -16,7 +16,7 @@ from ..repetition import Grid
from ..shapes import Path as MPath, Polygon, PolyCollection, RectCollection
from ..file import gdsii
from ..file.gdsii import arrow as gdsii_arrow
from ..file.gdsii.perf import write_fixture
from tools.generate_gds_perf import write_fixture
if not gdsii_arrow.is_available():

View file

@ -8,7 +8,7 @@ from numpy.testing import assert_allclose
from ..file import gdsii
from ..file.gdsii import lazy as gdsii_lazy
from ..file.gdsii import lazy_write as gdsii_lazy_write
from ..file.gdsii import writer as gdsii_writer
from ..file.utils import preflight_source_aware
from ..error import LibraryError
from ..pattern import Pattern
@ -37,29 +37,25 @@ def _make_lazy_port_library() -> Library:
return lib
def test_gdsii_lazy_write_ignores_non_mapping_library_info() -> None:
def test_gdsii_write_requires_units_without_gds_metadata() -> None:
lib = Library({'top': Pattern()})
lib.library_info = None # type: ignore[attr-defined]
with pytest.raises(LibraryError, match='required for non-GDS-backed lazy writes'):
gdsii_lazy.write(lib, io.BytesIO())
with pytest.raises(LibraryError, match='meters_per_unit is required'):
gdsii.write(lib, io.BytesIO())
def test_gdsii_lazy_write_plain_library_matches_eager_writer() -> None:
def test_gdsii_write_plain_library_defaults() -> None:
lib = _make_lazy_port_library()
eager_stream = io.BytesIO()
lazy_stream = io.BytesIO()
gdsii.write(lib, eager_stream, meters_per_unit=1e-9, library_name='writer-match')
gdsii_lazy.write(
lib,
lazy_stream,
meters_per_unit=1e-9,
logical_units_per_unit=1,
library_name='writer-match',
)
assert lazy_stream.getvalue() == eager_stream.getvalue()
stream = io.BytesIO()
gdsii.write(lib, stream, 1e-9)
stream.seek(0)
_roundtrip, info = gdsii.read(stream)
assert info == {
'name': 'masque-klamath',
'meters_per_unit': 1e-9,
'logical_units_per_unit': 1,
}
def test_gdsii_lazy_write_materializes_transiently() -> None:
@ -67,7 +63,7 @@ def test_gdsii_lazy_write_materializes_transiently() -> None:
lib['top'] = Pattern()
stream = io.BytesIO()
gdsii_lazy.write(
gdsii.write(
lib,
stream,
meters_per_unit=1e-9,
@ -92,7 +88,7 @@ def test_gdsii_raw_copy_provenance_cycle_falls_back() -> None:
view = SelfBorrowingView({'top': Pattern()})
assert gdsii_lazy_write._resolve_raw_struct(view, 'top') is None
assert gdsii_writer._resolve_raw_struct(view, 'top') is None
def test_gdsii_lazy_source_exposes_order_and_graph_without_materializing(tmp_path: Path) -> None:
@ -158,7 +154,7 @@ def test_gdsii_lazy_subtree_stays_borrowed_and_preserves_write_metadata(tmp_path
assert not raw._cache
out_file = tmp_path / 'lazy_subtree_out.gds'
gdsii_lazy.writefile(subtree, out_file)
gdsii.writefile(subtree, out_file)
assert not raw._cache
roundtrip, info = gdsii.readfile(out_file)
@ -180,7 +176,7 @@ def test_gdsii_lazy_borrowed_sources_require_matching_units(tmp_path: Path) -> N
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())
gdsii.write(overlay, io.BytesIO())
def test_gdsii_lazy_overlay_subtree_preserves_source_laziness(tmp_path: Path) -> None:
@ -198,7 +194,7 @@ def test_gdsii_lazy_overlay_subtree_preserves_source_laziness(tmp_path: Path) ->
assert subtree.borrowed_sources() == (raw,)
out_file = tmp_path / 'lazy_overlay_subtree_out.gds'
gdsii_lazy.writefile(subtree, out_file)
gdsii.writefile(subtree, out_file)
assert not raw._cache
roundtrip, info = gdsii.readfile(out_file)
@ -401,7 +397,7 @@ def test_gdsii_lazy_processed_write_roundtrips_without_explicit_units(tmp_path:
processed = PortLoadView(raw, layers=[(10, 0)], max_depth=2)
out_file = tmp_path / 'lazy_roundtrip_out.gds'
gdsii_lazy.writefile(processed, out_file)
gdsii.writefile(processed, out_file)
assert out_file.read_bytes() == gds_file.read_bytes()
@ -431,7 +427,7 @@ def test_gdsii_lazy_source_aware_write_copies_untouched_structures(
monkeypatch.setattr(raw, 'raw_struct_bytes', record_raw_read)
monkeypatch.setattr(raw, 'materialize', fail_materialize)
out_file = tmp_path / 'classic_copy_out.gds'
gdsii_lazy.writefile(prepared, out_file)
gdsii.writefile(prepared, out_file)
assert copied == ['leaf', 'child', 'top']
assert not raw._cache
@ -448,7 +444,7 @@ def test_gdsii_lazy_raw_copy_stream_backends(tmp_path: Path, use_mmap: bool) ->
raw, _ = gdsii_lazy.readfile(gds_file, use_mmap=use_mmap)
out_file = tmp_path / f'classic_stream_{use_mmap}.gds'
gdsii_lazy.writefile(raw, out_file)
gdsii.writefile(raw, out_file)
assert not raw._cache
assert out_file.read_bytes() == gds_file.read_bytes()
@ -467,7 +463,7 @@ def test_gdsii_lazy_raw_copy_gzipped_source(tmp_path: Path) -> None:
raw.raw_struct_bytes(name)
assert raw._source.stream.tell() == raw._cells[name].struct_end
out_file = tmp_path / 'classic_gzip_out.gds'
gdsii_lazy.writefile(raw, out_file)
gdsii.writefile(raw, out_file)
assert not raw._cache
assert out_file.read_bytes() == gds_file.read_bytes()
@ -494,7 +490,7 @@ def test_gdsii_lazy_cached_source_cell_disables_only_its_raw_copy(
monkeypatch.setattr(raw, 'raw_struct_bytes', record_raw_read)
out_file = tmp_path / 'classic_cached_out.gds'
gdsii_lazy.writefile(raw, out_file)
gdsii.writefile(raw, out_file)
assert copied == ['child', 'top']
roundtrip, _ = gdsii.readfile(out_file)
@ -522,7 +518,7 @@ def test_gdsii_lazy_materialized_cell_disables_only_its_raw_copy(
monkeypatch.setattr(raw, 'raw_struct_bytes', record_raw_read)
out_file = tmp_path / 'classic_partial_copy_out.gds'
gdsii_lazy.writefile(prepared, out_file)
gdsii.writefile(prepared, out_file)
assert copied == ['child', 'top']
assert not raw._cache
@ -538,7 +534,7 @@ def test_gdsii_lazy_layer_mapped_write_materializes_without_source_cache(tmp_pat
raw, _ = gdsii_lazy.readfile(gds_file)
mapped = LayerMappedView(raw, lambda layer: (20, 0) if layer == (10, 0) else layer)
out_file = tmp_path / 'lazy_layer_mapped.gds'
gdsii_lazy.writefile(mapped, out_file)
gdsii.writefile(mapped, out_file)
assert not raw._cache
roundtrip, info = gdsii.readfile(out_file)
@ -550,3 +546,5 @@ def test_gdsii_lazy_layer_mapped_write_materializes_without_source_cache(tmp_pat
def test_gdsii_removed_closure_based_lazy_loader() -> None:
assert not hasattr(gdsii, 'load_library')
assert not hasattr(gdsii, 'load_libraryfile')
assert not hasattr(gdsii_lazy, 'write')
assert not hasattr(gdsii_lazy, 'writefile')

View file

@ -16,14 +16,21 @@ from ..repetition import Grid
from ..file import gdsii
from ..file.utils import preflight_source_aware
from ..file.gdsii import lazy_arrow as gdsii_lazy_arrow
from ..file.gdsii import lazy_write as gdsii_lazy_write
from ..file.gdsii.perf import write_fixture
from ..file.gdsii import arrow as gdsii_arrow
from ..file.gdsii import writer as gdsii_writer
from tools.generate_gds_perf import write_fixture
if not gdsii_lazy_arrow.is_available():
if not gdsii_arrow.is_available():
pytest.skip('klamath_rs_ext shared library is not available', allow_module_level=True)
def test_gdsii_lazy_arrow_has_reader_only_surface() -> None:
assert not hasattr(gdsii_lazy_arrow, 'is_available')
assert not hasattr(gdsii_lazy_arrow, 'write')
assert not hasattr(gdsii_lazy_arrow, 'writefile')
def _make_small_library() -> Library:
lib = Library()
@ -225,7 +232,7 @@ def test_gdsii_lazy_arrow_untouched_write_is_copy_through(tmp_path: Path) -> Non
lib, info = gdsii_lazy_arrow.readfile(gds_file)
out_file = tmp_path / 'copy_out.gds'
gdsii_lazy_arrow.writefile(
gdsii.writefile(
lib,
out_file,
meters_per_unit=info['meters_per_unit'],
@ -255,7 +262,7 @@ def test_gdsii_raw_copy_resolves_generic_borrowing_views(tmp_path: Path, monkeyp
monkeypatch.setattr(raw, 'raw_struct_bytes', record_raw_read)
out_file = tmp_path / 'provenance_out.gds'
gdsii_lazy_arrow.writefile(overlay, out_file)
gdsii.writefile(overlay, out_file)
assert copied == ['leaf', 'mid', 'top']
assert out_file.read_bytes() == gds_file.read_bytes()
@ -263,12 +270,12 @@ def test_gdsii_raw_copy_resolves_generic_borrowing_views(tmp_path: Path, monkeyp
renamed = OverlayLibrary()
renamed.add_source(raw)
renamed.rename('top', 'renamed_top')
assert gdsii_lazy_write._resolve_raw_struct(renamed, 'renamed_top') is None
assert gdsii_writer._resolve_raw_struct(renamed, 'renamed_top') is None
remapped = OverlayLibrary()
remapped.add_source(raw)
remapped.rename('leaf', 'renamed_leaf', move_references=True)
assert gdsii_lazy_write._resolve_raw_struct(remapped, 'mid') is None
assert gdsii_writer._resolve_raw_struct(remapped, 'mid') is None
def test_gdsii_layer_mapped_view_controls_raw_copy_through(
@ -293,7 +300,7 @@ def test_gdsii_layer_mapped_view_controls_raw_copy_through(
mapped = LayerMappedView(raw, map_layer)
mapped_file = tmp_path / 'layer_mapped_all.gds'
gdsii_lazy_arrow.writefile(mapped, mapped_file)
gdsii.writefile(mapped, mapped_file)
assert copied == []
assert not raw._cache
@ -305,7 +312,7 @@ def test_gdsii_layer_mapped_view_controls_raw_copy_through(
preflighted = preflight_source_aware(passthrough)
assert isinstance(preflighted, OverlayLibrary)
copied_file = tmp_path / 'layer_mapped_copied.gds'
gdsii_lazy_arrow.writefile(preflighted, copied_file)
gdsii.writefile(preflighted, copied_file)
assert copied == ['leaf', 'mid', 'top']
assert copied_file.read_bytes() == gds_file.read_bytes()
@ -315,7 +322,7 @@ def test_gdsii_layer_mapped_view_controls_raw_copy_through(
assert set(passthrough['leaf'].shapes) == {(20, 0)}
preflighted = preflight_source_aware(passthrough)
materialized_file = tmp_path / 'layer_mapped_materialized.gds'
gdsii_lazy_arrow.writefile(preflighted, materialized_file)
gdsii.writefile(preflighted, materialized_file)
assert copied == ['mid', 'top']
assert not raw._cache
@ -345,7 +352,7 @@ def test_gdsii_lazy_arrow_processed_cell_edit_disables_raw_copy(
monkeypatch.setattr(raw, 'raw_struct_bytes', record_raw_read)
out_file = tmp_path / 'processed_edit_out.gds'
gdsii_lazy_arrow.writefile(processed, out_file)
gdsii.writefile(processed, out_file)
assert 'top' not in copied
roundtrip, _ = gdsii.readfile(out_file)
@ -370,7 +377,7 @@ def test_gdsii_lazy_arrow_subtree_preserves_raw_copy_and_ref_queries(tmp_path: P
assert not raw._cache
out_file = tmp_path / 'subtree_copy_out.gds'
gdsii_lazy_arrow.writefile(subtree, out_file)
gdsii.writefile(subtree, out_file)
assert not raw._cache
roundtrip, info = gdsii.readfile(out_file)
@ -394,7 +401,7 @@ def test_gdsii_lazy_arrow_overlay_subtree_preserves_raw_copy(tmp_path: Path) ->
assert not raw._cache
out_file = tmp_path / 'overlay_subtree_out.gds'
gdsii_lazy_arrow.writefile(subtree, out_file)
gdsii.writefile(subtree, out_file)
assert not raw._cache
roundtrip, info = gdsii.readfile(out_file)
@ -409,7 +416,7 @@ def test_gdsii_lazy_arrow_gzipped_copy_through(tmp_path: Path) -> None:
lib, info = gdsii_lazy_arrow.readfile(gds_file)
out_file = tmp_path / 'copy_out.gds.gz'
gdsii_lazy_arrow.writefile(
gdsii.writefile(
lib,
out_file,
meters_per_unit=info['meters_per_unit'],
@ -458,7 +465,7 @@ def test_gdsii_lazy_overlay_merge_and_write(tmp_path: Path) -> None:
overlay.move_references('leaf', renamed_leaf)
out_file = tmp_path / 'overlay_out.gds'
gdsii_lazy_arrow.writefile(overlay, out_file)
gdsii.writefile(overlay, out_file)
roundtrip, _ = gdsii.readfile(out_file)
assert set(roundtrip.keys()) == {'leaf', renamed_leaf, 'top_a', 'top_b'}

View file

@ -3,7 +3,7 @@ import json
from pathlib import Path
from ..file import gdsii
from ..file.gdsii.perf import fixture_manifest, write_fixture
from tools.generate_gds_perf import fixture_manifest, write_fixture
def test_gdsii_perf_fixture_smoke(tmp_path: Path) -> None: