From f80c21ed4d2581a3bf1e82beb6b0a88c1a798ce1 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Thu, 26 Jan 2023 11:36:27 -0800 Subject: [PATCH] Allow library __setitem__ to take in either Pattern or Callable No longer need it to be Generic! --- masque/builder/builder.py | 4 +-- masque/library.py | 57 +++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/masque/builder/builder.py b/masque/builder/builder.py index 530c079..201c37e 100644 --- a/masque/builder/builder.py +++ b/masque/builder/builder.py @@ -532,7 +532,7 @@ class Builder(PortList): in_ptype = self.pattern[portspec].ptype pat = tool.path(ccw, length, in_ptype=in_ptype, port_names=tool_port_names, **kwargs) name = self.library.get_name(base_name) - self.library.set_const(name, pat) + self.library[name] = pat return self.plug(Abstract(name, pat.ports), {portspec: tool_port_names[0]}) def path_to( @@ -615,7 +615,7 @@ class Builder(PortList): for port_name, length in extensions.items(): bld.path(port_name, ccw, length, tool_port_names=tool_port_names) name = self.library.get_name(base_name) - self.library.set_const(name, bld.pattern) + self.library[name] = bld.pattern return self.plug(Abstract(name, bld.pattern.ports), {sp: 'in_' + sp for sp in ports.keys()}) # TODO safe to use 'in_'? # TODO def path_join() and def bus_join()? diff --git a/masque/library.py b/masque/library.py index b7318f8..7888cee 100644 --- a/masque/library.py +++ b/masque/library.py @@ -5,7 +5,7 @@ Library classes for managing unique name->pattern mappings and # TODO documentn all library classes # TODO toplevel documentation of library, classes, and abstracts """ -from typing import List, Dict, Callable, TypeVar, Generic, Type, TYPE_CHECKING, cast +from typing import List, Dict, Callable, TypeVar, Type, TYPE_CHECKING, cast from typing import Tuple, Union, Iterator, Mapping, MutableMapping, Set, Optional, Sequence import logging import base64 @@ -403,32 +403,29 @@ class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta): raise LibraryError('visit_* functions returned a new `Pattern` object' ' but no top-level name was provided in `hierarchy`') - cast(MutableLibrary, self).set_const(name, pattern) + cast(MutableLibrary, self)[name] = pattern return self -VVV = TypeVar('VVV') - - -class MutableLibrary(Library, Generic[VVV], metaclass=ABCMeta): +class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta): # inherited abstract functions #def __getitem__(self, key: str) -> 'Pattern': #def __iter__(self) -> Iterator[str]: #def __len__(self) -> int: @abstractmethod - def __setitem__(self, key: str, value: VVV) -> None: + def __setitem__( + self, + key: str, + value: Union['Pattern', Callable[[], 'Pattern']], + ) -> None: pass @abstractmethod def __delitem__(self, key: str) -> None: pass - @abstractmethod - def set_const(self, key: str, value: 'Pattern') -> None: - pass - @abstractmethod def _merge(self, other: Mapping[str, 'Pattern'], key: str) -> None: pass @@ -566,7 +563,7 @@ class MutableLibrary(Library, Generic[VVV], metaclass=ABCMeta): del pat.shapes[i] for ll, pp in shape_pats.items(): - self.set_const(label2name(ll), pp) + self[label2name(ll)] = pp return self @@ -601,7 +598,7 @@ class MutableLibrary(Library, Generic[VVV], metaclass=ABCMeta): continue name = name_func(pat, shape) - self.set_const(name, Pattern(shapes=[shape])) + self[name] = Pattern(shapes=[shape]) pat.ref(name, repetition=shape.repetition) shape.repetition = None pat.shapes = new_shapes @@ -612,7 +609,7 @@ class MutableLibrary(Library, Generic[VVV], metaclass=ABCMeta): new_labels.append(label) continue name = name_func(pat, label) - self.set_const(name, Pattern(labels=[label])) + self[name] = Pattern(labels=[label]) pat.ref(name, repetition=label.repetition) label.repetition = None pat.labels = new_labels @@ -688,15 +685,23 @@ class WrapLibrary(MutableLibrary): def __len__(self) -> int: return len(self.mapping) - def __setitem__(self, key: str, value: 'Pattern') -> None: + def __setitem__( + self, + key: str, + value: Union['Pattern', Callable[[], 'Pattern']], + ) -> None: + if key in self.mapping: + raise LibraryError(f'"{key}" already exists in the library. Overwriting is not allowed!') + + if callable(value): + value = value() + else: + value = value self.mapping[key] = value def __delitem__(self, key: str) -> None: del self.mapping[key] - def set_const(self, key: str, value: 'Pattern') -> None: - self[key] = value - def _merge(self, other: Mapping[str, 'Pattern'], key: str) -> None: self[key] = other[key] @@ -721,8 +726,20 @@ class LazyLibrary(MutableLibrary): self.cache = {} self._lookups_in_progress = set() - def __setitem__(self, key: str, value: Callable[[], 'Pattern']) -> None: - self.dict[key] = value + def __setitem__( + self, + key: str, + value: Union['Pattern', Callable[[], 'Pattern']], + ) -> None: + if key in self.dict: + raise LibraryError(f'"{key}" already exists in the library. Overwriting is not allowed!') + + if callable(value): + value_func = value + else: + value_func = lambda: cast('Pattern', value) # noqa: E731 + + self.dict[key] = value_func if key in self.cache: del self.cache[key]