plesty.lib.experiment.cli
The command line that runs an experiment — a module supplies only its rig.
Everything about starting a run is the same for every experiment: which
configuration, where the runs go, whether this is a new run or the resumption
of an interrupted one, and whether to build the plan without touching an
instrument. What differs is the rig and how the experiment is constructed on
it. ExperimentCLI owns the former; the module writes two functions
and is done — the same division Viz makes for
watching a run.
cli = ExperimentCLI(Manifest(module="plesty.pol_pl", title="Polarization PL", ...))
cli.add_argument("--prominence", type=float, sets="analysis.fit_options.prominence",
help="Line-finding threshold in counts.")
@cli.rig
def rig(args, config, skip):
return PolPlRig(devices={n: d for n, d in DEVICES.items() if n not in skip})
@cli.build
def build(args, config, run_root, devices):
return Experiment(devices=devices, config=config, run_root=run_root)
if __name__ == "__main__":
sys.exit(cli.main())
python -m plesty.pol_pl # run with config/default.yaml
python -m plesty.pol_pl --resume pol_pl_2026… # continue an interrupted run
python -m plesty.pol_pl --dry-run # the plan, nothing connected
python -m plesty.pol_pl --manifest # what this module declares, as JSON
--manifest is the contract a caller reads: it connects to nothing, imports
no toolkit and needs no configuration, so a console can ask a freshly installed
module what settings it takes before anything is set up.
Stopping is interrupting. A run has no stop switch of its own and does not
need one: SIGINT reaches the process, the journal records run_canceled,
and the run id it names is what --resume takes. That is what a caller
sends to stop a run it started, and why it must not kill the process outright —
a killed run leaves no journal entry and so no point to resume from.
Attributes
Classes
The standard |
Functions
|
Return the command-line text catalog (loaded once from the assets). |
Module Contents
- plesty.lib.experiment.cli.RigFunc
- plesty.lib.experiment.cli.BuildFunc
- plesty.lib.experiment.cli.ConfigureFunc
- plesty.lib.experiment.cli.DefaultConfigFunc
- plesty.lib.experiment.cli.CheckFunc
- plesty.lib.experiment.cli.FinishedFunc
- plesty.lib.experiment.cli.NeedsFunc
- plesty.lib.experiment.cli._TEXT: dict[str, Any] | None = None
- plesty.lib.experiment.cli._EXIT_CODES
- plesty.lib.experiment.cli._text() dict[str, Any]
Return the command-line text catalog (loaded once from the assets).
- Return type:
dict[str, Any]
- class plesty.lib.experiment.cli.ExperimentCLI(manifest: plesty.lib.experiment.manifest.Manifest)
The standard
python -m <module>command line over one experiment.Describe the experiment this command line runs.
- Parameters:
manifest (plesty.lib.experiment.manifest.Manifest) – What the module declares — the configuration schema, the environment it reads, its default configuration file and run root. Options added with
add_argument()are folded in, so the printed manifest and the parser cannot drift apart.
- manifest
- _configure: ConfigureFunc | None = None
- _default_config: DefaultConfigFunc | None = None
- _finished: FinishedFunc | None = None
- _optional: frozenset[str]
- _extra: list[tuple[tuple[Any, Ellipsis], dict[str, Any]]] = []
- _options: list[plesty.lib.experiment.manifest.Option]
- rig(func: RigFunc) RigFunc
Register the function that builds the rig. Use as a decorator.
It is called again on every preflight retry, so an edited
.envor a server started in the meantime is picked up. ReturningNonedeclares an experiment that drives no devices.
- build(func: BuildFunc) BuildFunc
Register the function that builds the experiment. Use as a decorator.
It receives the rig —
Nonefor--dry-run, where nothing is connected but the plan must still be built.
- default_config(func: DefaultConfigFunc) DefaultConfigFunc
Register which configuration file to read when none was named.
Use as a decorator, for a module whose own options imply a different configuration — a
--demothat replays a recording is configured differently from a run against instruments. ReturningNonetakes the declared file.--configstill wins over both: whoever passed it said which file.- Parameters:
func (DefaultConfigFunc)
- Return type:
- configure(func: ConfigureFunc) ConfigureFunc
Register the configuration override hook. Use as a decorator.
Called once with the loaded configuration and the parsed arguments, before the plan is built; what it returns is the configuration the run freezes into its plan. Optional — without it the file is used as read.
- Parameters:
func (ConfigureFunc)
- Return type:
- finished(func: FinishedFunc) FinishedFunc
Register what to say when a run completes. Use as a decorator.
Called with the run directory once the plan is through, for a module that can summarise what it measured — the fitted results, a count, a path worth naming. It runs only on a completed run: a canceled or aborted one has a summary that would be a half-truth.
- Parameters:
func (FinishedFunc)
- Return type:
- check(func: CheckFunc) CheckFunc
Register the pre-connection check. Use as a decorator.
Called before the rig is built, to refuse an incomplete configuration while nothing has been connected and nothing measured. Optional.
- needs(func: NeedsFunc) NeedsFunc
Register which devices of
setup.yamla configuration uses. Use as a decorator.One module can measure in configurations that use different devices — in place with four, or navigating with four more on another bench. The bench serves only what this returns, and the run needs only those devices’ benches set up (#62).
Nonemeans all of them, as without this function. Optional.@cli.needs def needs(config): return ["hwp", "spec"] if not config.get("dots") else None
- devices(args: argparse.Namespace) list[str] | None
The devices of
setup.yamlthis run uses;Nonefor all of them.- Parameters:
args (argparse.Namespace) – The parsed arguments; their configuration is what decides.
- Return type:
Optional[list[str]]
- optional(*names: str) None
Declare sub-devices the run can do without.
When only these fail the preflight, the operator may continue without them; anything else is a rig that is not what the plan assumes.
- Parameters:
*names (str) – Sub-device names.
- Return type:
None
- add_argument(*args: Any, sets: str | None = None, **kwargs: Any) None
Add one option beyond the standard set, and declare it.
The option reaches both the parser and the printed manifest, so a caller offering the experiment’s settings sees exactly what the command line accepts.
- Parameters:
*args (Any) – As
argparse.ArgumentParser.add_argument().sets (Optional[str]) – The configuration key this option overrides, written as a renderer addresses it (
analysis.fit_options.prominence);Nonewhen it changes something else.**kwargs (Any) – As
argparse.ArgumentParser.add_argument().
- Return type:
None
- declared() plesty.lib.experiment.manifest.Manifest
Return the manifest including the options added to the parser.
- Return type:
- build_parser() argparse.ArgumentParser
Return the argument parser: the standard options plus the module’s.
- Return type:
argparse.ArgumentParser
- run_root(args: argparse.Namespace) str | None
Return where this run’s checkpoint directory goes.
--run-rootwins, as given; otherwise the module’s declared root — under the shared point when one is configured (pol-pl→<PLESTY_DATA>/pol-pl), as it is when not.- Parameters:
args (argparse.Namespace) – The parsed arguments.
- Returns:
The run root, as a path string.
- Return type:
Optional[str]
- config_path(args: argparse.Namespace) pathlib.Path
Return the configuration file this run reads.
--configalways wins: whoever passed it said which file, and a module second-guessing that would make the option a suggestion. With nothing passed, a module that chooses its own — one whose--demoimplies a different configuration — decides throughdefault_config(), and otherwise it is the declared one.- Parameters:
args (argparse.Namespace) – The parsed arguments.
- Returns:
The file to read.
- Return type:
pathlib.Path
- load(args: argparse.Namespace) dict[str, Any]
Return the configuration this run uses, overrides applied.
A missing file is an empty configuration, so an experiment whose defaults are all internal runs without one.
- Parameters:
args (argparse.Namespace) – The parsed arguments.
- Returns:
The configuration to freeze into the plan.
- Return type:
dict[str, Any]
- main(argv: Sequence[str] | None = None) int
Run the command line and return the exit code.
- Parameters:
argv (Optional[Sequence[str]]) – Argument list;
Noneusessys.argv.- Returns:
0when the run completed, the plan printed or the manifest was written; non-zero when the rig was not ready.- Raises:
RuntimeError – If no rig or build function was registered.
- Return type:
int
- async _execute(args: argparse.Namespace) int
Load, plan, connect and run, printing what each outcome means.
- Parameters:
args (argparse.Namespace) – The parsed arguments.
- Returns:
The exit code.
- Return type:
int