From f0a71bfb8bf73beb5bdea81c24082df43d565c4c Mon Sep 17 00:00:00 2001 From: jan Date: Fri, 7 Apr 2023 18:08:42 -0700 Subject: [PATCH] redo library class naming --- examples/pic2mask.py | 2 +- examples/test_rep.py | 6 ++-- examples/tutorial/devices.py | 4 +-- examples/tutorial/library.py | 2 +- masque/__init__.py | 4 +-- masque/abstract.py | 4 +-- masque/builder/builder.py | 22 ++++++------- masque/builder/flatbuilder.py | 4 +-- masque/file/dxf.py | 12 ++++---- masque/file/gdsii.py | 18 +++++------ masque/file/oasis.py | 14 ++++----- masque/library.py | 58 +++++++++++++++++------------------ masque/utils/ports2data.py | 6 ++-- 13 files changed, 78 insertions(+), 78 deletions(-) diff --git a/examples/pic2mask.py b/examples/pic2mask.py index 883f145..0f0d9a1 100644 --- a/examples/pic2mask.py +++ b/examples/pic2mask.py @@ -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 # diff --git a/examples/test_rep.py b/examples/test_rep.py index 4c99aa5..e4dbe28 100644 --- a/examples/test_rep.py +++ b/examples/test_rep.py @@ -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)} diff --git a/examples/tutorial/devices.py b/examples/tutorial/devices.py index c4e0896..b12fb6f 100644 --- a/examples/tutorial/devices.py +++ b/examples/tutorial/devices.py @@ -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) # diff --git a/examples/tutorial/library.py b/examples/tutorial/library.py index f23cf14..fe31265 100644 --- a/examples/tutorial/library.py +++ b/examples/tutorial/library.py @@ -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 diff --git a/masque/__init__.py b/masque/__init__.py index 54e199d..69fac81 100644 --- a/masque/__init__.py +++ b/masque/__init__.py @@ -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, ) diff --git a/masque/abstract.py b/masque/abstract.py index 9eefcbb..0f06144 100644 --- a/masque/abstract.py +++ b/masque/abstract.py @@ -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': # """ diff --git a/masque/builder/builder.py b/masque/builder/builder.py index 22905d9..b4998df 100644 --- a/masque/builder/builder.py +++ b/masque/builder/builder.py @@ -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`') diff --git a/masque/builder/flatbuilder.py b/masque/builder/flatbuilder.py index 9994e2b..b90769a 100644 --- a/masque/builder/flatbuilder.py +++ b/masque/builder/flatbuilder.py @@ -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 diff --git a/masque/file/dxf.py b/masque/file/dxf.py index 505b2ba..110129c 100644 --- a/masque/file/dxf.py +++ b/masque/file/dxf.py @@ -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 diff --git a/masque/file/gdsii.py b/masque/file/gdsii.py index 621c9b4..968a58a 100644 --- a/masque/file/gdsii.py +++ b/masque/file/gdsii.py @@ -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. diff --git a/masque/file/oasis.py b/masque/file/oasis.py index 3a6db97..8de9c1d 100644 --- a/masque/file/oasis.py +++ b/masque/file/oasis.py @@ -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 diff --git a/masque/library.py b/masque/library.py index f9411b1..07c0326 100644 --- a/masque/library.py +++ b/masque/library.py @@ -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 '' + return '' 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'' + return f'' -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'' + return f'' -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']: diff --git a/masque/utils/ports2data.py b/masque/utils/ports2data.py index d7ccf41..7963de7 100644 --- a/masque/utils/ports2data.py +++ b/masque/utils/ports2data.py @@ -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: