diff --git a/DESIGN.md b/DESIGN.md index 89a5cc9..6261ac6 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -265,14 +265,14 @@ The `testium_assist` editor extension is a thin LSP client that spawns `testium 1. **`pygls` (+ `lsprotocol`, `cattrs`, `attrs`, `typing_extensions`) must be bundled.** It is the pyproject `[lsp]` extra (kept optional so a plain `pip install testium` stays lean), wired into each full-app channel: `build_env.sh` installs it into the shared `test/tmp/.venv` (covers **source run** and the **PyInstaller** build env); the **AppImage** installs the wheel as `…whl[lsp]`; the **Flatpak** adds a `python3-lsp` pip module (network-at-build, consistent with the manifest's global `--share=network`); the **PyInstaller** `.spec` force-collects the submodules via `collect_submodules` + explicit `hiddenimports` (including the lazily-imported `lsp`, `lsp.server`, `lsp.schema`). 2. **The schema must build without source** — handled by the declarative `PARAMS`/`ACTIONS` above; PyInstaller is the only channel that strips `.py` source, and it no longer matters. -`test/validation/lsp_smoke.py` enforces both per channel: `run.sh` calls it before launching the suite, asserting that ` schema` returns JSON whose `console`/`plot`/`json_rpc` items still carry their actions, and that ` lsp` answers an `initialize` request with capabilities (and never reports the pygls dependency missing). So `./test/validation/run.sh --mode flatpak|pyinstaller|appimage` now fails loudly if a channel ships a broken or pygls-less language server. +`test/validation/lsp_check.py` enforces both per channel: `run.sh` calls it before launching the suite, asserting that ` schema` returns JSON whose `console`/`plot`/`json_rpc` items still carry their actions, and that ` lsp` answers an `initialize` request with capabilities (and never reports the pygls dependency missing). So `./test/validation/run.sh --mode flatpak|pyinstaller|appimage` now fails loudly if a channel ships a broken or pygls-less language server. ### Version reporting (`interpreter/utils/version.py`) Both Flatpak and AppImage export `TESTIUM_VERSION` from a launcher (Flatpak: launcher script in `org.testium.Testium.yaml`; AppImage: `runtime.env` in `AppImageBuilder.yml`). `get_testium_version()` checks `/.flatpak-info` / `APPIMAGE` and reads `TESTIUM_VERSION` rather than relying on package metadata or repo introspection. ## Recent fixes / notable changes -- LSP across packaging channels: `testium lsp` (and the `testium_assist` editor extension that spawns it) now works from source, wheel, PyInstaller, Flatpak and AppImage. Two enablers — (1) action items declare a class-level `ACTIONS = {key: class}` registry (like `PARAMS`), so `lsp/schema.py` builds the full schema from class attributes with no `inspect.getsource`/AST (which broke under frozen PyInstaller); (2) the `[lsp]` extra (pygls) is wired into every full-app channel. `test/validation/lsp_smoke.py`, run by `run.sh` before the suite, asserts per-channel that `schema` keeps its actions and `lsp` answers `initialize`. See the matching architecture sections. +- LSP across packaging channels: `testium lsp` (and the `testium_assist` editor extension that spawns it) now works from source, wheel, PyInstaller, Flatpak and AppImage. Two enablers — (1) action items declare a class-level `ACTIONS = {key: class}` registry (like `PARAMS`), so `lsp/schema.py` builds the full schema from class attributes with no `inspect.getsource`/AST (which broke under frozen PyInstaller); (2) the `[lsp]` extra (pygls) is wired into every full-app channel. `test/validation/lsp_check.py`, run by `run.sh` before the suite, asserts per-channel that `schema` keeps its actions and `lsp` answers `initialize`. See the matching architecture sections. - Declarative test item parameters (v0.2): each `TestItem` subclass exposes a `PARAMS = ParamSet(...)` class attribute consumed by the base `__init__`. Catches unknown YAML keys (typo warnings listing the accepted names) and missing required params (load-time errors with `.tum` context). Lays the schema foundation for a future LSP server and auto-generated manual sections. See the matching architecture section. - Flatpak: `py_func` / `lua_func` / `run` sub-instance now execute on the host via `flatpak-spawn --host`. The previous attempt to inject host lib dirs into the sandbox's `LD_LIBRARY_PATH` was abandoned — host shared libs are ABI-incompatible with the Flatpak runtime's glibc and would trip `_dl_call_libc_early_init`. The manifest gained `--talk-name=org.freedesktop.Flatpak` so the spawn proxy call is allowed. The testium package is staged once per process under `/tmp` (shared with the host) so the host interpreter can locate `py_func` / `lua_func`. - Validation suite: single entry point with `--mode source|wheel|pyinstaller|flatpak|appimage` to validate every packaging channel against the same items. Per-mode report filenames prevent clobbering. diff --git a/test/validation/lsp_smoke.py b/test/validation/lsp_check.py similarity index 91% rename from test/validation/lsp_smoke.py rename to test/validation/lsp_check.py index e96f872..74681a8 100644 --- a/test/validation/lsp_smoke.py +++ b/test/validation/lsp_check.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Per-channel smoke test for the testium language server. +"""Per-channel check of the testium language server. Given the channel's testium invocation as argv (e.g. ``flatpak run --command=testium org.testium.Testium``, a PyInstaller binary path, or @@ -25,7 +25,7 @@ EXPECTED_ACTION_PARENTS = ("console", "plot", "json_rpc") def fail(msg): - print(f"LSP SMOKE: FAIL — {msg}", file=sys.stderr) + print(f"LSP CHECK: FAIL — {msg}", file=sys.stderr) sys.exit(1) @@ -61,7 +61,7 @@ def check_schema(cmd): if not actions: fail(f"schema item '{parent}' has no actions — a frozen build lost " f"the declarative ACTIONS (item keys: {sorted(items)[:8]}…)") - print(f"LSP SMOKE: schema OK ({len(items)} items; actions present for " + print(f"LSP CHECK: schema OK ({len(items)} items; actions present for " f"{', '.join(EXPECTED_ACTION_PARENTS)})") @@ -86,16 +86,16 @@ def check_lsp(cmd): if b'"capabilities"' not in stdout: fail("`lsp` did not return an initialize result. " f"stdout[:200]={stdout[:200]!r} stderr[:200]={stderr[:200]!r}") - print("LSP SMOKE: lsp initialize OK (server answered with capabilities)") + print("LSP CHECK: lsp initialize OK (server answered with capabilities)") def main(): cmd = sys.argv[1:] if not cmd: - fail("usage: lsp_smoke.py ") + fail("usage: lsp_check.py ") check_schema(cmd) check_lsp(cmd) - print("LSP SMOKE: PASS") + print("LSP CHECK: PASS") if __name__ == "__main__": diff --git a/test/validation/run.sh b/test/validation/run.sh index b095656..bf50e85 100755 --- a/test/validation/run.sh +++ b/test/validation/run.sh @@ -137,12 +137,12 @@ esac echo "-- validation mode: $MODE" echo "-- launch: ${CMD[*]}" -# ---------- LSP smoke check (this exact channel) ------------------------------ +# ---------- LSP check (this exact channel) ------------------------------------ # Verify `testium lsp` / `testium schema` work in the build under test before # running the suite: schema must keep its nested actions (declarative ACTIONS, # survives frozen builds) and the language server must start (pygls bundled). -echo "-- LSP smoke check ($MODE)" -"$VENV_PYTHON" "$SCRIPT_DIR/lsp_smoke.py" "${CMD[@]}" +echo "-- LSP check ($MODE)" +"$VENV_PYTHON" "$SCRIPT_DIR/lsp_check.py" "${CMD[@]}" exec "${CMD[@]}" -b \ -d "python_bin=$VENV_PYTHON" \