Metadata-Version: 2.4
Name: lr-lumentest-sdk
Version: 0.7.0
Summary: Step-authoring SDK for LumenTest test sequences: write and run steps against the same lumentest_station API the station imports, from a standalone .venv with no monorepo checkout.
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
License-Expression: MIT
Project-URL: Homepage, https://gitlab.com/lumenradio/production/lumentest
Project-URL: Changelog, https://gitlab.com/lumenradio/production/lumentest/-/blob/main/CHANGELOG.md
Keywords: LumenRadio,LumenTest,production test,test station,step SDK
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.8
Requires-Dist: pyserial>=3.5
Provides-Extra: dev
Requires-Dist: build>=1.2.1; extra == "dev"
Requires-Dist: twine>=6.1; extra == "dev"
Requires-Dist: pytest>=8.4; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: black>=25.9; extra == "dev"
Dynamic: license-file

# lr-lumentest-sdk

Step-authoring SDK for LumenRadio LumenTest test sequences.

This package is for an embedded developer writing or updating test steps and
sequences for a LumenTest production station, who wants a `.venv` and an
editor with working imports, type hints and autocomplete for the step API —
without checking out or installing the station itself. It ships the exact
same `lumentest_station` source files the station runs, so a step written and
tested against this package behaves identically when the station loads it.

## Installation

```bash
pip install lr-lumentest-sdk
```

> **This package and `lumentest-station` both provide the `lumentest_station`
> import name and must never be installed into the same environment.** A
> station developer already has the real package — install `lr-lumentest-sdk`
> only in a separate `.venv` dedicated to authoring steps and sequences.

## Public API

```python
from lumentest_station import (
    step_options,      # decorator: attaches step metadata (type, timeout, limits section)
    sequence_options,  # decorator: attaches sequence metadata (name, serial handling)
    run_tool,          # run an external tool as a supervised subprocess
    StepFailed,        # raise to fail the step; optionally carrying the ToolResult that failed
    ToolResult,        # what run_tool() returns: exit_code, stdout, stderr, timed_out
    Measurement,       # a single limits-checked measurement to report
    step_main,         # run this step standalone from the command line
)
```

## Running a single step

A step module can run itself directly, with no separate harness:

```python
from lumentest_station import step_options, step_main


@step_options("PROGRAMMING", display_name="Flash Firmware")
def flash_firmware(test):
    ...


if __name__ == "__main__":
    raise SystemExit(step_main(flash_firmware))
```

```bash
python my_step.py --limits limits.toml --manifest artifact-manifest.json
```

For a step file with no `__main__` guard, use the `lumentest-step` console
script instead:

```bash
lumentest-step validate my_step.py
lumentest-step run my_step.py --limits limits.toml --manifest artifact-manifest.json --env NRF_TOOLS=/opt/nrf --results-dir ./results
```

`validate` is a static check only — it never imports the file, so it needs no
hardware and no environment. It enforces the two rules the station's loader
enforces: exactly one `@step_options`-decorated top-level function, and no
direct `subprocess` use (steps call `run_tool` instead). `run` performs the
same check, then imports and executes the step.

Options for `run`, and for `step_main` under a `__main__` guard:

| Option | Purpose |
|---|---|
| `--limits PATH` | TOML file of measurement limits; repeatable, later files win. Needed by any step that returns measurements. |
| `--manifest PATH` | A package directory, or its `artifact-manifest.json`, so `manifest.resolve(...)` works against a real package |
| `--env NAME=VALUE` | Set an environment variable for the step's run, repeatable. Production steps read station configuration from the environment, so this stands in for the station's `[env]` config. |
| `--dut`, `--article`, `--revision`, `--station` | The identity fields the step sees on its `test` context |
| `--timeout SECONDS` | Override the step's own `@step_options(timeout=...)` |
| `--results-dir DIR` | Where captured `stdout.txt`, `stderr.txt` and `traceback.txt` land |

The exit status is `0` when the step passed, `1` when it failed (an explicit
`StepFailed`, or an out-of-limit measurement), and `2` on an error — an
unexpected exception, a timeout, or a file the loader rejects.

A station does far more than run one step: it uploads to QRM, validates serial
numbers, curates the `PATH` a tool is resolved against, and runs a whole
sequence in order. None of that is reproduced here. A green standalone run says
the step's own logic holds, not that the sequence will pass on a station.

## Full authoring guide

For the complete authoring reference — sequence structure, limits files,
manifests, the step SDK's allowed third-party imports, and the full
`lumentest-step` command reference — see
[`doc/step-sdk.md`](https://gitlab.com/lumenradio/production/lumentest/-/blob/main/doc/step-sdk.md)
in the LumenTest repository.
