From 184168f623fdf20d55a320661443ed4e621be145 Mon Sep 17 00:00:00 2001 From: jan Date: Wed, 19 Nov 2025 01:24:02 -0800 Subject: [PATCH] [PatherMixin] add `thru` arg to path_into and rework portlist inheritance --- masque/builder/pather_mixin.py | 36 +++++++++++++++++++++++++--------- masque/builder/renderpather.py | 15 ++++++++++---- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/masque/builder/pather_mixin.py b/masque/builder/pather_mixin.py index 317bad4..b0ccf61 100644 --- a/masque/builder/pather_mixin.py +++ b/masque/builder/pather_mixin.py @@ -1,5 +1,5 @@ from typing import Self, TYPE_CHECKING -from collections.abc import Sequence, Iterator +from collections.abc import Sequence, Iterator, Iterable import logging from contextlib import contextmanager from abc import abstractmethod, ABCMeta @@ -9,22 +9,19 @@ from numpy import pi from numpy.typing import ArrayLike from ..pattern import Pattern -from ..library import ILibrary +from ..library import ILibrary, TreeView from ..error import PortError, BuildError from ..utils import SupportsBool from ..abstract import Abstract from .tools import Tool from .utils import ell - -if TYPE_CHECKING: - from .pather import Pather - from .renderpather import RenderPather +from ..ports import PortList logger = logging.getLogger(__name__) -class PatherMixin(metaclass=ABCMeta): +class PatherMixin(PortList, metaclass=ABCMeta): pattern: Pattern """ Layout of this device """ @@ -64,6 +61,21 @@ class PatherMixin(metaclass=ABCMeta): ) -> Self: pass + @abstractmethod + def plug( + self, + other: Abstract | str | Pattern | TreeView, + map_in: dict[str, str], + map_out: dict[str, str | None] | None = None, + *, + mirrored: bool = False, + thru: bool | str = True, + set_rotation: bool | None = None, + append: bool = False, + ok_connections: Iterable[tuple[str, str]] = (), + ) -> Self: + pass + def retool( self, tool: Tool, @@ -221,6 +233,7 @@ class PatherMixin(metaclass=ABCMeta): *, out_ptype: str | None = None, plug_destination: bool = True, + thru: str | None = None, **kwargs, ) -> Self: """ @@ -244,6 +257,8 @@ class PatherMixin(metaclass=ABCMeta): out_ptype: Passed to the pathing tool in order to specify the desired port type to be generated at the destination end. If `None` (default), the destination port's `ptype` will be used. + thru: If not `None`, the port by this name will be rename to `portspec_src`. + This can be used when routing a signal through a pre-placed 2-port device. Returns: self @@ -312,6 +327,9 @@ class PatherMixin(metaclass=ABCMeta): else: raise BuildError(f'Don\'t know how to route ports with relative angle {angle}') + if thru is not None: + self.rename_ports({thru: portspec_src}) + return self def mpath( @@ -453,9 +471,9 @@ class PortPather: port without needing to repeatedly pass its name. """ port: str - pather: 'Pather | RenderPather' + pather: PatherMixin - def __init__(self, port: str, pather: 'Pather | RenderPather') -> None: + def __init__(self, port: str, pather: PatherMixin) -> None: self.port = port self.pather = pather diff --git a/masque/builder/renderpather.py b/masque/builder/renderpather.py index 682f9ec..1665ed0 100644 --- a/masque/builder/renderpather.py +++ b/masque/builder/renderpather.py @@ -2,7 +2,7 @@ Pather with batched (multi-step) rendering """ from typing import Self -from collections.abc import Sequence, Mapping, MutableMapping +from collections.abc import Sequence, Mapping, MutableMapping, Iterable import copy import logging from collections import defaultdict @@ -13,7 +13,7 @@ from numpy import pi from numpy.typing import ArrayLike from ..pattern import Pattern -from ..library import ILibrary +from ..library import ILibrary, TreeView from ..error import BuildError from ..ports import PortList, Port from ..abstract import Abstract @@ -25,7 +25,7 @@ from .pather_mixin import PatherMixin logger = logging.getLogger(__name__) -class RenderPather(PortList, PatherMixin): +class RenderPather(PatherMixin): """ `RenderPather` is an alternative to `Pather` which uses the `path`/`path_to`/`mpath` functions to plan out wire paths without incrementally generating the layout. Instead, @@ -188,7 +188,7 @@ class RenderPather(PortList, PatherMixin): def plug( self, - other: Abstract | str, + other: Abstract | str | Pattern | TreeView, map_in: dict[str, str], map_out: dict[str, str | None] | None = None, *, @@ -196,6 +196,7 @@ class RenderPather(PortList, PatherMixin): thru: bool | str = True, set_rotation: bool | None = None, append: bool = False, + ok_connections: Iterable[tuple[str, str]] = (), ) -> Self: """ Wrapper for `Pattern.plug` which adds a `RenderStep` with opcode 'P' @@ -229,6 +230,12 @@ class RenderPather(PortList, PatherMixin): append: If `True`, `other` is appended instead of being referenced. Note that this does not flatten `other`, so its refs will still be refs (now inside `self`). + ok_connections: Set of "allowed" ptype combinations. Identical + ptypes are always allowed to connect, as is `'unk'` with + any other ptypte. Non-allowed ptype connections will emit a + warning. Order is ignored, i.e. `(a, b)` is equivalent to + `(b, a)`. + Returns: self