add the toolctx() context manager to simplify temporary retool() calls

This commit is contained in:
Jan Petykiewicz 2024-10-05 15:51:58 -07:00
parent f7e1e8a9eb
commit 03c4769714
2 changed files with 39 additions and 1 deletions

View File

@ -265,6 +265,12 @@ def main() -> None:
# when using pather.retool(). # when using pather.retool().
pather.path_to('VCC', None, -50_000, out_ptype='m1wire') pather.path_to('VCC', None, -50_000, out_ptype='m1wire')
# Now extend GND out to x=-50_000, using M2 for a portion of the path.
# We can use `pather.toolctx()` to temporarily retool, instead of calling `retool()` twice.
with pather.toolctx(M2_tool, keys=['GND']):
pather.path_to('GND', None, -40_000)
pather.path_to('GND', None, -50_000)
# Save the pather's pattern into our library # Save the pather's pattern into our library
library['Pather_and_BasicTool'] = pather.pattern library['Pather_and_BasicTool'] = pather.pattern

View File

@ -2,9 +2,10 @@
Manual wire/waveguide routing (`Pather`) Manual wire/waveguide routing (`Pather`)
""" """
from typing import Self from typing import Self
from collections.abc import Sequence, MutableMapping, Mapping from collections.abc import Sequence, MutableMapping, Mapping, Iterator
import copy import copy
import logging import logging
from contextlib import contextmanager
from pprint import pformat from pprint import pformat
import numpy import numpy
@ -281,6 +282,37 @@ class Pather(Builder):
self.tools[key] = tool self.tools[key] = tool
return self return self
@contextmanager
def toolctx(
self,
tool: Tool,
keys: str | Sequence[str | None] | None = None,
) -> Iterator[Self]:
"""
Context manager for temporarily `retool`-ing and reverting the `retool`
upon exiting the context.
Args:
tool: The new `Tool` to use for the given ports.
keys: Which ports the tool should apply to. `None` indicates the default tool,
used when there is no matching entry in `self.tools` for the port in question.
Returns:
self
"""
if keys is None or isinstance(keys, str):
keys = [keys]
saved_tools = {kk: self.tools.get(kk, None) for kk in keys} # If not in self.tools, save `None`
try:
yield self.retool(tool=tool, keys=keys)
finally:
for kk, tt in saved_tools.items():
if tt is None:
# delete if present
self.tools.pop(tt, None)
else:
self.tools[kk] = tt
def path( def path(
self, self,
portspec: str, portspec: str,