Expander API

The expander’s own Python API, generated from the source. This is the internal interface of scripts/rigc/ — the surface one module offers another, not a public library. Nothing here is a stability promise: the only supported entry points are the commands in Commands.

Read it to find out where something happens, or when a diagnostic sends you into the code. The prose is each module’s own docstring, so a page here cannot fall behind the code without the code changing under it — and test_api_reference_drift.py fails the test suite if a module is added with no page to document it.

The pipeline

One run is five stages, in this order. Each page below is one stage.

Stage

What it does

Front door

Parses the command line, sequences the run, decides the exit code. Desugars a promoted shield into the rig files the rest of the pipeline reads.

Loader

Reads the rig files and the shield library, resolves every reference and axis, and produces the rig model. Rejects anything the files get wrong.

Board reader

Reads the board’s real devicetree — sockets, buses, controllers — through the preprocessor and edtlib.

Analyzer

Decides whether the assembly is physically possible: mating, positions, nets, addresses, chip-selects, wires, labels. Rejects anything the hardware gets wrong.

Emitter

Renders the overlay, the config sheet, the expectations and the build glue.

Vocabulary is not a stage: it is the vocabulary all five share.

The package root

rigc – the rig compiler: reads a rig’s metadata and shield library, reads the board’s real devicetree, decides whether the assembly is physically possible, and emits the devicetree overlay plus build glue.

Five stages, in order: the CLI front door (cli.py) sequences the run; the loader (loader/, registry.py) reads the rig files and the shield library into the rig model (model.py); the board reader (board/) reads the board’s real devicetree; the analyzer (analyzer/) decides whether the assembly is physically possible; the emitter (emitter/) renders the overlay, the config sheet, the expectations and the build glue. diag.py is the diagnostics core all five report through.

unimplemented.py’s loud refusal (rigc: not implemented: <what>, exit 3) is the channel for a path this tool does not handle – see that module’s own docstring for what still reaches it.

Logging: every module gets its own logging.getLogger(__name__); this package’s ROOT logger gets a NullHandler here, the library convention – without it, an unconfigured logging tree falls through to Python’s own lastResort handler, which would print any WARNING-or- louder record straight to stderr and corrupt a golden comparison. cli.main() is the ONE place that ever attaches a REAL handler, and only when asked to: -v/-vv on the command line (INFO/DEBUG) or, absent either flag, the environment naming a level (RIGC_LOG=<level>) – see _configure_logging’s own docstring for the stderr-purity tradeoff either knob makes deliberately.

Other modules

Not part of the five-stage pipeline above, but real modules under scripts/rigc/ in this repository, documented here for the same reason as everything else on this page — see Test-report rendering for why this one is bridle-specific.