[wip] introduce BuildLibrary and make overlay first-class

This commit is contained in:
Jan Petykiewicz 2026-04-22 21:24:05 -07:00
commit 6d494142fe
7 changed files with 1335 additions and 98 deletions

View file

@ -1,9 +1,18 @@
"""
Source-backed lazy GDSII reader using the pure-python klamath path.
Classic source-backed lazy GDSII reader built on the pure-python klamath path.
This module mirrors the lazy Arrow reader's interface closely enough to share
the same overlay and ports-import helpers, while still materializing cells
through the classic `gdsii` decoder.
This module provides the non-Arrow half of Masque's lazy GDS architecture:
- `GdsLibrarySource` scans a GDS stream once to discover library metadata,
struct order, and child edges without materializing every cell.
- cells are materialized on demand through the classic `gdsii` decoder
whenever a caller indexes the lazy view
- the source can be wrapped in `PortsLibraryView` or merged through
`OverlayLibrary`, both of which live in `gdsii_lazy_core`
The public surface intentionally parallels `gdsii_lazy_arrow` closely so that
callers can swap between the classic and Arrow-backed implementations with
minimal changes.
"""
from __future__ import annotations
@ -36,6 +45,7 @@ logger = logging.getLogger(__name__)
@dataclass
class _SourceHandle:
""" Owns the underlying stream and any companion file handle for a source. """
path: pathlib.Path | None
stream: IO[bytes]
handle: IO[bytes] | None = None
@ -49,6 +59,7 @@ class _SourceHandle:
@dataclass(frozen=True)
class _CellScan:
""" Scan-time metadata for one cell in the source stream. """
offset: int
children: set[str]
@ -107,6 +118,10 @@ class GdsLibrarySource(ILibraryView):
Cells are scanned once up front to discover order and child edges, then
materialized one at a time through the classic `gdsii.read_elements` path.
The source owns the stream lifetime, preserves on-disk ordering through
`source_order()`, and answers graph queries from scan metadata whenever
possible so callers can inspect hierarchy without forcing a full load.
"""
def __init__(

View file

@ -1,5 +1,18 @@
"""
Shared helpers for source-backed lazy GDS views.
This module contains the reusable pieces that sit between lazy source readers
and ordinary mutable library usage:
- `PortsLibraryView` layers a processed, ports-importing cache on top of a raw
source view without mutating the source itself
- `OverlayLibrary` exposes a mutable library surface that can mix source-backed
cells with overlay-owned materialized patterns
- the write helpers preserve source-backed copy-through behavior where
possible, falling back to normal pattern serialization when a cell has been
materialized or remapped
Both the classic and Arrow-backed lazy GDS readers rely on these helpers.
"""
from __future__ import annotations
@ -30,6 +43,7 @@ logger = logging.getLogger(__name__)
@dataclass
class _SourceLayer:
""" One imported source layer tracked by an `OverlayLibrary`. """
library: ILibraryView
source_to_visible: dict[str, str]
visible_to_source: dict[str, str]
@ -39,6 +53,7 @@ class _SourceLayer:
@dataclass(frozen=True)
class _SourceEntry:
""" Reference to a single visible source-backed cell in an overlay. """
layer_index: int
source_name: str
@ -73,6 +88,10 @@ class PortsLibraryView(ILibraryView):
The wrapped source remains untouched; this view owns a separate processed
cache so direct-copy workflows can continue to use the raw source view.
Graph queries, source ordering, and copy-through capabilities are delegated
to the wrapped source whenever possible, while `__getitem__` and
`materialize_many()` return port-imported patterns.
"""
def __init__(
@ -231,6 +250,14 @@ class OverlayLibrary(ILibrary):
Source-backed cells remain lazy until accessed through `__getitem__`, at
which point that visible cell is promoted into an overlay-owned materialized
`Pattern`.
This is the main mutable integration surface for lazy GDS content. It lets
callers:
- expose one or more source-backed libraries behind a normal `ILibrary`
interface
- add or replace cells with overlay-owned patterns
- rename visible source cells
- remap references without immediately rewriting untouched source structs
"""
def __init__(self) -> None:
@ -522,6 +549,20 @@ class OverlayLibrary(ILibrary):
return tuple(name for name in self._order if name in self._entries)
class BuiltOverlayLibrary(OverlayLibrary):
"""
Internal overlay output returned by `BuildLibrary.build(output='overlay')`.
The type is intentionally not part of the public API. It exists so build
outputs can carry a `build_report` while still behaving like an
`OverlayLibrary`.
"""
def __init__(self, *, build_report: Any | None = None) -> None:
super().__init__()
self.build_report = build_report
def _iter_library_infos(library: Mapping[str, Pattern] | ILibraryView) -> Iterator[dict[str, Any]]:
info = getattr(library, 'library_info', None)
if isinstance(info, dict):