[Pather / AutoTool] rework route kwargs into tool_options, and actualyl pass them through AutoTool
This commit is contained in:
parent
49713896c3
commit
67afee7704
11 changed files with 865 additions and 130 deletions
|
|
@ -1,11 +1,12 @@
|
|||
from collections.abc import Sequence
|
||||
from typing import Any, Literal, Never
|
||||
import inspect
|
||||
|
||||
import pytest
|
||||
import numpy
|
||||
from numpy import pi
|
||||
|
||||
from masque import MinimumStatus, Pather, Library, Port, RouteError, RouteFailurePolicy
|
||||
from masque import MinimumStatus, Pather, PortPather, Library, Port, RouteError, RouteFailurePolicy
|
||||
from masque.builder.planner import RoutePortContext, RoutingPlanner
|
||||
from masque.builder.planner.planner import NoLegalRouteError
|
||||
from masque.builder.tools import BendOffer, PathTool, RenderStep, StraightOffer, Tool, UOffer
|
||||
|
|
@ -199,7 +200,7 @@ def test_route_error_reports_preferred_minimum_and_request_details() -> None:
|
|||
)
|
||||
|
||||
with pytest.raises(RouteError) as exc_info:
|
||||
p.ccw('A', 1, out_ptype='wide', diagnostic_context='tool-value')
|
||||
p.ccw('A', 1, out_ptype='wide', tool_options={'diagnostic_context': 'tool-value'})
|
||||
|
||||
details = exc_info.value.details
|
||||
assert isinstance(exc_info.value, BuildError)
|
||||
|
|
@ -211,7 +212,7 @@ def test_route_error_reports_preferred_minimum_and_request_details() -> None:
|
|||
'ccw': True,
|
||||
'length': 1,
|
||||
'out_ptype': 'wide',
|
||||
'diagnostic_context': 'tool-value',
|
||||
'tool_options': {'diagnostic_context': 'tool-value'},
|
||||
}
|
||||
assert details.resolved_length == 1
|
||||
assert details.resolved_jog is None
|
||||
|
|
@ -705,7 +706,7 @@ def test_pather_uturn_rejects_routing_bounds(kwargs: dict[str, int]) -> None:
|
|||
p = Pather(Library(), tools=PathTool(layer='M1', width=1, ptype='wire'))
|
||||
p.pattern.ports['A'] = Port((0, 0), rotation=0, ptype='wire')
|
||||
|
||||
with pytest.raises(BuildError, match='Unsupported routing bounds for uturn'):
|
||||
with pytest.raises(TypeError, match='unexpected keyword argument'):
|
||||
p.uturn('A', 4, **kwargs)
|
||||
|
||||
def test_pather_uturn_omitted_length_uses_minimum_length_route() -> None:
|
||||
|
|
@ -935,3 +936,74 @@ def test_pather_uturn_failed_two_bend_route_is_atomic() -> None:
|
|||
assert numpy.allclose(p.pattern.ports['A'].offset, (0, 0))
|
||||
assert p.pattern.ports['A'].rotation == 0
|
||||
assert len(p._paths['A']) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('route_type', [Pather, PortPather])
|
||||
@pytest.mark.parametrize('name', ['trace', 'trace_to', 'straight', 'bend', 'ccw', 'cw', 'jog', 'uturn', 'trace_into'])
|
||||
def test_routing_entry_points_have_no_catch_all_kwargs(route_type: type, name: str) -> None:
|
||||
parameters = inspect.signature(getattr(route_type, name)).parameters.values()
|
||||
assert all(parameter.kind is not inspect.Parameter.VAR_KEYWORD for parameter in parameters)
|
||||
|
||||
|
||||
def test_routing_typo_fails_before_tool_lookup() -> None:
|
||||
tool = RequestCountingTool()
|
||||
p = Pather(Library(), tools=tool, render='deferred')
|
||||
|
||||
with pytest.raises(TypeError, match='unexpected keyword argument'):
|
||||
p.straight('A', lenght=10) # type: ignore[call-arg]
|
||||
|
||||
assert tool.offer_calls == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('tool_options', [{1: 'bad'}, {'ccw': False}, {'out_ptype': 'bad'}])
|
||||
def test_tool_options_reject_invalid_or_reserved_keys(tool_options: dict[Any, Any]) -> None:
|
||||
tool = RequestCountingTool()
|
||||
p = Pather(Library(), tools=tool, render='deferred')
|
||||
|
||||
with pytest.raises(BuildError, match='tool_options'):
|
||||
p.trace('A', None, tool_options=tool_options)
|
||||
|
||||
assert tool.offer_calls == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'operation',
|
||||
[
|
||||
lambda p: p.jog('A', numpy.nan, length=1),
|
||||
lambda p: p.uturn('A', numpy.inf, length=1),
|
||||
lambda p: p.straight('A', x=numpy.nan),
|
||||
],
|
||||
ids=['jog-offset', 'uturn-offset', 'position-bound'],
|
||||
)
|
||||
def test_nonfinite_route_geometry_fails_before_offer_query(operation: Any) -> None:
|
||||
tool = RequestCountingTool()
|
||||
p = Pather(
|
||||
Library(),
|
||||
ports={'A': Port((0, 0), rotation=0, ptype='wire')},
|
||||
tools=tool,
|
||||
render='deferred',
|
||||
)
|
||||
|
||||
with pytest.raises(BuildError, match='finite'):
|
||||
operation(p)
|
||||
|
||||
assert tool.offer_calls == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('spacing', [-1, numpy.nan, numpy.inf])
|
||||
def test_invalid_bundle_spacing_fails_before_offer_query(spacing: float) -> None:
|
||||
tool = RequestCountingTool()
|
||||
p = Pather(
|
||||
Library(),
|
||||
ports={
|
||||
'A': Port((0, 0), rotation=0, ptype='wire'),
|
||||
'B': Port((0, 4), rotation=0, ptype='wire'),
|
||||
},
|
||||
tools=tool,
|
||||
render='deferred',
|
||||
)
|
||||
|
||||
with pytest.raises(BuildError, match='spacing'):
|
||||
p.trace(['A', 'B'], True, xmin=-10, spacing=spacing)
|
||||
|
||||
assert tool.offer_calls == 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue