[OverlayLibrary] enable renaming all cells during add_source with rename_when='always'
This commit is contained in:
parent
3dea61b05e
commit
08bbb10827
2 changed files with 58 additions and 4 deletions
|
|
@ -17,7 +17,7 @@ Both the classic and Arrow-backed lazy GDS readers rely on these helpers.
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import IO, Any, cast
|
||||
from typing import IO, Any, Literal, cast
|
||||
from collections import defaultdict
|
||||
from collections.abc import Callable, Iterator, Mapping, Sequence
|
||||
import copy
|
||||
|
|
@ -303,7 +303,23 @@ class OverlayLibrary(ILibrary):
|
|||
source: Mapping[str, Pattern] | ILibraryView,
|
||||
*,
|
||||
rename_theirs: Callable[[ILibraryView, str], str] | None = None,
|
||||
rename_when: Literal['conflict', 'always'] = 'conflict',
|
||||
) -> dict[str, str]:
|
||||
"""
|
||||
Add a source-backed library layer.
|
||||
|
||||
Args:
|
||||
rename_theirs: Function used to choose visible names for imported
|
||||
source cells.
|
||||
rename_when: If `'conflict'`, only conflicting names are renamed.
|
||||
If `'always'`, every imported source name is passed through
|
||||
`rename_theirs`.
|
||||
"""
|
||||
if rename_when not in ('conflict', 'always'):
|
||||
raise ValueError(f'Unknown source rename mode: {rename_when!r}')
|
||||
if rename_when == 'always' and rename_theirs is None:
|
||||
raise TypeError('rename_theirs is required when rename_when="always"')
|
||||
|
||||
view = _coerce_library_view(source)
|
||||
source_order = list(view.source_order())
|
||||
child_graph = view.child_graph(dangling='include')
|
||||
|
|
@ -314,12 +330,20 @@ class OverlayLibrary(ILibrary):
|
|||
|
||||
for name in source_order:
|
||||
visible = name
|
||||
if visible in self._entries or visible in visible_to_source:
|
||||
renamed = False
|
||||
if rename_when == 'always':
|
||||
visible = cast('Callable[[ILibraryView, str], str]', rename_theirs)(self, name)
|
||||
renamed = True
|
||||
elif visible in self._entries or visible in visible_to_source:
|
||||
if rename_theirs is None:
|
||||
raise LibraryError(f'Conflicting name while adding source: {name!r}')
|
||||
visible = rename_theirs(self, name)
|
||||
renamed = True
|
||||
if visible in self._entries or visible in visible_to_source:
|
||||
if not renamed:
|
||||
raise LibraryError(f'Conflicting name while adding source: {name!r}')
|
||||
raise LibraryError(f'Unresolved duplicate key encountered while adding source: {name!r} -> {visible!r}')
|
||||
if visible != name:
|
||||
rename_map[name] = visible
|
||||
source_to_visible[name] = visible
|
||||
visible_to_source[visible] = name
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from pathlib import Path
|
||||
|
||||
import numpy
|
||||
import pytest
|
||||
from numpy.testing import assert_allclose
|
||||
|
||||
from ..file import gdsii, gdsii_lazy
|
||||
|
|
@ -82,6 +83,35 @@ def test_gdsii_lazy_overlay_add_source_stays_lazy_for_processed_view(tmp_path: P
|
|||
assert set(abstract.ports) == {'A'}
|
||||
|
||||
|
||||
def test_gdsii_lazy_overlay_add_source_can_rename_every_source_cell() -> None:
|
||||
src = _make_lazy_port_library()
|
||||
overlay = gdsii_lazy.OverlayLibrary()
|
||||
|
||||
rename_map = overlay.add_source(
|
||||
src,
|
||||
rename_theirs=lambda _lib, name: f'mapped_{name}',
|
||||
rename_when='always',
|
||||
)
|
||||
|
||||
assert rename_map == {
|
||||
'leaf': 'mapped_leaf',
|
||||
'child': 'mapped_child',
|
||||
'top': 'mapped_top',
|
||||
}
|
||||
assert tuple(overlay.keys()) == ('mapped_leaf', 'mapped_child', 'mapped_top')
|
||||
assert 'mapped_leaf' in overlay['mapped_child'].refs
|
||||
|
||||
|
||||
def test_gdsii_lazy_overlay_add_source_rename_when_validation() -> None:
|
||||
src = _make_lazy_port_library()
|
||||
|
||||
with pytest.raises(TypeError, match='rename_theirs'):
|
||||
gdsii_lazy.OverlayLibrary().add_source(src, rename_when='always')
|
||||
|
||||
with pytest.raises(ValueError, match='rename mode'):
|
||||
gdsii_lazy.OverlayLibrary().add_source(src, rename_when='sometimes') # type: ignore[arg-type]
|
||||
|
||||
|
||||
def test_gdsii_lazy_processed_write_roundtrips_without_explicit_units(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'lazy_roundtrip.gds'
|
||||
src = _make_lazy_port_library()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue