From 429e687666fccedc3f5af9a0eb7359015f0d6f3d Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Mon, 6 Apr 2026 15:38:03 -0700 Subject: [PATCH] [docs] add migration guide --- MIGRATION.md | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 MIGRATION.md diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..5ab568c --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,265 @@ +# Migration Guide + +This guide covers changes between the git tag `release` and the current tree. +At `release`, `masque.__version__` was `3.3`; the current tree reports `3.4`. + +Most downstream changes are in `masque/builder/*`, but there are a few other +API changes that may require code updates. + +## Routing API: renamed and consolidated + +The routing helpers were consolidated into a single implementation in +`masque/builder/pather.py`. + +The biggest migration point is that the old routing verbs were renamed: + +| Old API | New API | +| --- | --- | +| `Pather.path(...)` | `Pather.trace(...)` | +| `Pather.path_to(...)` | `Pather.trace_to(...)` | +| `Pather.mpath(...)` | `Pather.trace(...)` / `Pather.trace_to(...)` with multiple ports | +| `Pather.path_into(...)` | `Pather.trace_into(...)` | +| `RenderPather.path(...)` | `RenderPather.trace(...)` | +| `RenderPather.path_to(...)` | `RenderPather.trace_to(...)` | +| `RenderPather.mpath(...)` | `RenderPather.trace(...)` / `RenderPather.trace_to(...)` | +| `RenderPather.path_into(...)` | `RenderPather.trace_into(...)` | + +There are also new convenience wrappers: + +- `straight(...)` for `trace_to(..., ccw=None, ...)` +- `ccw(...)` for `trace_to(..., ccw=True, ...)` +- `cw(...)` for `trace_to(..., ccw=False, ...)` +- `jog(...)` for S-bends +- `uturn(...)` for U-bends + +Important: `Pather.path()` is no longer the routing API. It now forwards to +`Pattern.path()` and creates a geometric `Path` element. Any old routing code +that still calls `pather.path(...)` must be renamed. + +### Common rewrites + +```python +# old +pather.path('VCC', False, 6_000) +pather.path_to('VCC', None, x=0) +pather.mpath(['GND', 'VCC'], True, xmax=-10_000, spacing=5_000) +pather.path_into('src', 'dst') + +# new +pather.cw('VCC', 6_000) +pather.straight('VCC', x=0) +pather.ccw(['GND', 'VCC'], xmax=-10_000, spacing=5_000) +pather.trace_into('src', 'dst') +``` + +If you prefer the more explicit spelling, `trace(...)` and `trace_to(...)` +remain the underlying primitives: + +```python +pather.trace('VCC', False, 6_000) +pather.trace_to('VCC', None, x=0) +``` + +## `PortPather` and `.at(...)` + +Routing can now be written in a fluent style via `.at(...)`, which returns a +`PortPather`. + +```python +(rpather.at('VCC') + .trace(False, length=6_000) + .trace_to(None, x=0) +) +``` + +This is additive, not required for migration. Existing code can stay with the +non-fluent `Pather`/`RenderPather` methods after renaming the verbs above. + +## Imports and module layout + +`Builder`, `Pather`, and `RenderPather` now live together in +`masque/builder/pather.py`. The old module files +`masque/builder/builder.py` and `masque/builder/renderpather.py` were removed. + +Update imports like this: + +```python +# old +from masque.builder.builder import Builder +from masque.builder.renderpather import RenderPather + +# new +from masque.builder import Builder, RenderPather +``` + +Top-level imports from `masque` also continue to work. + +`Builder` is now a thin compatibility wrapper over the unified `Pather` +implementation with `auto_render=True`. `RenderPather` is the same wrapper with +`auto_render=False`. + +## `BasicTool` was replaced + +`BasicTool` is no longer exported. Use: + +- `SimpleTool` for the simple "one straight generator + one bend cell" case +- `AutoTool` if you need transitions, multiple candidate straights/bends, or + S-bends/U-bends + +### Old `BasicTool` + +```python +from masque.builder.tools import BasicTool + +tool = BasicTool( + straight=(make_straight, 'input', 'output'), + bend=(lib.abstract('bend'), 'input', 'output'), + transitions={ + 'm2wire': (lib.abstract('via'), 'top', 'bottom'), + }, +) +``` + +### New `AutoTool` + +```python +from masque.builder.tools import AutoTool + +tool = AutoTool( + straights=[ + AutoTool.Straight( + ptype='m1wire', + fn=make_straight, + in_port_name='input', + out_port_name='output', + ), + ], + bends=[ + AutoTool.Bend( + abstract=lib.abstract('bend'), + in_port_name='input', + out_port_name='output', + clockwise=True, + ), + ], + sbends=[], + transitions={ + ('m2wire', 'm1wire'): AutoTool.Transition( + lib.abstract('via'), + 'top', + 'bottom', + ), + }, + default_out_ptype='m1wire', +) +``` + +The key differences are: + +- `BasicTool` -> `SimpleTool` or `AutoTool` +- `straight=(fn, in_name, out_name)` -> `straights=[AutoTool.Straight(...)]` +- `bend=(abstract, in_name, out_name)` -> `bends=[AutoTool.Bend(...)]` +- transition keys are now `(external_ptype, internal_ptype)` tuples +- transitions use `AutoTool.Transition(...)` instead of raw tuples + +If your old `BasicTool` usage did not rely on transitions or multiple routing +options, `SimpleTool` is the closest replacement. + +## Custom `Tool` subclasses + +If you maintain your own `Tool` subclass, the interface changed: + +- `Tool.path(...)` became `Tool.traceL(...)` +- `Tool.traceS(...)` and `Tool.traceU(...)` were added for native S/U routes +- `planL()` / `planS()` / `planU()` remain the planning hooks used by deferred rendering + +In practice, a minimal old implementation like: + +```python +class MyTool(Tool): + def path(self, ccw, length, **kwargs): + ... +``` + +should now become: + +```python +class MyTool(Tool): + def traceL(self, ccw, length, **kwargs): + ... +``` + +If you do not implement `traceS()` or `traceU()`, the unified pather will +either fall back to the planning hooks or synthesize those routes from simpler +steps where possible. + +## Transform semantics changed + +The other major user-visible change is that `mirror()` and `rotate()` are now +treated more consistently as intrinsic transforms on low-level objects. + +The practical migration rule is: + +- use `mirror()` / `rotate()` when you want to change the object relative to its + own origin +- use `flip_across(...)`, `rotate_around(...)`, or container-level transforms + when you want to move the object in its parent coordinate system + +### Example: `Port` + +Old behavior: + +```python +port.mirror(0) # changed both offset and orientation +``` + +New behavior: + +```python +port.mirror(0) # changes orientation only +port.flip_across(axis=0) # old "mirror in the parent pattern" behavior +``` + +### What to audit + +Check code that calls: + +- `Port.mirror(...)` +- `Ref.rotate(...)` +- `Ref.mirror(...)` +- `Label.rotate_around(...)` / `Label.mirror(...)` + +If that code expected offsets or repetition grids to move automatically, it +needs updating. For whole-pattern transforms, prefer calling `Pattern.mirror()` +or `Pattern.rotate_around(...)` at the container level. + +## Other user-facing changes + +### DXF environments + +If you install the DXF extra, the supported `ezdxf` baseline moved from +`~=1.0.2` to `~=1.4`. Any pinned environments should be updated accordingly. + +### New exports + +These are additive, but available now from `masque` and `masque.builder`: + +- `PortPather` +- `SimpleTool` +- `AutoTool` +- `boolean` + +## Minimal migration checklist + +If your code uses the routing stack, do these first: + +1. Replace `path`/`path_to`/`mpath`/`path_into` calls with + `trace`/`trace_to`/multi-port `trace`/`trace_into`. +2. Replace `BasicTool` with `SimpleTool` or `AutoTool`. +3. Fix imports that still reference `masque.builder.builder` or + `masque.builder.renderpather`. +4. Audit any low-level `mirror()` usage, especially on `Port` and `Ref`. + +If your code only uses `Pattern`, `Library`, `place()`, and `plug()` without the +routing helpers, you may not need any changes beyond the transform audit and any +stale imports.