From 3b0ef1e08d10f2c83b001c72c92e0c0675b4d18a Mon Sep 17 00:00:00 2001 From: jan Date: Mon, 28 Feb 2022 23:02:36 -0800 Subject: [PATCH] always couple LibDeviceLibrary keys to the underlying Library See comment for why this is necessary --- masque/library/device_library.py | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/masque/library/device_library.py b/masque/library/device_library.py index 4f8de3a..09cf70e 100644 --- a/masque/library/device_library.py +++ b/masque/library/device_library.py @@ -203,6 +203,24 @@ class LibDeviceLibrary(DeviceLibrary): DeviceLibrary.__init__(self) self.underlying = Library() + def __setitem__(self, key: str, value: Callable[[], 'Device']) -> None: + self.generators[key] = value + if key in self.cache: + del self.cache[key] + + # If any `Library` that has been (or will be) added has an entry for `key`, + # it will be added to `self.underlying` and then returned by it during subpattern + # resolution for other entries, and will conflict with the name for our + # wrapped device. To avoid that, we need to set ourselves as the "true" source of + # the `Pattern` named `key`. + if key in self.underlying: + raise DeviceLibraryError(f'Device name {key} already exists in underlying Library!' + ' Demote or delete it first.') + + # NOTE that this means the `Device` may be cached without the `Pattern` being in + # the `underlying` cache yet! + self.underlying.set_value(name, '__DeviceLibrary', lambda: self[key].pattern) + def __delitem__(self, key: str) -> None: DeviceLibrary.__delitem__(self, key) if key in self.underlying: @@ -268,33 +286,17 @@ class LibDeviceLibrary(DeviceLibrary): self, name: str, old_name: str, - tag: str = '_wrap', ) -> None: """ Create a new device which simply contains an instance of an already-existing device. This is useful for assigning an alternate name to a device, while still keeping - the underlying name available for traceability. + the original name available for traceability. Args: name: Name for the wrapped device. old_name: Name of the existing device to wrap. - tag: Tag for the new entry in the `underyling` library. Default '_wrap'. - The default should be usable for most applications. """ - logger.warning('wrap_device needs testing!!!') - #def build_wrapped_pat() -> Pattern: - # dev = self[old_name] - # wrapper = Pattern(name=name) - # wrapper.addsp(dev.pattern) - # return wrapper - ## Need to set underlying entry to allow use as a subcomponent - #self.underlying.set_value(name, tag, build_wrapped_pat) - - #def build_wrapped_dev() -> Device: - # dev = self[old_name] - # wrapper = self.underlying[name] - # return Device(wrapper, dev.ports) def build_wrapped_dev() -> Device: old_dev = self[old_name]