plesty.server.view.dialogs
The console’s pop-up views: declare a device, run a field test, follow a job.
Each dialog collects an intent and turns it into a model object
(DeviceSpec, FieldTestRun); the window hands that to the
presenter. JobDialog is the one that renders as it goes: it tails a
job log through the presenter until the job ends.
Classes
A word-wrapped label that holds on to the height its text needs. |
|
Add (or edit) a device declaration. |
|
Configure a field-test run for one device. |
|
Follow one job: its log as it grows, its state, a cancel button. |
|
Help ▸ Report a problem: say what happened, read what goes with it. |
|
Help ▸ Check for updates…: the version installed, the newest one, and Update (#29). |
|
Edit → Device config…: the declaration and the |
|
Server ▸ Configure…: what this bench serves remote clients on. |
|
Server ▸ Benches…: the other benches this master shows and drives. |
|
Edit → Fleet file…: the fleet as YAML, validated before it is written. |
|
Hub → Browse…: the Hub's modules, put on this bench. |
Functions
|
A yes/no question; |
|
Show an error. |
|
The About box's text: what the console is, version, and details as a table. |
|
The About box, with the PLESTY mark: the version, and details about it (#29). |
Module Contents
- class plesty.server.view.dialogs.WrapLabel(text: str = '')
Bases:
PySide6.QtWidgets.QLabelA word-wrapped label that holds on to the height its text needs.
minimumSizeHintis asked for without a width, so a wrapped label answers with the single line its text would take unwrapped. Every extra line the wrap actually adds is therefore missing from the dialog’s minimum height, andQFormLayoutmakes up the shortfall out of the rows below — which is how the working fleet checkbox came to be drawn inside the Env editor once the project link wrapped.Taking the wrapped height as the minimum makes the dialog grow to fit instead of compressing what is under the label. The height is re-taken whenever the width changes or the text does, since either can change how many lines the text needs.
A label showing text, word-wrapped.
- Parameters:
text (str)
- _take_height() None
Claim the height this text needs at the current width.
- Return type:
None
- resizeEvent(event: Any) None
Re-take the height for the width just assigned.
- Parameters:
event (Any)
- Return type:
None
- setText(text: str) None
Show text, and re-take the height it needs.
- Parameters:
text (str)
- Return type:
None
- class plesty.server.view.dialogs.DeclareDialog(parent: PySide6.QtWidgets.QWidget | None = None, spec: plesty.server.model.DeviceSpec | None = None, options: plesty.server.presenter.SourceOptions | None = None, packages: tuple[str, Ellipsis] = (), options_for: collections.abc.Callable[[str], plesty.server.presenter.SourceOptions] | None = None, info_for: collections.abc.Callable[[str], Any] | None = None, fetch_for: collections.abc.Callable[[str], plesty.server.presenter.SourceOptions] | None = None, worker: Any = None)
Bases:
PySide6.QtWidgets.QDialogAdd (or edit) a device declaration.
The source is one of two, never both: a release (PyPI, pinned to a version or the newest) or a repository (git URL at a ref). The version and ref fields are editable drop-downs filled from what the bench knows (
SourceOptions); anything else can be typed.Build the form.
- Parameters:
parent (PySide6.QtWidgets.QWidget | None) – Qt parent.
spec (plesty.server.model.DeviceSpec | None) – The declaration to edit;
Nonedeclares a new device.options (plesty.server.presenter.SourceOptions | None) – Drop-down contents for the (initial) package.
packages (tuple[str, Ellipsis]) – Installed modules a new device may be declared from — the only choices; the catalogue installs new ones.
options_for (collections.abc.Callable[[str], plesty.server.presenter.SourceOptions] | None) – Returns the drop-down contents for a package, called when the user picks another one.
info_for (collections.abc.Callable[[str], Any] | None) – Returns the package-level record (repository, latest release) shown read-only under the package.
fetch_for (collections.abc.Callable[[str], plesty.server.presenter.SourceOptions] | None) – Like options_for, but asks PyPI and the repository for every release and tag; run on worker when the user picks another package, and the drop-downs refilled from it.
worker (Any) – Runs fetch_for off the GUI thread.
- _options_for = None
- _info_for = None
- _fetch_for = None
- _worker = None
- name
- _proposed
- _name_before
- package
- release_radio
- repo_radio
- _source_group
- version
- git
- ref
- args
- env
- autostart
- project
- hint
- error
- _spec: plesty.server.model.DeviceSpec | None = None
- property repository_mode: bool
Whether the repository source is selected (else the release).
- Return type:
bool
- property package_name: str
The package the declaration names.
- Return type:
str
- show_project(info: Any) None
Show the package’s project page and latest release (a
PackageInfo).- Parameters:
info (Any)
- Return type:
None
- _name_changed(text: str) None
Say what the rename will do, while the new name is still being typed.
- Parameters:
text (str)
- Return type:
None
- _package_changed(package: str) None
Refill the version/ref/url drop-downs (and the project line) for another package.
- Parameters:
package (str)
- Return type:
None
- _fill(options: plesty.server.presenter.SourceOptions, keep: bool = False) None
Refill the version/ref/url drop-downs; keep what was already entered in them.
- Parameters:
options (plesty.server.presenter.SourceOptions)
keep (bool)
- Return type:
None
- _source_changed(*_args: object) None
- Parameters:
_args (object)
- Return type:
None
- to_spec() plesty.server.model.DeviceSpec
The declaration the form describes.
- Raises:
FleetError – When a field is malformed.
- Return type:
- property spec: plesty.server.model.DeviceSpec | None
The accepted declaration, or
Nonewhen cancelled.- Return type:
- _accept() None
- Return type:
None
- class plesty.server.view.dialogs.FieldTestDialog(name: str, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QDialogConfigure a field-test run for one device.
The gates are the standard plesty-lib field-test gates as check boxes (all checked = the script’s default: run everything); a script’s own
--helpmay narrow the list once the window has fetched it.Build the form for device name.
- Parameters:
name (str)
parent (PySide6.QtWidgets.QWidget | None)
- tier
- address
- gate_boxes: dict[str, PySide6.QtWidgets.QCheckBox]
- gates_box
- _gates_layout
- repetitions
- keep_going
- keep_server
- extra
- options_label
- error
- _run: plesty.server.model.FieldTestRun | None = None
- _set_gates(gates: list[str]) None
Rebuild the gate check boxes (all checked).
- Parameters:
gates (list[str])
- Return type:
None
- show_options(info: dict[str, list[str]]) None
Show what the device’s script accepts (fetched by the window off the GUI thread).
- Parameters:
info (dict[str, list[str]])
- Return type:
None
- property selected_gates: tuple[str, Ellipsis] | None
The checked gates in order, or
Nonewhen all are checked (= run everything).- Return type:
tuple[str, Ellipsis] | None
- to_run() plesty.server.model.FieldTestRun
The request the form describes.
- Raises:
FleetError – When a field is malformed (e.g. no gate checked).
- Return type:
- property run: plesty.server.model.FieldTestRun | None
The accepted request, or
Nonewhen cancelled.- Return type:
- _accept() None
- Return type:
None
- class plesty.server.view.dialogs.JobDialog(bench: plesty.server.presenter.Bench, job: plesty.server.model.Job, parent: PySide6.QtWidgets.QWidget | None = None, poll_ms: int = 400, on_finished: collections.abc.Callable[[plesty.server.model.Job], None] | None = None)
Bases:
PySide6.QtWidgets.QDialogFollow one job: its log as it grows, its state, a cancel button.
Start tailing job through bench.
- Parameters:
bench (plesty.server.presenter.Bench) – The presenter.
job (plesty.server.model.Job) – The job to follow.
parent (PySide6.QtWidgets.QWidget | None) – Qt parent.
poll_ms (int) – Tail interval.
on_finished (collections.abc.Callable[[plesty.server.model.Job], None] | None) – Called once, on the GUI thread, when the job ends.
- bench
- job
- _offset = 0
- _on_finished = None
- _finished = False
- state
- log
- cancel_button
- close_button
- _timer
- poll() None
Read new log text and the job state; stop polling when it ended.
- Return type:
None
- _cancel() None
- Return type:
None
- plesty.server.view.dialogs.confirm(parent: PySide6.QtWidgets.QWidget | None, title: str, text: str) bool
A yes/no question;
Truewhen confirmed.- Parameters:
parent (PySide6.QtWidgets.QWidget | None)
title (str)
text (str)
- Return type:
bool
- plesty.server.view.dialogs.alert(parent: PySide6.QtWidgets.QWidget | None, title: str, text: str) None
Show an error.
- Parameters:
parent (PySide6.QtWidgets.QWidget | None)
title (str)
text (str)
- Return type:
None
- class plesty.server.view.dialogs.ProblemReportDialog(parent: PySide6.QtWidgets.QWidget | None, bench: plesty.server.presenter.Bench)
Bases:
PySide6.QtWidgets.QDialogHelp ▸ Report a problem: say what happened, read what goes with it.
The report is shown in full and stays editable, because “reviews what is sent” is only true if what is shown is what is sent and the operator can take something out of it. Typing in the description rebuilds the report around it, so the two never disagree.
The bench files nothing. It holds no credential that could write to the tracker, and giving it one so it could would put a token on every lab machine for the sake of a convenience. Instead the report goes on the clipboard or into a file, and Open tracker opens the project’s own new-issue page in the operator’s browser, signed in as themselves.
Gather the report and show it beside the description.
- Parameters:
parent (PySide6.QtWidgets.QWidget | None) – The window this belongs to.
bench (plesty.server.presenter.Bench) – The bench to describe.
- PROJECT = 'https://gitlab.com/plesty/core/plesty-bench'
- bench
- title
- what
- body
- copy_button
- save_button
- open_button
- said
- _rebuild() None
Rebuild the report around the description as it is typed.
- Return type:
None
- payload() str
What would be sent: the body as it stands, edits included.
- Return type:
str
- _issue_title() str
The title, or a usable stand-in when none was typed.
- Return type:
str
- _copy() None
Put the report on the clipboard.
- Return type:
None
- _save() None
Write the report to a file the operator picks.
- Return type:
None
- _open_tracker() None
Copy the report, then open the tracker’s new-issue page.
Both, and in that order: a report longer than a query string will not fit in the URL, so the clipboard is what actually carries it and the page is opened with the title filled in and a line saying to paste.
- Return type:
None
- plesty.server.view.dialogs.about_text(version: str, details: collections.abc.Sequence[tuple[str, str]] = ()) str
The About box’s text: what the console is, version, and details as a table.
The changelog link goes to the one released with version, so it reads as this version’s changes; a version that is not a release (a checkout) links to the changelog of the integration line.
- Parameters:
version (str)
details (collections.abc.Sequence[tuple[str, str]])
- Return type:
str
- plesty.server.view.dialogs.about(parent: PySide6.QtWidgets.QWidget | None, version: str, details: collections.abc.Sequence[tuple[str, str]] = ()) None
The About box, with the PLESTY mark: the version, and details about it (#29).
- Parameters:
parent (PySide6.QtWidgets.QWidget | None)
version (str)
details (collections.abc.Sequence[tuple[str, str]])
- Return type:
None
- class plesty.server.view.dialogs.UpdateDialog(parent: PySide6.QtWidgets.QWidget | None, installed: str, can_update: bool, cannot: str = '')
Bases:
PySide6.QtWidgets.QDialogHelp ▸ Check for updates…: the version installed, the newest one, and Update (#29).
It opens at once on the installed version and asks PyPI for the newest in the background (
show_latest()). Update is enabled once there is a newer release and this console is an install that can replace itself — the Windows installer’s, or auv toolone; a source checkout is told why not. Accepting the dialog is asking for the update: the window then closes and hands it to the helper.Build the dialog.
- Parameters:
parent (PySide6.QtWidgets.QWidget | None) – The window it belongs to.
installed (str) – The version running.
can_update (bool) – Whether this console can install a newer one itself.
cannot (str) – Why it cannot, said when a newer one is found.
- installed
- can_update
- cannot = ''
- chosen: str | None = None
- latest
- note
- buttons
- update_button
- show_latest(latest: str, newer: bool) None
Say what the newest release is, and offer it when it is newer than the installed one.
- Parameters:
latest (str)
newer (bool)
- Return type:
None
- show_error(message: str) None
Say why the newest release could not be read.
- Parameters:
message (str)
- Return type:
None
- class plesty.server.view.dialogs.DeviceConfigDialog(bench: plesty.server.presenter.Bench, name: str, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QDialogEdit → Device config…: the declaration and the
.envfile of one device, tabbed.Build the dialog for device name on bench.
- Parameters:
bench (plesty.server.presenter.Bench)
name (str)
parent (PySide6.QtWidgets.QWidget | None)
- bench
- name
- declare
- env
- env_highlighter
- tabs
- error
- _save() None
- Return type:
None
- class plesty.server.view.dialogs.AgentDialog(bench: plesty.server.presenter.Bench, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QDialogServer ▸ Configure…: what this bench serves remote clients on.
A bench with the console open looks up and healthy while a
plesty-benchclient times out against it, because nothing has started the agent — it could only be started from a command line. This is where the endpoint, the token and the worker count are set, and the settings are kept in the bench home so the next start uses them.The token travels by hand: it is generated here, copied, and pasted into the client machine’s
PLESTY_BENCH_TOKEN(orBenchClient(token=…)). An empty token is legal and reads as what it is — no check at all.Show the agent settings of bench.
- Parameters:
bench (plesty.server.presenter.Bench)
parent (PySide6.QtWidgets.QWidget | None)
- bench
- bind
- token
- workers
- role
- show_token
- copy_button
- data_folder
- check_updates
- error
- saved: Any = None
- to_settings() Any
The settings the form describes.
- Raises:
FleetError – When they would not bind.
- Return type:
Any
- Return type:
None
- _show_token_changed(shown: bool) None
- Parameters:
shown (bool)
- Return type:
None
- _generate() None
- Return type:
None
- _copy() None
- Return type:
None
- _save() None
- Return type:
None
- class plesty.server.view.dialogs.PeersDialog(bench: plesty.server.presenter.Bench, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QDialogServer ▸ Benches…: the other benches this master shows and drives.
A row per bench: what to call it, where its agent listens, and the secret that agent checks. The name is this console’s — it labels the Host column and the control panels — so it is what an operator calls the rig rather than whatever the machine calls itself.
The tokens are the nodes’ own, written to
peers.yamlreadable by its owner alone. They are shown masked for the same reason the agent’s is: a console is open on a bench in a shared room.Show the node list of bench.
- Parameters:
bench (plesty.server.presenter.Bench)
parent (PySide6.QtWidgets.QWidget | None)
- bench
- editor
- table
- error
- saved: Any = None
- _add_row() None
- Return type:
None
- _remove_row() None
- Return type:
None
- to_peers() Any
The benches the table describes; see
BenchesEditor.to_peers().- Return type:
Any
- _save() None
- Return type:
None
- class plesty.server.view.dialogs.FleetFileDialog(bench: plesty.server.presenter.Bench, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QDialogEdit → Fleet file…: the fleet as YAML, validated before it is written.
Show the current fleet text of bench.
- Parameters:
bench (plesty.server.presenter.Bench)
parent (PySide6.QtWidgets.QWidget | None)
- bench
- editor
- error
- _save() None
- Return type:
None
- class plesty.server.view.dialogs.CatalogueDialog(bench: plesty.server.presenter.Bench, parent: PySide6.QtWidgets.QWidget | None = None, worker: Any = None)
Bases:
PySide6.QtWidgets.QDialogHub → Browse…: the Hub’s modules, put on this bench.
A market place, and nothing more: installing from it stocks the bench with a module. No device is declared and no fleet file is touched — Edit ▸ Add device… does that, choosing from what the bench holds.
The source is the one the bench can carry out: a release from PyPI, which needs only
uv, or the repository at a ref, which needs git. Which of the two a module offers is what PyPI is asked on selection.Build the dialog; the catalogue is fetched on
load().- Parameters:
bench (plesty.server.presenter.Bench) – The presenter.
parent (PySide6.QtWidgets.QWidget | None) – Qt parent.
worker (Any) – Runs the PyPI lookup off the GUI thread; without one it is done in place (tests).
- bench
- _entries: list[Any] = []
- _shown: list[Any] = []
- _releases: dict[str, tuple[tuple[str, Ellipsis], tuple[str, Ellipsis]]]
- _worker = None
- _item_type
- query
- kind
- vendor
- refresh_button
- table
- release_radio
- repo_radio
- _source_group
- version
- ref
- source_note
- install_button
- status
- error
- selected_entry: Any = None
- started_job: plesty.server.model.Job | None = None
- reload(refresh: bool = False) None
Fetch the catalogue and show it; refresh asks the hub rather than the cache.
The fetch runs on the worker when the dialog was given one, so the window stays answerable while the hub is slow. A fetch that fails reports and leaves the table as it is: an unreachable hub should not cost the operator the list they are already reading.
- Parameters:
refresh (bool)
- Return type:
None
- load(entries: list[Any]) None
Show entries (fetched by the caller, off the GUI thread).
- Parameters:
entries (list[Any])
- Return type:
None
- apply_filter() None
Repaint the table for the current query and vendor.
- Return type:
None
- _on_bench(package: str) str
What this bench already holds of package: versions and refs, or
—.- Parameters:
package (str)
- Return type:
str
- _selection_changed() None
- Return type:
None
- _ask_pypi(entry: Any) None
Look up every release and tag of entry, off the GUI thread when it can.
- Parameters:
entry (Any)
- Return type:
None
- _show_source(entry: Any, releases: tuple[str, Ellipsis], tags: tuple[str, Ellipsis]) None
Offer every release and tag, select the source the bench can carry out, say why.
- Parameters:
entry (Any)
releases (tuple[str, Ellipsis])
tags (tuple[str, Ellipsis])
- Return type:
None
- _source_changed() None
- Return type:
None
- _install() None
- Return type:
None