lr-lumentest-cli 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lr_lumentest_cli-0.5.1/LICENSE +21 -0
- lr_lumentest_cli-0.5.1/Makefile +145 -0
- lr_lumentest_cli-0.5.1/PKG-INFO +245 -0
- lr_lumentest_cli-0.5.1/README.md +213 -0
- lr_lumentest_cli-0.5.1/lumentest.spec +48 -0
- lr_lumentest_cli-0.5.1/pyproject.toml +86 -0
- lr_lumentest_cli-0.5.1/setup.cfg +4 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/PKG-INFO +245 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/SOURCES.txt +55 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/dependency_links.txt +1 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/entry_points.txt +2 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/requires.txt +15 -0
- lr_lumentest_cli-0.5.1/src/lr_lumentest_cli.egg-info/top_level.txt +1 -0
- lr_lumentest_cli-0.5.1/src/lumentest/__init__.py +6 -0
- lr_lumentest_cli-0.5.1/src/lumentest/__main__.py +3 -0
- lr_lumentest_cli-0.5.1/src/lumentest/_version.py +24 -0
- lr_lumentest_cli-0.5.1/src/lumentest/auth.py +185 -0
- lr_lumentest_cli-0.5.1/src/lumentest/build_words.py +94 -0
- lr_lumentest_cli-0.5.1/src/lumentest/cli.py +58 -0
- lr_lumentest_cli-0.5.1/src/lumentest/client.py +1125 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/__init__.py +1 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/config.py +218 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/operator.py +200 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/product.py +686 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/result.py +692 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/sequence.py +325 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/test.py +308 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands/test_ui.py +753 -0
- lr_lumentest_cli-0.5.1/src/lumentest/commands_shared.py +301 -0
- lr_lumentest_cli-0.5.1/src/lumentest/config.py +69 -0
- lr_lumentest_cli-0.5.1/src/lumentest/env_report.py +220 -0
- lr_lumentest_cli-0.5.1/src/lumentest/manifest_gen.py +235 -0
- lr_lumentest_cli-0.5.1/src/lumentest/prerequisites_report.py +218 -0
- lr_lumentest_cli-0.5.1/tests/__init__.py +0 -0
- lr_lumentest_cli-0.5.1/tests/conftest.py +67 -0
- lr_lumentest_cli-0.5.1/tests/integration/__init__.py +0 -0
- lr_lumentest_cli-0.5.1/tests/integration/test_entrypoint_smoke.py +105 -0
- lr_lumentest_cli-0.5.1/tests/unit/__init__.py +0 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_auth.py +314 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_build_words.py +84 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_cli_version.py +28 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_client.py +561 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_commands_shared.py +249 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_config.py +138 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_config_commands.py +551 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_env_report.py +331 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_json_output_contract.py +716 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_manifest_gen.py +488 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_operator.py +235 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_prerequisites_report.py +470 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_product.py +874 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_product_import.py +1521 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_pypi_metadata.py +206 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_result.py +1309 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_sequence.py +582 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_test_commands.py +767 -0
- lr_lumentest_cli-0.5.1/tests/unit/test_test_ui.py +1141 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LumenRadio AB
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
VENV := .venv
|
|
2
|
+
PY := $(VENV)/bin/python
|
|
3
|
+
PIP := $(VENV)/bin/pip
|
|
4
|
+
|
|
5
|
+
# Resolve black config from the repo root (one directory up).
|
|
6
|
+
# This avoids duplicating line-length / target-version between server and CLI.
|
|
7
|
+
ROOT_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
|
|
8
|
+
|
|
9
|
+
# setuptools_scm version, resolved on the host from the installed _version.py.
|
|
10
|
+
# Injected via SETUPTOOLS_SCM_PRETEND_VERSION_FOR_* so the sdist build skips the
|
|
11
|
+
# VCS file-finder (which root=".." would otherwise use to pull in the whole
|
|
12
|
+
# monorepo), and so in-container builds (no git / no repo-root mount) get it too.
|
|
13
|
+
DIST_ENV := SETUPTOOLS_SCM_PRETEND_VERSION_FOR_LR_LUMENTEST_CLI
|
|
14
|
+
SCM_VERSION = $(shell $(PY) -c "import lumentest._version as v; print(v.version)" 2>/dev/null)
|
|
15
|
+
|
|
16
|
+
# Only the sdist and wheel are valid PyPI distributions; dist/ also holds the
|
|
17
|
+
# PyInstaller one-file binary and the linux-arm64/ build tree, so a bare
|
|
18
|
+
# dist/* glob trips twine on files it was never meant to see.
|
|
19
|
+
DIST_FILES := dist/*.whl dist/*.tar.gz
|
|
20
|
+
|
|
21
|
+
PYPI_REPOSITORY ?= https://upload.pypi.org/legacy/
|
|
22
|
+
TEST_PYPI_REPOSITORY ?= https://test.pypi.org/legacy/
|
|
23
|
+
|
|
24
|
+
# The PyPI token lives in the releasing developer's shell, exported by hand
|
|
25
|
+
# before running `publish`/`publish-test` — the same arrangement lr-gladiator
|
|
26
|
+
# and lr-qrm use. No CI job holds it, so a release reaches PyPI only when a
|
|
27
|
+
# person runs the target.
|
|
28
|
+
#
|
|
29
|
+
# setuptools_scm derives SCM_VERSION from the `lumentest-*` tag: any commit
|
|
30
|
+
# past the tag carries a `.devN+g<sha>` suffix. PyPI rejects a local (`+…`)
|
|
31
|
+
# segment outright, and a `.dev` upload permanently spends a version number
|
|
32
|
+
# the index can never reuse — so both upload targets refuse anything but a
|
|
33
|
+
# clean tag.
|
|
34
|
+
CHECK_RELEASE_VERSION = case "$(SCM_VERSION)" in *dev*|*+*|"") echo "error: refusing to upload $(SCM_VERSION) — build from a clean 'lumentest-X.Y.Z' tag"; exit 2 ;; esac
|
|
35
|
+
|
|
36
|
+
.DEFAULT_GOAL := install
|
|
37
|
+
|
|
38
|
+
.PHONY: install dev test test-only format dist check publish publish-test shell clean package build-linux-docker build-linux-arm64-docker build-windows-docker
|
|
39
|
+
|
|
40
|
+
$(VENV)/bin/activate:
|
|
41
|
+
python3.12 -m venv $(VENV)
|
|
42
|
+
$(PIP) install --upgrade pip
|
|
43
|
+
|
|
44
|
+
install: $(VENV)/bin/activate
|
|
45
|
+
$(PIP) install .
|
|
46
|
+
|
|
47
|
+
dev: $(VENV)/bin/activate
|
|
48
|
+
$(PIP) install -e ".[dev,package]"
|
|
49
|
+
|
|
50
|
+
# `test` is the whole job: sync the venv, then run pytest. `test-only` is the
|
|
51
|
+
# pytest half on its own, for a driver that has already done the `dev` pass and
|
|
52
|
+
# wants to run several sub-trees at once -- the editable installs `dev` performs
|
|
53
|
+
# write in-tree build artefacts, so they must not overlap; pytest runs may.
|
|
54
|
+
test: dev test-only
|
|
55
|
+
|
|
56
|
+
test-only:
|
|
57
|
+
$(VENV)/bin/pytest \
|
|
58
|
+
--cov=lumentest \
|
|
59
|
+
--cov-report=term-missing \
|
|
60
|
+
--cov-report=html:htmlcov \
|
|
61
|
+
--junit-xml=test-results.xml \
|
|
62
|
+
tests/
|
|
63
|
+
|
|
64
|
+
format: dev
|
|
65
|
+
$(VENV)/bin/black --config $(ROOT_DIR)/pyproject.toml src/ tests/
|
|
66
|
+
|
|
67
|
+
# Clearing the previous sdist and wheel is what keeps `$(DIST_FILES)` meaning
|
|
68
|
+
# "this build": every artefact accumulates under its own version, and an upload
|
|
69
|
+
# globbing the directory would carry a stale version along with the current one.
|
|
70
|
+
# The PyInstaller binary and the arm64 tree in dist/ are left alone.
|
|
71
|
+
dist: dev
|
|
72
|
+
rm -f dist/*.whl dist/*.tar.gz
|
|
73
|
+
$(DIST_ENV)="$(SCM_VERSION)" $(PY) -m build
|
|
74
|
+
|
|
75
|
+
check: dist
|
|
76
|
+
$(VENV)/bin/twine check $(DIST_FILES)
|
|
77
|
+
|
|
78
|
+
# Both upload targets pass credentials through TWINE_USERNAME/TWINE_PASSWORD,
|
|
79
|
+
# which twine reads natively, and silence the upload line with `@`. `-u`/`-p`
|
|
80
|
+
# would put the token in the echoed recipe line and in the upload process's
|
|
81
|
+
# argv, where `ps` can read it — visible in a developer's scrollback and, since
|
|
82
|
+
# this target also runs as a CI job, in a captured job log.
|
|
83
|
+
publish-test: check
|
|
84
|
+
@$(CHECK_RELEASE_VERSION)
|
|
85
|
+
@if [ -z "$$TEST_PYPI_TOKEN" ]; then echo "error: TEST_PYPI_TOKEN is required — create one at https://test.pypi.org/manage/account/token/"; exit 2; fi
|
|
86
|
+
@TWINE_USERNAME=__token__ TWINE_PASSWORD="$$TEST_PYPI_TOKEN" $(VENV)/bin/twine upload --repository-url $(TEST_PYPI_REPOSITORY) $(DIST_FILES)
|
|
87
|
+
|
|
88
|
+
publish: check
|
|
89
|
+
@$(CHECK_RELEASE_VERSION)
|
|
90
|
+
@if [ -z "$$PYPI_TOKEN" ]; then echo "error: PYPI_TOKEN is required — create one at https://pypi.org/manage/account/token/"; exit 2; fi
|
|
91
|
+
@TWINE_USERNAME=__token__ TWINE_PASSWORD="$$PYPI_TOKEN" $(VENV)/bin/twine upload --repository-url $(PYPI_REPOSITORY) $(DIST_FILES)
|
|
92
|
+
|
|
93
|
+
shell:
|
|
94
|
+
@echo "source $(VENV)/bin/activate"
|
|
95
|
+
|
|
96
|
+
clean:
|
|
97
|
+
rm -rf $(VENV) dist/ build/ htmlcov/ test-results.xml .coverage
|
|
98
|
+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null; true
|
|
99
|
+
find . -name "*.pyc" -delete 2>/dev/null; true
|
|
100
|
+
find . -name "*.egg-info" -type d -exec rm -rf {} + 2>/dev/null; true
|
|
101
|
+
|
|
102
|
+
package: dev
|
|
103
|
+
$(VENV)/bin/pyinstaller lumentest.spec
|
|
104
|
+
|
|
105
|
+
# ubuntu:24.04 caps the glibc floor at 2.39 by construction.
|
|
106
|
+
build-linux-docker: dev
|
|
107
|
+
docker run --rm \
|
|
108
|
+
-e $(DIST_ENV)="$(SCM_VERSION)" \
|
|
109
|
+
-e DEBIAN_FRONTEND=noninteractive \
|
|
110
|
+
-v "$(CURDIR):/src" \
|
|
111
|
+
-w /src \
|
|
112
|
+
ubuntu:24.04 \
|
|
113
|
+
bash -c "apt-get update -qq && \
|
|
114
|
+
apt-get install -y --no-install-recommends python3 python3-venv python3-pip binutils && \
|
|
115
|
+
python3 -m venv /build-venv && \
|
|
116
|
+
/build-venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
|
117
|
+
/build-venv/bin/pip install --no-cache-dir -e ".[package]" && \
|
|
118
|
+
/build-venv/bin/pyinstaller lumentest.spec; \
|
|
119
|
+
rc=\$$?; chown -R $(shell id -u):$(shell id -g) build dist src/*.egg-info 2>/dev/null; exit \$$rc"
|
|
120
|
+
|
|
121
|
+
build-linux-arm64-docker: dev
|
|
122
|
+
docker run --rm \
|
|
123
|
+
--platform linux/arm64 \
|
|
124
|
+
-e $(DIST_ENV)="$(SCM_VERSION)" \
|
|
125
|
+
-e DEBIAN_FRONTEND=noninteractive \
|
|
126
|
+
-v "$(CURDIR):/src" \
|
|
127
|
+
-w /src \
|
|
128
|
+
ubuntu:24.04 \
|
|
129
|
+
bash -c "apt-get update -qq && \
|
|
130
|
+
apt-get install -y --no-install-recommends python3 python3-venv python3-pip binutils && \
|
|
131
|
+
python3 -m venv /build-venv && \
|
|
132
|
+
/build-venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
|
133
|
+
/build-venv/bin/pip install --no-cache-dir -e ".[package]" && \
|
|
134
|
+
/build-venv/bin/pyinstaller lumentest.spec --distpath dist/linux-arm64 --workpath build/linux-arm64; \
|
|
135
|
+
rc=\$$?; chown -R $(shell id -u):$(shell id -g) build dist src/*.egg-info 2>/dev/null; exit \$$rc"
|
|
136
|
+
|
|
137
|
+
build-windows-docker: dev
|
|
138
|
+
docker run --rm \
|
|
139
|
+
--entrypoint bash \
|
|
140
|
+
-e $(DIST_ENV)="$(SCM_VERSION)" \
|
|
141
|
+
-v "$(CURDIR):/src" \
|
|
142
|
+
-w /src \
|
|
143
|
+
batonogov/pyinstaller-windows:v5.0.0 \
|
|
144
|
+
-c "pip install --no-cache-dir --upgrade -e . && pyinstaller lumentest.spec; \
|
|
145
|
+
rc=\$$?; chown -R $(shell id -u):$(shell id -g) build dist src/*.egg-info 2>/dev/null; exit \$$rc"
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lr-lumentest-cli
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: CLI client for the LumenRadio LumenTest production test station: import artifact packages, run test sequences, and read results over HTTP.
|
|
5
|
+
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/lumenradio/production/lumentest
|
|
8
|
+
Project-URL: Changelog, https://gitlab.com/lumenradio/production/lumentest/-/blob/main/CHANGELOG.md
|
|
9
|
+
Keywords: LumenRadio,LumenTest,production test,test station,CLI
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Topic :: Software Development :: Testing
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: typer>=0.12
|
|
19
|
+
Requires-Dist: rich>=13.7
|
|
20
|
+
Requires-Dist: httpx>=0.27
|
|
21
|
+
Requires-Dist: pydantic>=2.8
|
|
22
|
+
Requires-Dist: mnemonic>=0.21
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
25
|
+
Requires-Dist: twine>=6.1; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest>=8.4; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
28
|
+
Requires-Dist: black>=25.9; extra == "dev"
|
|
29
|
+
Provides-Extra: package
|
|
30
|
+
Requires-Dist: pyinstaller==6.21.0; extra == "package"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# lr-lumentest-cli
|
|
34
|
+
|
|
35
|
+
CLI for the LumenRadio LumenTest production test station server.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install lr-lumentest-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Point the CLI at your station server and identify yourself by scanning
|
|
47
|
+
# your badge (the handheld scanner types the badge id at the prompt)
|
|
48
|
+
lumentest login --base-url http://10.0.0.1:17080 --badge-id LOP0000001
|
|
49
|
+
|
|
50
|
+
# Check server health and login state
|
|
51
|
+
lumentest status
|
|
52
|
+
|
|
53
|
+
# Scan and list imported products
|
|
54
|
+
lumentest product scan
|
|
55
|
+
lumentest product list
|
|
56
|
+
|
|
57
|
+
# Run a full test sequence interactively (prompts on ALERT steps)
|
|
58
|
+
lumentest test start --serial SN-00001
|
|
59
|
+
|
|
60
|
+
# Run a single step (for development / debugging)
|
|
61
|
+
lumentest test step production-test flash-firmware --serial SN-00001
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Command Reference
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
lumentest login [--base-url URL] --badge-id ID
|
|
68
|
+
# ID is the scanned QR badge; the server resolves it to your operator id.
|
|
69
|
+
lumentest logout
|
|
70
|
+
lumentest status [--output rich|json]
|
|
71
|
+
lumentest --version
|
|
72
|
+
|
|
73
|
+
lumentest product list [--output rich|json]
|
|
74
|
+
# Table includes a Build Words column — see doc/build-words.md. The manifest
|
|
75
|
+
# digest is not shown: read it from --output json when you need the digest.
|
|
76
|
+
lumentest product active
|
|
77
|
+
lumentest product set ARTICLE [REVISION]
|
|
78
|
+
lumentest product remove ARTICLE [REVISION] [--yes]
|
|
79
|
+
lumentest product scan [--rescan] [--output rich|json]
|
|
80
|
+
# Scans the station's artifact_cache/, registers every valid package, and
|
|
81
|
+
# reports each package's declared env variables (from parameters.toml) —
|
|
82
|
+
# the value a run will see, where it came from (config.toml's [env], the
|
|
83
|
+
# station's own environment, or the package default) and which are still
|
|
84
|
+
# unconfigured — alongside its prerequisites (the external tools its
|
|
85
|
+
# sequences need) against the station itself. Each unconfigured variable's
|
|
86
|
+
# line carries the exact `lumentest config set env.NAME <VALUE>` command to
|
|
87
|
+
# fix it; a set value applies to the running station immediately, so
|
|
88
|
+
# re-running scan is enough to confirm it, for a variable and for a tool
|
|
89
|
+
# newly installed on PATH alike — no restart needed either way. --output
|
|
90
|
+
# json emits the raw payload.
|
|
91
|
+
lumentest product import PATH [--update] [--bundle] [--output rich|json]
|
|
92
|
+
# PATH: directory or .zip/.tar.gz archive.
|
|
93
|
+
# --update: recompute SHA-256 checksums in artifact-manifest.json before
|
|
94
|
+
# uploading — useful during step development to skip manual hashing.
|
|
95
|
+
# --bundle: pack PATH into <PATH>.tar.gz (manifest + declared files only)
|
|
96
|
+
# next to it instead of uploading — for email/USB delivery;
|
|
97
|
+
# import the archive later with the same command. Requires a
|
|
98
|
+
# directory; passing an archive file just warns and exits.
|
|
99
|
+
# Prints the package's Build Words (doc/build-words.md) so a
|
|
100
|
+
# technician can read them off a locally built bundle without a
|
|
101
|
+
# running server; --output json carries them as "build_words".
|
|
102
|
+
# Reports the package's declared env variables the same way `product scan`
|
|
103
|
+
# does: the value a run will see, where it came from, and which still need
|
|
104
|
+
# a value. Fix an unconfigured one with the `lumentest config set` command
|
|
105
|
+
# printed on its line, then re-run `product scan` to confirm — same as
|
|
106
|
+
# confirming a newly installed prerequisite tool, neither needs a restart.
|
|
107
|
+
# Only artifact-manifest.json's declared files (and declared extra
|
|
108
|
+
# sequences) are packed and uploaded — the manifest is the contract for
|
|
109
|
+
# what the package needs. A package that needs a file its manifest does
|
|
110
|
+
# not declare must have that file added to the manifest, not bundled some
|
|
111
|
+
# other way.
|
|
112
|
+
# A directory import first checks with the station which files it already
|
|
113
|
+
# has (by digest, including across every other cached revision) — a
|
|
114
|
+
# retry after an interrupted upload resumes instead of re-sending
|
|
115
|
+
# everything. Only what's actually missing is uploaded, with a progress
|
|
116
|
+
# bar over just those bytes; the command then reports how many files were
|
|
117
|
+
# reused, e.g. "12 of 24 files already on the station (302 MB reused)".
|
|
118
|
+
# An existing .zip/.tar.gz archive still uploads as a single one-shot
|
|
119
|
+
# transfer. --output json moves all of the above to stderr so stdout
|
|
120
|
+
# carries nothing but the final JSON — see "Machine-readable output".
|
|
121
|
+
|
|
122
|
+
lumentest sequence list [--article ARTICLE] [--output rich|json]
|
|
123
|
+
lumentest sequence steps ARTICLE SEQUENCE
|
|
124
|
+
lumentest sequence selection get ARTICLE SEQUENCE
|
|
125
|
+
lumentest sequence selection set ARTICLE SEQUENCE --steps 1,2,5
|
|
126
|
+
lumentest sequence selection clear ARTICLE SEQUENCE
|
|
127
|
+
|
|
128
|
+
lumentest test start [--serial SN] [--article ARTICLE] [--sequence NAME]
|
|
129
|
+
# Blocks with an interactive Rich UI; handles ALERT prompts; exits with
|
|
130
|
+
# the run's terminal status: 0 PASS, 1 FAIL, 2 ABORTED, 3 ERROR (outcome
|
|
131
|
+
# undetermined — station unreachable or run gone). The operator comes
|
|
132
|
+
# from the bearer token established by `lumentest login`, not a flag.
|
|
133
|
+
# The run header shows the package's Build Words when the station reports
|
|
134
|
+
# them.
|
|
135
|
+
lumentest test step SEQUENCE STEP [--article ARTICLE] [--serial SN]
|
|
136
|
+
# Runs one step via the same interactive UI. STEP is a name or 0-based index.
|
|
137
|
+
lumentest test status [--output rich|json]
|
|
138
|
+
# One-shot snapshot of the currently active test run.
|
|
139
|
+
|
|
140
|
+
lumentest result list [--limit N] [--serial SN] [--output rich|json]
|
|
141
|
+
# --serial SN filters to runs for one device (exact dut_id match); the station
|
|
142
|
+
# filters server-side so high-throughput stations don't ship the full history.
|
|
143
|
+
lumentest result show [RUN_ID]
|
|
144
|
+
# RUN_ID is optional: omit it to show the most recent run.
|
|
145
|
+
lumentest result logs [RUN_ID] [--step IDX] [--stream stdout|stderr|traceback]
|
|
146
|
+
[--download DIR] [--output rich|json]
|
|
147
|
+
# RUN_ID is optional: omit it to fetch the most recent run's logs.
|
|
148
|
+
# Without --step: fetches the complete log bundle via GET /logs/all — run error,
|
|
149
|
+
# structured journal, and every step's stdout/stderr/traceback. --output json
|
|
150
|
+
# emits the raw JSON bundle; --download DIR writes the tree to DIR/<run_id>/
|
|
151
|
+
# (error.txt, log.jsonl, steps/<name>/{stdout,stderr,traceback}.txt, omitting
|
|
152
|
+
# empty files). --output json takes precedence when both flags are given.
|
|
153
|
+
# With --step IDX: shows that step's stdout, stderr, and traceback (or a single
|
|
154
|
+
# stream via --stream).
|
|
155
|
+
lumentest result export [RUN_ID] [--all] [--serial SN] [--limit N]
|
|
156
|
+
[--out DIR] [--output rich|json]
|
|
157
|
+
# Downloads one .tar.gz station snapshot via GET /api/results/export: the
|
|
158
|
+
# selected run(s) verbatim under results/ (run.json, qrm-payload.json, the
|
|
159
|
+
# journal, every step's captured streams) plus the station's own log,
|
|
160
|
+
# state.json, operator_stats.json and effective config under station/ —
|
|
161
|
+
# laid out exactly as the station stores them on disk. RUN_ID / --all /
|
|
162
|
+
# --serial / --limit govern results/ only; the station context is always
|
|
163
|
+
# included. Bare `result export` packs only the most recent run; --all
|
|
164
|
+
# opts into every retained run. RUN_ID is mutually exclusive with --all,
|
|
165
|
+
# --serial and --limit.
|
|
166
|
+
# --out DIR: directory to write the archive into (default: the current
|
|
167
|
+
# directory). The filename is stamped by the station itself from its own
|
|
168
|
+
# [station].id and a UTC timestamp, so an export stays identifiable once
|
|
169
|
+
# it is off the station.
|
|
170
|
+
# artifact_cache/ package binaries are never packed — represented instead by
|
|
171
|
+
# an inventory (article, revision, size, file count); Arena is the system
|
|
172
|
+
# of record for firmware. Re-send a run to QRM by hand with
|
|
173
|
+
# `qrm result upload <run>/qrm-payload.json` against the extracted tree.
|
|
174
|
+
# An export contains the station's QRM service password, session token
|
|
175
|
+
# hashes, operator identities, and whatever a step or tool printed. Treat
|
|
176
|
+
# an archive as a secret — see doc/troubleshooting.md § Collecting a
|
|
177
|
+
# station snapshot for support.
|
|
178
|
+
|
|
179
|
+
lumentest config list [--output rich|json]
|
|
180
|
+
# Flattens config.toml to dotted keys (station.id, env.NRF_TOOLS,
|
|
181
|
+
# timeouts.default_step_s, ...) so a technician can scan the whole
|
|
182
|
+
# effective configuration in one table. Secrets (qrm.password,
|
|
183
|
+
# serial.client_secret, user password hashes) show as "<redacted>" and are
|
|
184
|
+
# marked in the Notes column, alongside keys that need a station restart
|
|
185
|
+
# to take effect (station.host, station.port, debug.results_dir).
|
|
186
|
+
lumentest config get KEY [--output rich|json]
|
|
187
|
+
lumentest config set KEY VALUE [--json] [--output rich|json]
|
|
188
|
+
# VALUE is sent as a raw string and coerced through the server's pydantic
|
|
189
|
+
# validation (e.g. "90" -> the int 90); pass --json to send VALUE parsed
|
|
190
|
+
# as JSON instead, for list/dict/explicitly-typed values. This is how a
|
|
191
|
+
# newly required package env variable gets set without restarting the
|
|
192
|
+
# station: `lumentest config set env.SOME_VAR value` then
|
|
193
|
+
# `lumentest product scan`. A key flagged restart-required still saves,
|
|
194
|
+
# but a visible warning says it only takes effect after the next restart.
|
|
195
|
+
# Setting a secret back to its own masked "<redacted>" value is rejected,
|
|
196
|
+
# so a `config get` / `config set` round trip can never silently
|
|
197
|
+
# overwrite a credential.
|
|
198
|
+
lumentest config unset KEY
|
|
199
|
+
# Resets KEY to its model default; for the free-form [env] and
|
|
200
|
+
# [test].fake_tools maps this removes the entry instead. A required key
|
|
201
|
+
# with no default (e.g. station.id) is rejected. A restart-required key
|
|
202
|
+
# carries the same warning `config set` gives — the reset is saved, but
|
|
203
|
+
# the running station keeps the old value until it restarts.
|
|
204
|
+
|
|
205
|
+
lumentest operator whoami [--output rich|json]
|
|
206
|
+
# Resolve the operator behind the stored token via GET /api/auth/whoami.
|
|
207
|
+
# Exits 1 if the token is missing, unknown, or expired.
|
|
208
|
+
|
|
209
|
+
lumentest operator stats [OPERATOR_ID] [--stations URL1,URL2,...] [--output rich|json]
|
|
210
|
+
# Per-operator statistics aggregated across stations (counters add,
|
|
211
|
+
# last_login = max). Omit OPERATOR_ID to list every operator seen.
|
|
212
|
+
# --stations defaults to the logged-in station.
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Machine-readable output
|
|
216
|
+
|
|
217
|
+
Every command above that takes `--output json` writes **exactly one JSON document
|
|
218
|
+
to stdout and nothing else**, so a caller can pipe it straight into a parser:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
lumentest product import --bundle --output json ./400-1011_A | jq -r .build_words
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Everything meant for a human — progress bars, warnings, "generated the
|
|
225
|
+
manifest" — goes to **stderr** in JSON mode, and errors always do. Redirect it
|
|
226
|
+
away with `2>/dev/null`, or keep it to watch a long import while still capturing
|
|
227
|
+
the result.
|
|
228
|
+
|
|
229
|
+
A command that finds nothing to report emits `null` rather than staying silent,
|
|
230
|
+
so stdout parses unconditionally.
|
|
231
|
+
|
|
232
|
+
`result logs --step IDX` is the one exception: it has no JSON form, so `--output`
|
|
233
|
+
is inert there and the step's captured streams go to stdout either way. Piping
|
|
234
|
+
that output works with the flag or without it.
|
|
235
|
+
|
|
236
|
+
In `--output rich` (the default) the human output goes to stdout as usual.
|
|
237
|
+
|
|
238
|
+
## Server URL
|
|
239
|
+
|
|
240
|
+
The CLI reads the server URL from (in order of priority):
|
|
241
|
+
|
|
242
|
+
1. `--base-url` flag on `lumentest login`
|
|
243
|
+
2. `LUMENTEST_URL` environment variable
|
|
244
|
+
3. Stored value in `~/.config/lumentest/login.json`
|
|
245
|
+
4. Default: `http://127.0.0.1:17080`
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# lr-lumentest-cli
|
|
2
|
+
|
|
3
|
+
CLI for the LumenRadio LumenTest production test station server.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install lr-lumentest-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Point the CLI at your station server and identify yourself by scanning
|
|
15
|
+
# your badge (the handheld scanner types the badge id at the prompt)
|
|
16
|
+
lumentest login --base-url http://10.0.0.1:17080 --badge-id LOP0000001
|
|
17
|
+
|
|
18
|
+
# Check server health and login state
|
|
19
|
+
lumentest status
|
|
20
|
+
|
|
21
|
+
# Scan and list imported products
|
|
22
|
+
lumentest product scan
|
|
23
|
+
lumentest product list
|
|
24
|
+
|
|
25
|
+
# Run a full test sequence interactively (prompts on ALERT steps)
|
|
26
|
+
lumentest test start --serial SN-00001
|
|
27
|
+
|
|
28
|
+
# Run a single step (for development / debugging)
|
|
29
|
+
lumentest test step production-test flash-firmware --serial SN-00001
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Command Reference
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
lumentest login [--base-url URL] --badge-id ID
|
|
36
|
+
# ID is the scanned QR badge; the server resolves it to your operator id.
|
|
37
|
+
lumentest logout
|
|
38
|
+
lumentest status [--output rich|json]
|
|
39
|
+
lumentest --version
|
|
40
|
+
|
|
41
|
+
lumentest product list [--output rich|json]
|
|
42
|
+
# Table includes a Build Words column — see doc/build-words.md. The manifest
|
|
43
|
+
# digest is not shown: read it from --output json when you need the digest.
|
|
44
|
+
lumentest product active
|
|
45
|
+
lumentest product set ARTICLE [REVISION]
|
|
46
|
+
lumentest product remove ARTICLE [REVISION] [--yes]
|
|
47
|
+
lumentest product scan [--rescan] [--output rich|json]
|
|
48
|
+
# Scans the station's artifact_cache/, registers every valid package, and
|
|
49
|
+
# reports each package's declared env variables (from parameters.toml) —
|
|
50
|
+
# the value a run will see, where it came from (config.toml's [env], the
|
|
51
|
+
# station's own environment, or the package default) and which are still
|
|
52
|
+
# unconfigured — alongside its prerequisites (the external tools its
|
|
53
|
+
# sequences need) against the station itself. Each unconfigured variable's
|
|
54
|
+
# line carries the exact `lumentest config set env.NAME <VALUE>` command to
|
|
55
|
+
# fix it; a set value applies to the running station immediately, so
|
|
56
|
+
# re-running scan is enough to confirm it, for a variable and for a tool
|
|
57
|
+
# newly installed on PATH alike — no restart needed either way. --output
|
|
58
|
+
# json emits the raw payload.
|
|
59
|
+
lumentest product import PATH [--update] [--bundle] [--output rich|json]
|
|
60
|
+
# PATH: directory or .zip/.tar.gz archive.
|
|
61
|
+
# --update: recompute SHA-256 checksums in artifact-manifest.json before
|
|
62
|
+
# uploading — useful during step development to skip manual hashing.
|
|
63
|
+
# --bundle: pack PATH into <PATH>.tar.gz (manifest + declared files only)
|
|
64
|
+
# next to it instead of uploading — for email/USB delivery;
|
|
65
|
+
# import the archive later with the same command. Requires a
|
|
66
|
+
# directory; passing an archive file just warns and exits.
|
|
67
|
+
# Prints the package's Build Words (doc/build-words.md) so a
|
|
68
|
+
# technician can read them off a locally built bundle without a
|
|
69
|
+
# running server; --output json carries them as "build_words".
|
|
70
|
+
# Reports the package's declared env variables the same way `product scan`
|
|
71
|
+
# does: the value a run will see, where it came from, and which still need
|
|
72
|
+
# a value. Fix an unconfigured one with the `lumentest config set` command
|
|
73
|
+
# printed on its line, then re-run `product scan` to confirm — same as
|
|
74
|
+
# confirming a newly installed prerequisite tool, neither needs a restart.
|
|
75
|
+
# Only artifact-manifest.json's declared files (and declared extra
|
|
76
|
+
# sequences) are packed and uploaded — the manifest is the contract for
|
|
77
|
+
# what the package needs. A package that needs a file its manifest does
|
|
78
|
+
# not declare must have that file added to the manifest, not bundled some
|
|
79
|
+
# other way.
|
|
80
|
+
# A directory import first checks with the station which files it already
|
|
81
|
+
# has (by digest, including across every other cached revision) — a
|
|
82
|
+
# retry after an interrupted upload resumes instead of re-sending
|
|
83
|
+
# everything. Only what's actually missing is uploaded, with a progress
|
|
84
|
+
# bar over just those bytes; the command then reports how many files were
|
|
85
|
+
# reused, e.g. "12 of 24 files already on the station (302 MB reused)".
|
|
86
|
+
# An existing .zip/.tar.gz archive still uploads as a single one-shot
|
|
87
|
+
# transfer. --output json moves all of the above to stderr so stdout
|
|
88
|
+
# carries nothing but the final JSON — see "Machine-readable output".
|
|
89
|
+
|
|
90
|
+
lumentest sequence list [--article ARTICLE] [--output rich|json]
|
|
91
|
+
lumentest sequence steps ARTICLE SEQUENCE
|
|
92
|
+
lumentest sequence selection get ARTICLE SEQUENCE
|
|
93
|
+
lumentest sequence selection set ARTICLE SEQUENCE --steps 1,2,5
|
|
94
|
+
lumentest sequence selection clear ARTICLE SEQUENCE
|
|
95
|
+
|
|
96
|
+
lumentest test start [--serial SN] [--article ARTICLE] [--sequence NAME]
|
|
97
|
+
# Blocks with an interactive Rich UI; handles ALERT prompts; exits with
|
|
98
|
+
# the run's terminal status: 0 PASS, 1 FAIL, 2 ABORTED, 3 ERROR (outcome
|
|
99
|
+
# undetermined — station unreachable or run gone). The operator comes
|
|
100
|
+
# from the bearer token established by `lumentest login`, not a flag.
|
|
101
|
+
# The run header shows the package's Build Words when the station reports
|
|
102
|
+
# them.
|
|
103
|
+
lumentest test step SEQUENCE STEP [--article ARTICLE] [--serial SN]
|
|
104
|
+
# Runs one step via the same interactive UI. STEP is a name or 0-based index.
|
|
105
|
+
lumentest test status [--output rich|json]
|
|
106
|
+
# One-shot snapshot of the currently active test run.
|
|
107
|
+
|
|
108
|
+
lumentest result list [--limit N] [--serial SN] [--output rich|json]
|
|
109
|
+
# --serial SN filters to runs for one device (exact dut_id match); the station
|
|
110
|
+
# filters server-side so high-throughput stations don't ship the full history.
|
|
111
|
+
lumentest result show [RUN_ID]
|
|
112
|
+
# RUN_ID is optional: omit it to show the most recent run.
|
|
113
|
+
lumentest result logs [RUN_ID] [--step IDX] [--stream stdout|stderr|traceback]
|
|
114
|
+
[--download DIR] [--output rich|json]
|
|
115
|
+
# RUN_ID is optional: omit it to fetch the most recent run's logs.
|
|
116
|
+
# Without --step: fetches the complete log bundle via GET /logs/all — run error,
|
|
117
|
+
# structured journal, and every step's stdout/stderr/traceback. --output json
|
|
118
|
+
# emits the raw JSON bundle; --download DIR writes the tree to DIR/<run_id>/
|
|
119
|
+
# (error.txt, log.jsonl, steps/<name>/{stdout,stderr,traceback}.txt, omitting
|
|
120
|
+
# empty files). --output json takes precedence when both flags are given.
|
|
121
|
+
# With --step IDX: shows that step's stdout, stderr, and traceback (or a single
|
|
122
|
+
# stream via --stream).
|
|
123
|
+
lumentest result export [RUN_ID] [--all] [--serial SN] [--limit N]
|
|
124
|
+
[--out DIR] [--output rich|json]
|
|
125
|
+
# Downloads one .tar.gz station snapshot via GET /api/results/export: the
|
|
126
|
+
# selected run(s) verbatim under results/ (run.json, qrm-payload.json, the
|
|
127
|
+
# journal, every step's captured streams) plus the station's own log,
|
|
128
|
+
# state.json, operator_stats.json and effective config under station/ —
|
|
129
|
+
# laid out exactly as the station stores them on disk. RUN_ID / --all /
|
|
130
|
+
# --serial / --limit govern results/ only; the station context is always
|
|
131
|
+
# included. Bare `result export` packs only the most recent run; --all
|
|
132
|
+
# opts into every retained run. RUN_ID is mutually exclusive with --all,
|
|
133
|
+
# --serial and --limit.
|
|
134
|
+
# --out DIR: directory to write the archive into (default: the current
|
|
135
|
+
# directory). The filename is stamped by the station itself from its own
|
|
136
|
+
# [station].id and a UTC timestamp, so an export stays identifiable once
|
|
137
|
+
# it is off the station.
|
|
138
|
+
# artifact_cache/ package binaries are never packed — represented instead by
|
|
139
|
+
# an inventory (article, revision, size, file count); Arena is the system
|
|
140
|
+
# of record for firmware. Re-send a run to QRM by hand with
|
|
141
|
+
# `qrm result upload <run>/qrm-payload.json` against the extracted tree.
|
|
142
|
+
# An export contains the station's QRM service password, session token
|
|
143
|
+
# hashes, operator identities, and whatever a step or tool printed. Treat
|
|
144
|
+
# an archive as a secret — see doc/troubleshooting.md § Collecting a
|
|
145
|
+
# station snapshot for support.
|
|
146
|
+
|
|
147
|
+
lumentest config list [--output rich|json]
|
|
148
|
+
# Flattens config.toml to dotted keys (station.id, env.NRF_TOOLS,
|
|
149
|
+
# timeouts.default_step_s, ...) so a technician can scan the whole
|
|
150
|
+
# effective configuration in one table. Secrets (qrm.password,
|
|
151
|
+
# serial.client_secret, user password hashes) show as "<redacted>" and are
|
|
152
|
+
# marked in the Notes column, alongside keys that need a station restart
|
|
153
|
+
# to take effect (station.host, station.port, debug.results_dir).
|
|
154
|
+
lumentest config get KEY [--output rich|json]
|
|
155
|
+
lumentest config set KEY VALUE [--json] [--output rich|json]
|
|
156
|
+
# VALUE is sent as a raw string and coerced through the server's pydantic
|
|
157
|
+
# validation (e.g. "90" -> the int 90); pass --json to send VALUE parsed
|
|
158
|
+
# as JSON instead, for list/dict/explicitly-typed values. This is how a
|
|
159
|
+
# newly required package env variable gets set without restarting the
|
|
160
|
+
# station: `lumentest config set env.SOME_VAR value` then
|
|
161
|
+
# `lumentest product scan`. A key flagged restart-required still saves,
|
|
162
|
+
# but a visible warning says it only takes effect after the next restart.
|
|
163
|
+
# Setting a secret back to its own masked "<redacted>" value is rejected,
|
|
164
|
+
# so a `config get` / `config set` round trip can never silently
|
|
165
|
+
# overwrite a credential.
|
|
166
|
+
lumentest config unset KEY
|
|
167
|
+
# Resets KEY to its model default; for the free-form [env] and
|
|
168
|
+
# [test].fake_tools maps this removes the entry instead. A required key
|
|
169
|
+
# with no default (e.g. station.id) is rejected. A restart-required key
|
|
170
|
+
# carries the same warning `config set` gives — the reset is saved, but
|
|
171
|
+
# the running station keeps the old value until it restarts.
|
|
172
|
+
|
|
173
|
+
lumentest operator whoami [--output rich|json]
|
|
174
|
+
# Resolve the operator behind the stored token via GET /api/auth/whoami.
|
|
175
|
+
# Exits 1 if the token is missing, unknown, or expired.
|
|
176
|
+
|
|
177
|
+
lumentest operator stats [OPERATOR_ID] [--stations URL1,URL2,...] [--output rich|json]
|
|
178
|
+
# Per-operator statistics aggregated across stations (counters add,
|
|
179
|
+
# last_login = max). Omit OPERATOR_ID to list every operator seen.
|
|
180
|
+
# --stations defaults to the logged-in station.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Machine-readable output
|
|
184
|
+
|
|
185
|
+
Every command above that takes `--output json` writes **exactly one JSON document
|
|
186
|
+
to stdout and nothing else**, so a caller can pipe it straight into a parser:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
lumentest product import --bundle --output json ./400-1011_A | jq -r .build_words
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Everything meant for a human — progress bars, warnings, "generated the
|
|
193
|
+
manifest" — goes to **stderr** in JSON mode, and errors always do. Redirect it
|
|
194
|
+
away with `2>/dev/null`, or keep it to watch a long import while still capturing
|
|
195
|
+
the result.
|
|
196
|
+
|
|
197
|
+
A command that finds nothing to report emits `null` rather than staying silent,
|
|
198
|
+
so stdout parses unconditionally.
|
|
199
|
+
|
|
200
|
+
`result logs --step IDX` is the one exception: it has no JSON form, so `--output`
|
|
201
|
+
is inert there and the step's captured streams go to stdout either way. Piping
|
|
202
|
+
that output works with the flag or without it.
|
|
203
|
+
|
|
204
|
+
In `--output rich` (the default) the human output goes to stdout as usual.
|
|
205
|
+
|
|
206
|
+
## Server URL
|
|
207
|
+
|
|
208
|
+
The CLI reads the server URL from (in order of priority):
|
|
209
|
+
|
|
210
|
+
1. `--base-url` flag on `lumentest login`
|
|
211
|
+
2. `LUMENTEST_URL` environment variable
|
|
212
|
+
3. Stored value in `~/.config/lumentest/login.json`
|
|
213
|
+
4. Default: `http://127.0.0.1:17080`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -*- mode: python ; coding: utf-8 -*-
|
|
2
|
+
from PyInstaller.utils.hooks import (
|
|
3
|
+
copy_metadata,
|
|
4
|
+
collect_data_files,
|
|
5
|
+
collect_submodules,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
a = Analysis(
|
|
9
|
+
["src/lumentest/__main__.py"],
|
|
10
|
+
pathex=[],
|
|
11
|
+
binaries=[],
|
|
12
|
+
datas=[
|
|
13
|
+
*copy_metadata("lr-lumentest-cli"),
|
|
14
|
+
*collect_data_files("rich"),
|
|
15
|
+
],
|
|
16
|
+
# rich.cells lazily import_module()s a Unicode-version-specific submodule
|
|
17
|
+
# (e.g. rich._unicode_data.unicode17-0-0) whose name is computed at runtime,
|
|
18
|
+
# so PyInstaller's static analysis can't discover it. Collect them all.
|
|
19
|
+
hiddenimports=[*collect_submodules("rich._unicode_data")],
|
|
20
|
+
hookspath=[],
|
|
21
|
+
hooksconfig={},
|
|
22
|
+
runtime_hooks=[],
|
|
23
|
+
excludes=[],
|
|
24
|
+
noarchive=False,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
pyz = PYZ(a.pure)
|
|
28
|
+
|
|
29
|
+
exe = EXE(
|
|
30
|
+
pyz,
|
|
31
|
+
a.scripts,
|
|
32
|
+
a.binaries,
|
|
33
|
+
a.datas,
|
|
34
|
+
[],
|
|
35
|
+
name="lumentest",
|
|
36
|
+
debug=False,
|
|
37
|
+
bootloader_ignore_signals=False,
|
|
38
|
+
strip=False,
|
|
39
|
+
upx=True,
|
|
40
|
+
upx_exclude=[],
|
|
41
|
+
runtime_tmpdir=None,
|
|
42
|
+
console=True,
|
|
43
|
+
disable_windowed_traceback=False,
|
|
44
|
+
argv_emulation=False,
|
|
45
|
+
target_arch=None,
|
|
46
|
+
codesign_identity=None,
|
|
47
|
+
entitlements_file=None,
|
|
48
|
+
)
|