query module#

JITX Transformation Query Layer#

A pluggable layer on top of visit() for queries that need conversion. Where visit() finds objects already present in the tree of the requested type, TransformQuery walks the tree and applies registered transformer functions to convert source objects into the requested target type.

A transformer is a function (Trace, S) -> Iterable[(Trace, D)] registered with TransformQuery.transformer(). The engine maintains an adjacency map src -> [Transformer] updated on each registration, and at query time recursively walks forward from each found instance, halting when the recursion produces an instance that matches one of the query’s targets.

A module-level default instance backs the convenience functions query() and transformer(). Built-in transformers (such as Pad -> Copper, Via -> Copper, Via -> Cutout) live in the source files where their source types are defined and self-register on the default at import time. Independent TransformQuery instances can be constructed for isolated registries.

Note that transformers do not apply trace.transform to their output: the produced object is in the source’s local coordinate frame, and the caller composes trace.transform with the object’s geometry if/when needed. This keeps the layer pluggable for any user-defined target type, even ones for which world-coordinate composition is not meaningful, and propagates a None transform (for example when transform=None was passed) faithfully. A transformer _may_ modify the trace.transform if it’s reasonable to update the returned object’s frame of reference, but it will not be applied to the output object (if applicable), and it’s up to the user of the interface to apply it if desired.

>>> # Walk a design and gather every Copper on layer 3, regardless of whether
>>> # it lives as an explicit Copper, a Pour, an OverlappableCopper feature,
>>> # or a per-layer Pad shape.
>>> for trace, c in query(design, Copper, filter=lambda c: c.layer == 3):
...     ...
type TransformerFn = Callable[[Trace, S], Iterable[tuple[Trace, D]]]#
class Transformer(src, dst, fn)[source]#

Bases: object

A registered transformer from one type to another. The function takes a Trace and a source instance and yields (Trace, target_instance) pairs.

Parameters:
src: type#
dst: type#
fn: TransformerFn#
class TransformQuery(base=None)[source]#

Bases: object

Registry and engine for transformation queries. Construct the object, add transformers using the :py:decorator:`~TransformQuery.transformer` and query a design or object using query().

Parameters:

base (TransformQuery | None) – If provided, its transformations will be copied and reused in this registry. It’s a one-time copy, and will not reflect subsequent changes to the base transform query.

register(src, dst, fn)[source]#

Register fn as a transformer from src to dst.

Return type:

None

Parameters:
transformer(src, dst)[source]#

Decorator form of register().

>>> @engine.transformer(Pad, Copper)
... def pad_to_copper(trace, pad):
...     for layer, shape in _explicit_pad_shapes(pad):
...         yield trace, Copper(shape, layer)
Parameters:
query(root, target, /, *, through=None, transform=Transform((0, 0), 0, (1, 1)), opaque=None, refs=False, filter=None)[source]#

Walk root and yield (Trace, target) for every instance of target produced by the registered transformer graph.

Overloads:
  • self, root, target (T), through (tuple[type, …] | UnionType | None), transform (Transform | None), opaque (type | tuple[type, …] | UnionType | None), refs (bool), filter (Callable[[T], bool] | None) → Generator[tuple[Trace, T], None, None]

  • self, root, target (type[T] | tuple[type[T], …]), through (tuple[type, …] | UnionType | None), transform (Transform | None), opaque (type | tuple[type, …] | UnionType | None), refs (bool), filter (Callable[[T], bool] | None) → Generator[tuple[Trace, T], None, None]

Parameters:

target may be a single type, a tuple of types, or a types.UnionType (e.g. Copper | Pour), mirroring visit(). Subclasses count as matches.

For each instance found by visit(), the engine forward-walks registered transformers and yields the first instance of any target produced. This means direct-target instances yield as identity (Pour for target=Copper), source-is-target chains are collapsed (Pad in Pad | Copper yields as Pad, the Pad -> Copper chain is bypassed), and longer chains truncate at the first intermediate that matches a target (with Object -> Pour -> Copper registered, query(design, Pour | Copper) yields the Pour and never reaches Copper).

Arguments mirror visit(). filter is applied to the produced target instances, not to the source instances. trace.transform may be None (when transform=None was passed, or when an intermediate element along the path has no transform); transformers pass it through verbatim.

default = <jitx.query.TransformQuery object>#

The default TransformQuery instance used by the module-level query() and transformer() convenience helpers, and against which the built-in transformers are registered.

transformer(src, dst)[source]#

Convenience: register on the default engine.

>>> @transformer(Pad, Copper)
... def pad_to_copper(trace, pad):
...     ...
Parameters:
query(root, target, /, *, through=None, transform=Transform((0, 0), 0, (1, 1)), opaque=None, refs=False, filter=None)[source]#

Convenience: query against the default engine. See TransformQuery.query().

Overloads:
  • root, target (type[T]), through (tuple[type, …] | UnionType | None), transform (Transform | None), opaque (type | tuple[type, …] | UnionType | None), refs (bool), filter (Callable[[T], bool] | None) → Generator[tuple[Trace, T], None, None]

  • root, target (tuple[type[T], …]), through (tuple[type, …] | UnionType | None), transform (Transform | None), opaque (type | tuple[type, …] | UnionType | None), refs (bool), filter (Callable[[T], bool] | None) → Generator[tuple[Trace, T], None, None]

Parameters: