redo library class naming

This commit is contained in:
jan 2023-04-07 18:08:42 -07:00
parent c7505a12b0
commit 9c9d3c3928
13 changed files with 78 additions and 78 deletions

View File

@ -7,7 +7,7 @@ from skimage.measure import find_contours
from matplotlib import pyplot
import numpy
from masque import Pattern, Library, Polygon
from masque import Pattern, Polygon
from masque.file.gdsii import writefile
#

View File

@ -5,14 +5,14 @@ import numpy
from numpy import pi
import masque
from masque import Pattern, Ref, Arc, WrapLibrary
from masque import Pattern, Ref, Arc, Library
from masque.repetition import Grid
from masque.file import gdsii, dxf, oasis
def main():
lib = WrapLibrary()
lib = Library()
cell_name = 'ellip_grating'
pat = masque.Pattern()
@ -115,7 +115,7 @@ def main():
print(f'Read back and rewrite to {dxf2}')
dxf_lib, _info = dxf.readfile(dxf1)
print(WrapLibrary(dxf_lib))
print(Library(dxf_lib))
dxf.writefile(dxf_lib, 'Model', dxf2)
layer_map = {'base': (0,0), 'mylabel': (1,2)}

View File

@ -6,7 +6,7 @@ from numpy import pi
from masque import (
layer_t, Pattern, Ref, Label, Builder, Port, Polygon,
WrapLibrary, Library,
Library, ILibraryView,
)
from masque.utils import ports2data
from masque.file.gdsii import writefile, check_valid_names
@ -247,7 +247,7 @@ def main(interactive: bool = True) -> None:
devices['l3cav'] = perturbed_l3(lattice_constant=a, hole='smile', hole_lib=shape_lib, xy_size=(4, 10)) # uses smile :)
# Turn our dict of devices into a Library -- useful for getting abstracts
lib = WrapLibrary(devices)
lib = Library(devices)
abv = lib.abstract_view() # lets us use abv[cell] instead of lib.abstract(cell)
#

View File

@ -4,7 +4,7 @@ from pprint import pformat
import numpy
from numpy import pi
from masque import Pattern, Builder, WrapLibrary, LazyLibrary, Library
from masque import Pattern, Builder, LazyLibrary
from masque.file.gdsii import writefile, load_libraryfile
import pcgen

View File

@ -35,8 +35,8 @@ from .ref import Ref
from .pattern import Pattern
from .library import (
Library, MutableLibrary,
WrapROLibrary, WrapLibrary, LazyLibrary,
ILibraryView, ILibrary,
LibraryView, Library, LazyLibrary,
AbstractView,
Tree,
)

View File

@ -11,7 +11,7 @@ from .utils import rotation_matrix_2d, normalize_mirror
#if TYPE_CHECKING:
# from .builder import Builder, Tool
# from .library import MutableLibrary
# from .library import ILibrary
logger = logging.getLogger(__name__)
@ -44,7 +44,7 @@ class Abstract(PortList):
# def build(
# self,
# library: 'MutableLibrary',
# library: 'ILibrary',
# tools: 'None | Tool | MutableMapping[str | None, Tool]' = None,
# ) -> 'Builder':
# """

View File

@ -8,7 +8,7 @@ from numpy.typing import ArrayLike
from ..pattern import Pattern
from ..ref import Ref
from ..library import MutableLibrary
from ..library import ILibrary
from ..error import PortError, BuildError
from ..ports import PortList, Port
from ..abstract import Abstract
@ -79,7 +79,7 @@ class Builder(PortList):
pattern: Pattern
""" Layout of this device """
library: MutableLibrary | None
library: ILibrary | None
"""
Library from which existing patterns should be referenced, and to which
new ones should be added
@ -98,7 +98,7 @@ class Builder(PortList):
def __init__(
self,
library: MutableLibrary | None = None,
library: ILibrary | None = None,
*,
pattern: Pattern | None = None,
ports: str | Mapping[str, Port] | None = None,
@ -140,7 +140,7 @@ class Builder(PortList):
cls,
source: PortList | Mapping[str, Port] | str,
*,
library: MutableLibrary | None = None,
library: ILibrary | None = None,
in_prefix: str = 'in_',
out_prefix: str = '',
port_map: dict[str, str] | Sequence[str] | None = None,
@ -194,7 +194,7 @@ class Builder(PortList):
names.
"""
if library is None:
if hasattr(source, 'library') and isinstance(source.library, MutableLibrary):
if hasattr(source, 'library') and isinstance(source.library, ILibrary):
library = source.library
if isinstance(source, str):
@ -541,7 +541,7 @@ class Pather(Builder):
"""
__slots__ = ('tools',)
library: MutableLibrary
library: ILibrary
"""
Library from which existing patterns should be referenced, and to which
new ones should be added
@ -555,7 +555,7 @@ class Pather(Builder):
def __init__(
self,
library: MutableLibrary,
library: ILibrary,
*,
pattern: Pattern | None = None,
ports: str | Mapping[str, Port] | None = None,
@ -599,7 +599,7 @@ class Pather(Builder):
@classmethod
def mk(
cls,
library: MutableLibrary,
library: ILibrary,
name: str,
*,
ports: str | Mapping[str, Port] | None = None,
@ -614,7 +614,7 @@ class Pather(Builder):
cls,
builder: Builder,
*,
library: MutableLibrary | None = None,
library: ILibrary | None = None,
tools: Tool | MutableMapping[str | None, Tool] | None = None,
) -> 'Pather':
"""TODO from_builder docs"""
@ -629,7 +629,7 @@ class Pather(Builder):
cls,
source: PortList | Mapping[str, Port] | str,
*,
library: MutableLibrary | None = None,
library: ILibrary | None = None,
tools: Tool | MutableMapping[str | None, Tool] | None = None,
in_prefix: str = 'in_',
out_prefix: str = '',
@ -640,7 +640,7 @@ class Pather(Builder):
TODO doc pather.interface
"""
if library is None:
if hasattr(source, 'library') and isinstance(source.library, MutableLibrary):
if hasattr(source, 'library') and isinstance(source.library, ILibrary):
library = source.library
else:
raise BuildError('No library provided (and not present in `source.library`')

View File

@ -105,8 +105,8 @@ class FlatBuilder(PortList):
Args:
source: A collection of ports (e.g. Pattern, Builder, or dict)
from which to create the interface.
library: Used for buildin functions; if not passed and the source
library: Library from which existing patterns should be referenced,
library: Used for buildin functions; if not passed and the source TODO
library: Library from which existing patterns should be referenced, TODO
and to which new ones should be added. If not provided,
the source's library will be used (if available).
tools: Tool objects are used to dynamically generate new single-use

View File

@ -18,7 +18,7 @@ from ezdxf.enums import TextEntityAlignment
from .utils import is_gzipped, tmpfile
from .. import Pattern, Ref, PatternError, Label
from ..library import Library, WrapROLibrary, WrapLibrary
from ..library import ILibraryView, LibraryView, Library
from ..shapes import Shape, Polygon, Path
from ..repetition import Grid
from ..utils import rotation_matrix_2d, layer_t
@ -75,9 +75,9 @@ def write(
#TODO consider supporting DXF arcs?
if not isinstance(library, Library):
if isinstance(library, dict):
library = WrapROLibrary(library)
library = LibraryView(library)
else:
library = WrapROLibrary(dict(library))
library = LibraryView(dict(library))
pattern = library[top_name]
subtree = library.subtree(top_name)
@ -148,7 +148,7 @@ def readfile(
filename: str | pathlib.Path,
*args,
**kwargs,
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
Wrapper for `dxf.read()` that takes a filename or path instead of a stream.
@ -172,7 +172,7 @@ def readfile(
def read(
stream: TextIO,
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
Read a dxf file and translate it into a dict of `Pattern` objects. DXF `Block`s are
translated into `Pattern` objects; `LWPolyline`s are translated into polygons, and `Insert`s
@ -190,7 +190,7 @@ def read(
msp = lib.modelspace()
top_name, top_pat = _read_block(msp)
mlib = WrapLibrary({top_name: top_pat})
mlib = Library({top_name: top_pat})
for bb in lib.blocks:
if bb.name == '*Model_Space':
continue

View File

@ -38,7 +38,7 @@ from .. import Pattern, Ref, PatternError, LibraryError, Label, Shape
from ..shapes import Polygon, Path
from ..repetition import Grid
from ..utils import layer_t, normalize_mirror, annotations_t
from ..library import LazyLibrary, WrapLibrary, MutableLibrary, Library
from ..library import LazyLibrary, Library, ILibrary, ILibraryView
logger = logging.getLogger(__name__)
@ -97,11 +97,11 @@ def write(
library_name: Library name written into the GDSII file.
Default 'masque-klamath'.
"""
if not isinstance(library, MutableLibrary):
if not isinstance(library, ILibrary):
if isinstance(library, dict):
library = WrapLibrary(library)
library = Library(library)
else:
library = WrapLibrary(dict(library))
library = Library(dict(library))
# Create library
header = klamath.library.FileHeader(
@ -160,7 +160,7 @@ def readfile(
filename: str | pathlib.Path,
*args,
**kwargs,
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
Wrapper for `read()` that takes a filename or path instead of a stream.
@ -185,7 +185,7 @@ def readfile(
def read(
stream: IO[bytes],
raw_mode: bool = True,
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
# TODO check GDSII file for cycles!
Read a gdsii file and translate it into a dict of Pattern objects. GDSII structures are
@ -208,7 +208,7 @@ def read(
"""
library_info = _read_header(stream)
mlib = WrapLibrary()
mlib = Library()
found_struct = records.BGNSTR.skip_past(stream)
while found_struct:
name = records.STRNAME.skip_and_read(stream)
@ -511,7 +511,7 @@ def load_library(
stream: IO[bytes],
*,
full_load: bool = False,
postprocess: Callable[[Library, str, Pattern], Pattern] | None = None
postprocess: Callable[[ILibraryView, str, Pattern], Pattern] | None = None
) -> tuple[LazyLibrary, dict[str, Any]]:
"""
Scan a GDSII stream to determine what structures are present, and create
@ -571,7 +571,7 @@ def load_libraryfile(
*,
use_mmap: bool = True,
full_load: bool = False,
postprocess: Callable[[Library, str, Pattern], Pattern] | None = None
postprocess: Callable[[ILibraryView, str, Pattern], Pattern] | None = None
) -> tuple[LazyLibrary, dict[str, Any]]:
"""
Wrapper for `load_library()` that takes a filename or path instead of a stream.

View File

@ -29,7 +29,7 @@ from fatamorgana.basic import PathExtensionScheme, AString, NString, PropStringR
from .utils import is_gzipped, tmpfile
from .. import Pattern, Ref, PatternError, LibraryError, Label, Shape
from ..library import WrapLibrary, MutableLibrary
from ..library import Library, ILibrary
from ..shapes import Polygon, Path, Circle
from ..repetition import Grid, Arbitrary, Repetition
from ..utils import layer_t, normalize_mirror, annotations_t
@ -98,11 +98,11 @@ def build(
Returns:
`fatamorgana.OasisLayout`
"""
if not isinstance(library, MutableLibrary):
if not isinstance(library, ILibrary):
if isinstance(library, dict):
library = WrapLibrary(library)
library = Library(library)
else:
library = WrapLibrary(dict(library))
library = Library(dict(library))
if layer_map is None:
layer_map = {}
@ -205,7 +205,7 @@ def readfile(
filename: str | pathlib.Path,
*args,
**kwargs,
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
Wrapper for `oasis.read()` that takes a filename or path instead of a stream.
@ -229,7 +229,7 @@ def readfile(
def read(
stream: IO[bytes],
) -> tuple[WrapLibrary, dict[str, Any]]:
) -> tuple[Library, dict[str, Any]]:
"""
Read a OASIS file and translate it into a dict of Pattern objects. OASIS cells are
translated into Pattern objects; Polygons are translated into polygons, and Placements
@ -260,7 +260,7 @@ def read(
layer_map[str(layer_name.nstring)] = layer_name
library_info['layer_map'] = layer_map
mlib = WrapLibrary()
mlib = Library()
for cell in lib.cells:
if isinstance(cell.name, int):
cell_name = lib.cellnames[cell.name].nstring.string

View File

@ -35,7 +35,7 @@ logger = logging.getLogger(__name__)
visitor_function_t = Callable[..., 'Pattern']
def _rename_patterns(lib: 'Library', name: str) -> str:
def _rename_patterns(lib: 'ILibraryView', name: str) -> str:
# TODO document rename function
if not name.startswith('_'):
return name
@ -44,7 +44,7 @@ def _rename_patterns(lib: 'Library', name: str) -> str:
return lib.get_name(stem)
class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta):
# inherited abstract functions
#def __getitem__(self, key: str) -> 'Pattern':
#def __iter__(self) -> Iterator[str]:
@ -68,7 +68,7 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
return Abstract(name=name, ports=self[name].ports)
def __repr__(self) -> str:
return '<Library with keys\n' + pformat(list(self.keys())) + '>'
return '<ILibraryView with keys\n' + pformat(list(self.keys())) + '>'
def dangling_refs(
self,
@ -138,9 +138,9 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
def subtree(
self,
tops: str | Sequence[str],
) -> 'Library':
) -> 'ILibraryView':
"""
Return a new `Library`, containing only the specified patterns and the patterns they
Return a new `ILibraryView`, containing only the specified patterns and the patterns they
reference (recursively).
Dangling references do not cause an error.
@ -148,7 +148,7 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
tops: Name(s) of patterns to keep
Returns:
A `WrapROLibrary` containing only `tops` and the patterns they reference.
A `LibraryView` containing only `tops` and the patterns they reference.
"""
if isinstance(tops, str):
tops = (tops,)
@ -157,7 +157,7 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
keep |= set(tops)
filtered = {kk: vv for kk, vv in self.items() if kk in keep}
new = WrapROLibrary(filtered)
new = LibraryView(filtered)
return new
def polygonize(
@ -415,19 +415,19 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
if pattern is not original_pattern:
name = hierarchy[-1] # TODO what is name=None?
if not isinstance(self, MutableLibrary):
if not isinstance(self, ILibrary):
raise LibraryError('visit_* functions returned a new `Pattern` object'
' but the library is immutable')
if name is None:
raise LibraryError('visit_* functions returned a new `Pattern` object'
' but no top-level name was provided in `hierarchy`')
cast(MutableLibrary, self)[name] = pattern
cast(ILibrary, self)[name] = pattern
return self
class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta):
class ILibrary(ILibraryView, MutableMapping[str, 'Pattern'], metaclass=ABCMeta):
# inherited abstract functions
#def __getitem__(self, key: str) -> 'Pattern':
#def __iter__(self) -> Iterator[str]:
@ -510,7 +510,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
def add(
self,
other: Mapping[str, 'Pattern'],
rename_theirs: Callable[['Library', str], str] = _rename_patterns,
rename_theirs: Callable[['ILibraryView', str], str] = _rename_patterns,
) -> dict[str, str]:
"""
Add keys from another library into this one.
@ -534,7 +534,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
self._merge(key, other, key)
return {}
temp = WrapLibrary(copy.deepcopy(dict(other))) # TODO maybe add a `mutate` arg? Might want to keep the same patterns
temp = Library(copy.deepcopy(dict(other))) # TODO maybe add a `mutate` arg? Might want to keep the same patterns
rename_map = {}
for old_name in temp:
if old_name in self:
@ -559,13 +559,13 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
self,
tree: 'Tree',
name: str | None = None,
rename_theirs: Callable[['Library', str], str] = _rename_patterns,
rename_theirs: Callable[['ILibraryView', str], str] = _rename_patterns,
) -> str:
"""
Add a `Tree` object into the current library.
Args:
tree: The `Tree` object (a `Library` with a specified `top` Pattern)
tree: The `Tree` object (an `ILibraryView` with a specified `top` Pattern)
which will be added into the current library.
name: New name for the top-level pattern. If not given, `tree.top` is used.
rename_theirs: Called as rename_theirs(self, name) for each duplicate name
@ -593,8 +593,8 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
if len(other) == 1:
name = next(iter(other))
else:
if not isinstance(other, Library):
other = WrapROLibrary(other)
if not isinstance(other, ILibraryView):
other = LibraryView(other)
tops = other.tops()
if len(tops) > 1:
@ -764,7 +764,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
tops: str | Sequence[str],
) -> Self:
"""
Return a new `Library`, containing only the specified patterns and the patterns they
Return a new `ILibraryView`, containing only the specified patterns and the patterns they
reference (recursively).
Dangling references do not cause an error.
@ -772,7 +772,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
tops: Name(s) of patterns to keep
Returns:
A `Library` containing only `tops` and the patterns they reference.
An object of the same type as `self` containing only `tops` and the patterns they reference.
"""
if isinstance(tops, str):
tops = (tops,)
@ -815,7 +815,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
return self
class WrapROLibrary(Library):
class LibraryView(ILibraryView):
mapping: Mapping[str, 'Pattern']
def __init__(
@ -837,10 +837,10 @@ class WrapROLibrary(Library):
return key in self.mapping
def __repr__(self) -> str:
return f'<WrapROLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
return f'<LibraryView ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
class WrapLibrary(MutableLibrary):
class Library(ILibrary):
mapping: MutableMapping[str, 'Pattern']
def __init__(
@ -885,10 +885,10 @@ class WrapLibrary(MutableLibrary):
self[key_self] = other[key_other]
def __repr__(self) -> str:
return f'<WrapLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
return f'<Library ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
class LazyLibrary(MutableLibrary):
class LazyLibrary(ILibrary):
"""
This class is usually used to create a library of Patterns by mapping names to
functions which generate or load the relevant `Pattern` object as-needed.
@ -1027,9 +1027,9 @@ class LazyLibrary(MutableLibrary):
class AbstractView(Mapping[str, Abstract]):
library: Library
library: ILibraryView
def __init__(self, library: Library) -> None:
def __init__(self, library: ILibraryView) -> None:
self.library = library
def __getitem__(self, key: str) -> Abstract:
@ -1042,9 +1042,9 @@ class AbstractView(Mapping[str, Abstract]):
return self.library.__len__()
class Tree(MutableLibrary):
class Tree(ILibrary):
top: str
library: MutableLibrary
library: ILibrary
@property
def pattern(self) -> 'Pattern':
@ -1053,10 +1053,10 @@ class Tree(MutableLibrary):
def __init__(
self,
top: str,
library: MutableLibrary | None = None
library: ILibrary | None = None
) -> None:
self.top = top
self.library = library if library is not None else WrapLibrary()
self.library = library if library is not None else Library()
@classmethod
def mk(cls, top: str) -> tuple['Tree', 'Pattern']:

View File

@ -16,7 +16,7 @@ from ..label import Label
from ..utils import layer_t
from ..ports import Port
from ..error import PatternError
from ..library import Library, WrapROLibrary
from ..library import ILibraryView, LibraryView
logger = logging.getLogger(__name__)
@ -88,8 +88,8 @@ def data_to_ports(
logger.warning(f'Pattern {name if name else pattern} already had ports, skipping data_to_ports')
return pattern
if not isinstance(library, Library):
library = WrapROLibrary(library)
if not isinstance(library, ILibraryView):
library = LibraryView(library)
data_to_ports_flat(layers, pattern, name)
if (skip_subcells and pattern.ports) or max_depth == 0: