plesty.server.cli.main ====================== .. py:module:: plesty.server.cli.main .. autoapi-nested-parse:: The ``plesty-server`` command group. Every command opens the :class:`~plesty.server.presenter.Bench` for the ``--home``/``-f`` given (or found) and calls one presenter method. Long work (install, update, field test) is started as a job and the job log is streamed unless ``--no-wait`` is given; the hidden ``_job`` group is what those jobs execute in the foreground. Attributes ---------- .. autoapisummary:: plesty.server.cli.main.pass_context plesty.server.cli.main.EXPECTED Classes ------- .. autoapisummary:: plesty.server.cli.main.Context Functions --------- .. autoapisummary:: plesty.server.cli.main.app plesty.server.cli.main._run plesty.server.cli.main._follow_job plesty.server.cli.main._finish_job plesty.server.cli.main.declare plesty.server.cli.main._parse_env plesty.server.cli.main.install plesty.server.cli.main.update plesty.server.cli.main.uninstall plesty.server.cli.main.module plesty.server.cli.main.module_install plesty.server.cli.main.module_list plesty.server.cli.main.list_devices plesty.server.cli.main.start plesty.server.cli.main.stop plesty.server.cli.main.restart plesty.server.cli.main.status plesty.server.cli.main.log plesty.server.cli.main.field_test plesty.server.cli.main._field_test_run plesty.server.cli.main.reports plesty.server.cli.main.jobs plesty.server.cli.main.jobs_list plesty.server.cli.main.jobs_log plesty.server.cli.main.jobs_cancel plesty.server.cli.main.fleet plesty.server.cli.main.fleet_init plesty.server.cli.main.fleet_up plesty.server.cli.main.fleet_down plesty.server.cli.main.fleet_run plesty.server.cli.main.fleet_status plesty.server.cli.main.agent plesty.server.cli.main.gui plesty.server.cli.main.job_group plesty.server.cli.main.job_install plesty.server.cli.main.job_module_install plesty.server.cli.main.job_update plesty.server.cli.main.job_field_test plesty.server.cli.main.launch_waiter plesty.server.cli.main._device_dict plesty.server.cli.main._report_dict plesty.server.cli.main._table plesty.server.cli.main._status_table plesty.server.cli.main._echo_status plesty.server.cli.main.main plesty.server.cli.main._printable_output plesty.server.cli.main.gui_main Module Contents --------------- .. py:class:: Context(home: str | None, fleet: str | None, quiet: bool) What every command receives: how to open the bench, and how loud to be. Remember the global options. .. py:attribute:: home_arg .. py:attribute:: fleet_arg .. py:attribute:: quiet .. py:attribute:: _bench :type: plesty.server.presenter.Bench | None :value: None .. py:method:: bench() -> plesty.server.presenter.Bench The bench (opened once per invocation). .. py:method:: say(line: str) -> None Progress to stderr unless ``--quiet``. .. py:data:: pass_context .. py:function:: app(ctx: click.Context, home_arg: str | None, fleet_arg: str | None, quiet: bool) -> None Install, launch and supervise PLESTY device servers on this bench. .. py:data:: EXPECTED .. py:function:: _run[T](ctx: Context, action: collections.abc.Callable[[], T]) -> T Call *action*, turning every expected failure into a one-line CLI error. .. py:function:: _follow_job(ctx: Context, job: plesty.server.model.Job) -> int Stream a job's log until it ends; returns its exit code. .. py:function:: _finish_job(ctx: Context, job: plesty.server.model.Job, wait: bool) -> None .. py:function:: declare(ctx: Context, name: str, package: str, version: str | None, git_url: str | None, ref: str | None, args: tuple[str, Ellipsis], env: tuple[str, Ellipsis], no_autostart: bool) -> None Add device NAME running PACKAGE to the fleet file. .. py:function:: _parse_env(pairs: tuple[str, Ellipsis]) -> dict[str, str] .. py:function:: install(ctx: Context, name: str, force: bool, no_wait: bool) -> None Install the environment NAME declares (as a job). .. py:function:: update(ctx: Context, name: str, ref: str | None, no_wait: bool) -> None Pull and re-sync (git) or reinstall (PyPI) the environment of NAME. .. py:function:: uninstall(ctx: Context, name: str) -> None Stop NAME and remove its environment (unless another device uses it). .. py:function:: module() -> None The device modules on this bench — what the fleet declares instances of. .. py:function:: module_install(ctx: Context, package: str, version: str | None, git_url: str | None, ref: str | None, force: bool, no_wait: bool) -> None Put PACKAGE on this bench (as a job); no device is declared. .. py:function:: module_list(ctx: Context, as_json: bool) -> None List the modules installed on this bench. .. py:function:: list_devices(ctx: Context, no_probe: bool, as_json: bool) -> None Show every declared device: source, installed version, state. .. py:function:: start(ctx: Context, name: str, no_wait: bool, timeout: float | None) -> None Start the device server NAME (installing first when needed). .. py:function:: stop(ctx: Context, name: str, timeout: float | None) -> None Stop the device server NAME. .. py:function:: restart(ctx: Context, name: str, no_wait: bool) -> None Stop (if running) and start the device server NAME. .. py:function:: status(ctx: Context, names: tuple[str, Ellipsis], no_probe: bool, as_json: bool) -> None Show the state of NAMES (default: every declared device). .. py:function:: log(ctx: Context, name: str, lines: int) -> None Print the tail of the server log of NAME. .. py:function:: field_test(ctx: Context, name: str, extra: tuple[str, Ellipsis], tier: str, address: str | None, gates: str | None, repetitions: int | None, keep_going: bool, keep_server: bool, no_wait: bool) -> None Run the field test of NAME on this bench (as a job). EXTRA goes to the script. .. py:function:: _field_test_run(tier: str, address: str | None, gates: str | None, repetitions: int | None, keep_going: bool, keep_server: bool, extra: tuple[str, Ellipsis]) -> plesty.server.model.FieldTestRun .. py:function:: reports(ctx: Context, name: str, as_json: bool) -> None List the published field-test reports of NAME. .. py:function:: jobs() -> None Long-running work on the bench: installs, updates, field tests. .. py:function:: jobs_list(ctx: Context, name: str | None, kind: str | None, as_json: bool) -> None List jobs, newest first. .. py:function:: jobs_log(ctx: Context, job_id: str, follow: bool, offset: int, as_json: bool) -> None Print the log of JOB_ID (from --offset; --json for a tailing client). .. py:function:: jobs_cancel(ctx: Context, job_id: str) -> None Kill a running job. .. py:function:: fleet() -> None Operate every device declared in fleet.yaml at once. .. py:function:: fleet_init(path: str, force: bool) -> None Write an annotated example fleet.yaml to PATH. .. py:function:: fleet_up(ctx: Context, names: tuple[str, Ellipsis], no_install: bool, no_wait: bool) -> None Install and start the autostart devices (or NAMES). .. py:function:: fleet_down(ctx: Context, names: tuple[str, Ellipsis]) -> None Stop the declared devices (or NAMES). .. py:function:: fleet_run(ctx: Context, names: tuple[str, Ellipsis], interval: float, with_agent: bool, bind: str | None, token: str | None, leave_running: bool, sweeps: int | None) -> None Bring the fleet up and keep it up until interrupted (headless bench mode). .. py:function:: fleet_status(ctx: Context, no_probe: bool) -> None Show the state of every declared device. .. py:function:: agent(ctx: Context, bind: str | None, token: str | None, workers: int, max_replies: int | None) -> None Serve plesty-bench clients: run plesty-server commands for them on this bench. .. py:function:: gui(ctx: Context, title: str | None) -> None Open the Qt console (needs the 'gui' extra). .. py:function:: job_group() -> None Foreground twins of the job commands (run by the launcher, not by people). .. py:function:: job_install(ctx: Context, name: str, force: bool) -> None Install NAME in the foreground. .. py:function:: job_module_install(ctx: Context, package: str, version: str | None, git_url: str | None, ref: str | None, force: bool) -> None Install the module PACKAGE in the foreground. .. py:function:: job_update(ctx: Context, name: str, ref: str | None) -> None Update NAME in the foreground. .. py:function:: job_field_test(ctx: Context, name: str, extra: tuple[str, Ellipsis], tier: str, address: str | None, gates: str | None, repetitions: int | None, keep_going: bool, keep_server: bool) -> None Run the field test of NAME in the foreground. .. py:function:: launch_waiter() -> None Run the detached launcher (spec as JSON on stdin); used by the PyInstaller bundle. .. py:function:: _device_dict(view: plesty.server.presenter.DeviceView) -> dict[str, object] .. py:function:: _report_dict(ctx: Context, report: plesty.server.model.FieldTestReport) -> dict[str, object] .. py:function:: _table(header: collections.abc.Sequence[str], rows: collections.abc.Sequence[collections.abc.Sequence[str]]) -> list[str] .. py:function:: _status_table(statuses: collections.abc.Sequence[plesty.server.model.ProcessStatus]) -> list[str] .. py:function:: _echo_status(status: plesty.server.model.ProcessStatus) -> None .. py:function:: main() -> None Console-script entry point. .. py:function:: _printable_output() -> None Never let the console's codepage turn output into a crash. A job log holds whatever the tools wrote — uv draws its resolution errors with box characters — and a Windows console is cp1252 by default, which cannot encode them. Echoing such a log raised UnicodeEncodeError and the operator got a traceback instead of the one-line error the log actually contained. A console keeps its own encoding and loses what it cannot draw: a ``?`` is a fair price for the message surviving. Anything redirected is a file this bench owns — a job log, read back later and sent to whoever is helping — so it is written as UTF-8 and keeps every character. .. py:function:: gui_main() -> None GUI-script entry point (``plesty-server-gui``): the console window, no terminal. Installed as a ``gui-scripts`` entry so Windows starts it with ``pythonw`` — no black console box behind the window. Arguments are the group's (``--home``, ``-f``); ``_launch``/``_job`` pass through for re-execution.