plesty.server.model
Model layer: fleet configuration, device catalogue, installer and supervisor state.
Pure Python — no Qt imports. Everything the presenter needs to know about the bench lives here and is testable without a display.
Submodules
- plesty.server.model.agent
- plesty.server.model.catalogue
- plesty.server.model.device
- plesty.server.model.device_manager
- plesty.server.model.envfile
- plesty.server.model.errors
- plesty.server.model.experiment
- plesty.server.model.field_test
- plesty.server.model.fleet
- plesty.server.model.home
- plesty.server.model.job
- plesty.server.model.peer
- plesty.server.model.ports
- plesty.server.model.process
- plesty.server.model.purge
- plesty.server.model.traffic
- plesty.server.model.yaml_edit
Attributes
Exceptions
Raised when a module's manifest cannot be read or makes no sense. |
|
An installed-version record is missing or inconsistent. |
|
A fleet file or device declaration is malformed. |
|
A field test cannot be set up as asked. |
|
A job record does not exist or cannot be read. |
Classes
How the bench agent binds, whom it answers, and whether it drives others. |
|
One module of the hub catalogue. |
|
One device server as the fleet declares it. |
|
What a module answered when asked what it takes. |
|
One experiment as the fleet declares it. |
|
One configuration parameter the module declares. |
|
The installed-module inventory under a |
|
All installed versions of one device module. |
|
One version of one device module present on the bench. |
|
What the bench knows about a module as a project — independent of any install. |
|
What a field test published — the summary a bench needs, not the whole document. |
|
One field-test request. |
|
One gate of a published report. |
|
A parsed fleet file. |
|
Layout of the plesty-server home directory. |
|
One unit of long-running work. |
|
Job records and logs under a |
|
One bench this master drives. |
|
What the supervisor persists about a started server. |
|
The observed state of one device server. |
|
One served request, as the server reported it. |
Functions
|
Return share and folder, having made sure the bench can write in the folder. |
|
The agent settings of home, defaults when it has none. |
|
Write settings to home; returns the path. |
|
Where home keeps the agent settings. |
|
Every entry of a |
|
Raise |
|
The import path served by |
|
Parse dotenv text into a mapping (later keys win). |
|
Parse the file at path; empty when it does not exist. |
|
Render a mapping as dotenv text (one |
|
The tier's script inside checkout, or |
|
Every published field-test report under |
|
The gate names a script's |
|
The long options an argparse |
|
Locate the fleet file a command should consult. |
|
Read and validate a fleet file. |
|
Write a fleet file. |
|
The home directory the environment or the packaged config designates. |
|
The last lines lines of path, read from at most its last limit bytes. |
|
The nodes home declares, empty when it declares none. |
|
Every peer of a |
|
Where home keeps the node list. |
|
Write peers to home; returns the path. |
|
The lowest free port from base up, skipping taken and the agent's. |
|
Whether args or env name the port themselves. |
|
Resolve the TCP port a server binds from its args and environment. |
|
Whether port can actually be bound right now. |
|
Whether something accepts TCP connections on port right now. |
|
Every traffic record in text, oldest first. |
Package Contents
- plesty.server.model.DATA_PATH_VAR = 'DEVICE_DATA_PATH'
- plesty.server.model.DATA_ROOT_VAR = 'DEVICE_DATA_ROOT'
- plesty.server.model.DATA_SHARE_VAR = 'PLESTY_DATA'
- plesty.server.model.DEFAULT_DATA_DIR = 'tmp'
- plesty.server.model.DEFAULT_WORKERS = 4
- plesty.server.model.ROLE_MASTER = 'master'
- plesty.server.model.ROLE_NODE = 'node'
- plesty.server.model.ROLES
- class plesty.server.model.AgentSettings
How the bench agent binds, whom it answers, and whether it drives others.
- Variables:
bind – ZMQ endpoint to bind.
token – Shared secret every
exec/fetchmust carry. Empty is legal and means no check — a bench on a network already trusted.workers – Requests served concurrently.
role –
masterto drive other benches,nodeto serve only this one. One master to a group and no chaining, so the benches of a lab form a star: seeis_master.data_share – The Plesty share — the lab’s shared disk — as this machine mounts it (
Z:/xyz/plesty,/Volumes/plesty). Empty until set.data_folder – This bench’s folder in the share, relative to it (
platform-a, any depth); empty for the share itself.check_updates – Whether the console asks PyPI for a newer bench when it starts, at most once a day (#39).
- bind: str = 'tcp://*:5550'
- token: str = ''
- workers: int = 4
- role: str = 'node'
- data_folder: str = ''
- check_updates: bool = True
- property data_root: str
its folder in the share, where every device it starts writes.
Empty while no share is set.
- Type:
The bench data path
- Return type:
str
- property guarded: bool
Whether a token is checked (never the token itself).
- Return type:
bool
- property is_master: bool
Whether this bench declares nodes and drives their devices.
A configuration convention rather than a permission: the agent checks one shared secret and knows no caller identity, so a node’s token drives that node whoever holds it, and nothing here stops a second bench from declaring itself master of the same nodes. What the role decides is what this console does — a node keeps no peer list and offers nothing remote.
- Return type:
bool
- validate() AgentSettings
Return self, having refused settings the agent could not bind.
- Raises:
FleetError – When the endpoint is empty or the worker count is not a positive number.
- Return type:
- to_mapping() dict[str, Any]
The document written to
agent.yaml.- Return type:
dict[str, Any]
- classmethod from_mapping(raw: Any) AgentSettings
Read a document, falling back to the defaults key by key.
A settings file nobody can parse must not stop the console from opening: what is unreadable is replaced by its default rather than raised, since the operator can see and fix every value in the dialog.
- Parameters:
raw (Any)
- Return type:
- with_new_token() AgentSettings
These settings with a freshly generated token.
- Return type:
- device_data_env(name: str, data_dir: str | None, fallback: pathlib.Path | None = None) dict[str, str]
Where a device the bench starts may write, and where it writes by default.
- Parameters:
name (str) – The device, whose own folder under
tmpis its default.data_dir (str | None) – Its folder under the bench data path, as its declaration names it;
Nonefortmp/<name>.fallback (pathlib.Path | None) – Where it writes while the bench has no share — a folder of the bench’s own (#43). A device that must have a data path otherwise refused to start on a bench alone.
- Returns:
DEVICE_DATA_ROOT,DEVICE_DATA_PATHandPLESTY_DATA— the share, which the device reports its folders relative to. Without a share, the first two under fallback and noPLESTY_DATA; nothing when there is no fallback either.- Return type:
dict[str, str]
- run_data_env() dict[str, str]
PLESTY_DATAfor a run the bench starts: where it reads its devices’ files.- Return type:
dict[str, str]
- plesty.server.model.check_data_location(share: str, folder: str) tuple[str, str]
Return share and folder, having made sure the bench can write in the folder.
An empty share is legal and means unset. Otherwise the share is an absolute path to an existing folder — a relative one would follow whatever directory a server happens to start in — and the bench’s folder is a path inside it, created when missing.
- Returns:
The share, and the folder as
a/b(empty for the share itself).- Raises:
FleetError – Naming why the bench cannot write there.
- Parameters:
share (str)
folder (str)
- Return type:
tuple[str, str]
- plesty.server.model.load_agent_settings(home: plesty.server.model.home.Home) AgentSettings
The agent settings of home, defaults when it has none.
- Parameters:
- Return type:
- plesty.server.model.save_agent_settings(home: plesty.server.model.home.Home, settings: AgentSettings) pathlib.Path
Write settings to home; returns the path.
The file holds a shared secret, so it is made readable by its owner alone. Windows ignores the mode — there the bench home’s own ACL is the guard — which is why the token is a bench-network secret and not a credential.
- Raises:
FleetError – When the settings would not bind (see
AgentSettings.validate()).- Parameters:
settings (AgentSettings)
- Return type:
pathlib.Path
- plesty.server.model.settings_file(home: plesty.server.model.home.Home) pathlib.Path
Where home keeps the agent settings.
- Parameters:
- Return type:
pathlib.Path
- plesty.server.model.DEFAULT_INDEX_URL = 'https://hub.plesty.net/api/modules/'
- plesty.server.model.INSTALLABLE_CATEGORIES = ('devices', 'experiments')
- plesty.server.model.REQUIRED_STANDARD = 'quantum'
- class plesty.server.model.CatalogueEntry
One module of the hub catalogue.
- Variables:
name – Distribution name (
plesty-pm100d).slug – Project slug.
namespace – GitLab path (
plesty/hub/devices/thorlab/pm100d).description – One line.
category –
devices,analyzersorexperiments.vendor – Vendor group for devices (
thorlab), else empty.repo_url – Clone URL — what a git install uses.
web_url – Project page.
version – Latest release version, or empty.
latest_tag – Latest tag (
v0.2.1), or empty.standard – Compliance standard the module pins (
quantum), or empty.checked – Whether a
plesty checkreport is published.gates_ok – Whether that report passed.
gates_passed – Gates passed in it.
gates_failed – Gates failed in it.
field_tests – Number of published field-test reports.
sdk_version – The plesty-sdk that report was made with, or empty.
- name: str
- slug: str = ''
- namespace: str = ''
- description: str = ''
- category: str = ''
- vendor: str = ''
- repo_url: str = ''
- web_url: str = ''
- version: str = ''
- latest_tag: str = ''
- standard: str = ''
- checked: bool = False
- gates_ok: bool = False
- gates_passed: int = 0
- gates_failed: int = 0
- field_tests: int = 0
- sdk_version: str = ''
- property publishes_manifest: bool
Whether the module is shown to answer
--manifest; true of any non-experiment.Shown by its published check: passed, on a plesty-sdk that has the Experiment Manifest gate (
MANIFEST_SDK).- Return type:
bool
- property installable: bool
a device or experiment at the standard, with a repository.
The standard is the gate, not the category: what a bench installs it also runs, and a module that has not met the standard has not shown that it can be. A module the hub lists without one is not offered here until its registry entry says it reached it. An experiment must also publish its manifest (
publishes_manifest): one that does not installs, and then cannot be configured.- Type:
Whether the bench offers it
- Return type:
bool
- property ref: str | None
the latest tag, else the default branch.
- Type:
The git ref a fresh install checks out
- Return type:
str | None
- property quality: str
ok,failing,unchecked.- Type:
One word for listings
- Return type:
str
- matches(query: str) bool
Case-insensitive substring match on name, slug, vendor and description.
- Parameters:
query (str)
- Return type:
bool
- classmethod from_registry(raw: collections.abc.Mapping[str, Any]) CatalogueEntry
Build from one element of the registry’s
moduleslist.- Parameters:
raw (collections.abc.Mapping[str, Any])
- Return type:
- plesty.server.model.parse_catalogue(document: Any) list[CatalogueEntry]
Every entry of a
/api/modules/document (a mapping withmodulesor a bare list).- Parameters:
document (Any)
- Return type:
list[CatalogueEntry]
- class plesty.server.model.DeviceSpec
One device server as the fleet declares it.
- Variables:
name – Instance name — the venv, log and state key; unique per bench.
package – PyPI distribution of the device module.
version – Pinned release, or
Nonefor the newest one at install time.git – Repository URL to install from instead of PyPI, or
None.ref – Branch, tag or commit for a git source;
None=v<version>when a version is given, else the default branch.module – Import path served with
python -m; derived from package.args – Arguments appended to
python -m <module>.env – Environment set for the server process on top of the bench’s own.
port – TCP port the server binds; probed for liveness.
autostart – Whether
fleet up/fleet runstart it.host_name – The bench the server runs on, as an experiment’s
setup.yamlnames it; the run’s<DEVICE>_ADDRESSis built from that bench and the port (plesty.lib.experiment.setup).path – A local repository to run instead of an install — the folder Hub ▸ Load from… loaded. Only a declaration naming it runs it.
data_dir – Where the device writes, relative to its bench’s data path (Server ▸ Configure…) —
pol-plfor a spectrometer saving frames there. Started by the bench, the device is given that folder asDEVICE_DATA_PATH;Nonegives ittmp/<name>. Never absolute and never above the data path.
- name: str
- package: str
- version: str | None = None
- git: str | None = None
- ref: str | None = None
- module: str = ''
- args: tuple[str, Ellipsis] = ()
- env: collections.abc.Mapping[str, str]
- port: int = 0
- autostart: bool = True
- host_name: str | None = None
- path: str | None = None
- data_dir: str | None = None
- __post_init__() None
Fill the derived fields and validate the declaration.
- Return type:
None
- property port_is_explicit: bool
Whether this device asked for its port rather than taking the default.
True once the bench has allocated one and written it down, so the port a client connected to yesterday is the port it finds today.
- Return type:
bool
- property launch_args: tuple[str, Ellipsis]
The arguments
python -m <module>is started with.portis what the supervisor probes; unless the args already name a port, it is also handed to the server as--tcp-port, so what is probed and what is bound cannot drift. An environment value (*_TCP_PORT— often5555straight from a module’s.env.example) is deliberately not trusted here: an explicit flag beats the environment in every hub module, and the bench owns the ports.- Return type:
tuple[str, Ellipsis]
- property git_ref: str | None
The ref a git install checks out (
ref, elsev<version>, elseNone).- Return type:
str | None
- property requirement: str
The pip requirement string.
plesty-pm100d==0.2.1for a PyPI source;plesty-pm100d @ git+<url>@v0.2.1for a git source.- Return type:
str
- classmethod from_mapping(name: str, raw: collections.abc.Mapping[str, Any]) DeviceSpec
Build a spec from one
devices:entry of a fleet file.- Parameters:
name (str) – The mapping key.
raw (collections.abc.Mapping[str, Any]) – The entry’s fields.
- Raises:
FleetError – On unknown keys or wrong value types.
- Return type:
- to_mapping() dict[str, Any]
The fleet-file form of this spec (derived defaults omitted).
- Return type:
dict[str, Any]
- plesty.server.model.check_name(name: str) None
Raise
FleetErrorunless name is usable as a file name on any bench.The name of a device is not only a label: it names its virtual environment, its log, its run directory and its state file. A name that a Windows bench cannot open (
com3) or that reaches out of its directory (../x) would declare fine on a developer machine and fail on the instrument.- Parameters:
name (str) – The key the fleet file gives the device.
- Raises:
FleetError – When the name cannot be a file name everywhere.
- Return type:
None
- plesty.server.model.module_for(package: str) str
The import path served by
python -mfor a PLESTY distribution.- Parameters:
package (str) – PyPI distribution name, e.g.
plesty-pm100d.- Returns:
plesty.pm100d— the platform’s flat namespace convention.- Return type:
str
- plesty.server.model.DEFAULT_CONFIG = 'config/default.yaml'
- class plesty.server.model.ExperimentManifest
What a module answered when asked what it takes.
- Variables:
module – Import path the manifest names.
title – Human title of the experiment.
config – The configuration file the module uses by default.
run_root – Where the module puts runs when nothing overrides it.
viz – Import path of its viewer, or
Nonewhen it ships none.parameters – Every declared configuration parameter, in file order.
environment – The variables the run reads, each with whether it is required and what it is for.
chooses_devices – Whether the module names the devices of its
setup.yamla configuration uses (--devices); without it every device is served (plesty-lib#62).
- module: str
- title: str = ''
- config: str = 'config/default.yaml'
- run_root: str = 'runs'
- viz: str | None = None
- environment: tuple[tuple[str, str, bool], Ellipsis] = ()
- chooses_devices: bool = False
- property groups: list[str]
The parameter groups, in the order they were declared.
- Return type:
list[str]
- in_group(group: str) list[Parameter]
The parameters of group, in declaration order.
- Parameters:
group (str)
- Return type:
list[Parameter]
- property required_env: list[str]
The environment variables a run cannot do without.
- Return type:
list[str]
- missing_env(values: collections.abc.Mapping[str, str]) list[str]
The required variables values does not set, or sets empty.
- Parameters:
values (collections.abc.Mapping[str, str]) – The environment the run would get.
- Returns:
The missing variable names, in declaration order. A run can be refused on these before anything is started, rather than aborting part-way through a plan.
- Return type:
list[str]
- classmethod parse(text: str) ExperimentManifest
Read a manifest from what
--manifestprinted.- Parameters:
text (str) – The command’s standard output.
- Returns:
The manifest.
- Raises:
ManifestError – If the output is not the document it should be.
- Return type:
- class plesty.server.model.ExperimentSpec
One experiment as the fleet declares it.
- Variables:
name – Instance name — the key its runs and jobs are recorded under; unique per bench.
package – PyPI distribution of the experiment module.
version – Pinned release, or
Nonefor the newest at install time.git – Repository URL to install from; an experiment is normally installed this way, since its configuration is in the checkout.
ref – Branch, tag or commit for a git source;
None=v<version>when a version is given, else the default branch.path – A local repository to run instead of an install — the folder Hub ▸ Load from… loaded. Only a declaration naming it runs it.
module – Import path run with
python -m; derived from package.config – Configuration file, relative to the checkout.
args – Arguments appended to
python -m <module>, beyond the ones the console supplies itself (--config,--run-root,--resume).env – Environment set for the run on top of the bench’s own.
- name: str
- package: str
- version: str | None = None
- git: str | None = None
- ref: str | None = None
- path: str | None = None
- module: str = ''
- config: str = 'config/default.yaml'
- args: tuple[str, Ellipsis] = ()
- env: collections.abc.Mapping[str, str]
- __post_init__() None
Fill the derived fields and validate the declaration.
- Raises:
FleetError – If the name is unusable as a directory key, or no package is named.
- Return type:
None
- property git_ref: str | None
The ref a git install checks out, or
Nonefor the default branch.- Return type:
str | None
- property requirement: str
The pip requirement a release install resolves.
- Return type:
str
- command(python: str, run_root: str, resume: str | None = None, config: str | None = None) list[str]
Build the command that runs this experiment.
The console supplies the three arguments it is entitled to decide — which configuration, where the run goes, and whether this continues an earlier one — and the declaration’s own arguments follow, so a module option always wins over nothing and never over the operator.
- Parameters:
python (str) – Interpreter of the module’s environment.
run_root (str) – Directory the run’s checkpoint directory goes in.
resume (str | None) – Run id to continue, or
Nonefor a new run.config (str | None) – The configuration file, when the run has its own; the declared one by default. Passed once: a second
--configwould win only by coming last.
- Returns:
The command line.
- Return type:
list[str]
- manifest_command(python: str) list[str]
Build the command that asks the module what it takes.
- Parameters:
python (str) – Interpreter of the module’s environment.
- Returns:
The command line; it connects to nothing and needs no configuration.
- Return type:
list[str]
- devices_command(python: str, config: str) list[str]
Build the command that asks which devices a run of config uses.
- Parameters:
python (str) – Interpreter of the module’s environment.
config (str) – The configuration file the run will read.
- Returns:
The command line; it connects to nothing.
- Return type:
list[str]
- classmethod from_mapping(name: str, raw: collections.abc.Mapping[str, Any]) ExperimentSpec
Build a spec from one
experiments:entry.- Parameters:
name (str) – The instance name the entry is keyed by.
raw (collections.abc.Mapping[str, Any]) – The entry.
- Raises:
FleetError – On unknown keys or a malformed value.
- Return type:
- to_mapping() dict[str, Any]
The declaration’s YAML form, derived defaults left out.
- Return type:
dict[str, Any]
- exception plesty.server.model.ManifestError
Bases:
RuntimeErrorRaised when a module’s manifest cannot be read or makes no sense.
Initialize self. See help(type(self)) for accurate signature.
- class plesty.server.model.Parameter
One configuration parameter the module declares.
The fields are the device vocabulary — the console renders an experiment’s settings with the same code that renders a device’s panel, so nothing here is new and nothing here may drift from it.
- Variables:
key – How the configuration addresses it,
group.parameterfor a grouped one.group – The group it belongs to.
name – Its name within the group.
dtype – Declared type name;
yamlfor a value that is a document rather than a scalar.unit – Physical unit, or
""for a count, orNone.description – What it means.
default – What the module uses when the configuration omits it.
minimum – Lower bound, or
None.maximum – Upper bound, or
None.options – Allowed values, which make it a choice.
- key: str
- group: str
- name: str
- dtype: str = 'str'
- unit: str | None = None
- description: str = ''
- default: Any = None
- minimum: float | None = None
- maximum: float | None = None
- options: tuple[Any, Ellipsis] | None = None
- property is_document: bool
Whether its value is a document rather than a scalar.
- Return type:
bool
- plesty.server.model.SOURCE_GIT = 'git'
- plesty.server.model.SOURCE_LOCAL = 'local'
- plesty.server.model.SOURCE_PYPI = 'pypi'
- class plesty.server.model.DeviceManager(home: plesty.server.model.home.Home)
The installed-module inventory under a
Home.Bind to a home.
- Parameters:
home (plesty.server.model.home.Home) – The bench home.
- home
- record(package: str, version: str, source: str = SOURCE_PYPI, git: str | None = None, ref: str | None = None, commit: str | None = None, python: str = '', job_id: str | None = None, path: str | os.PathLike[str] | None = None) InstalledVersion
Write down that package version is installed; returns the record.
- Parameters:
package (str) – Distribution name.
version (str) – Installed release.
source (str) –
SOURCE_PYPIorSOURCE_GIT.git (str | None) – Repository URL for a git source.
ref (str | None) – Requested ref for a git source.
commit (str | None) – Checked-out commit for a git source.
python (str) – Interpreter version of the environment.
job_id (str | None) – The install job.
path (str | os.PathLike[str] | None) – Environment location when not the default package dir.
- Return type:
- save(installed: InstalledVersion) pathlib.Path
Write installed to its record file; returns the path.
- Parameters:
installed (InstalledVersion)
- Return type:
pathlib.Path
- get(package: str, slot: str) InstalledVersion | None
The record of package at slot (a version, or
git-<ref>), orNone.- Parameters:
package (str)
slot (str)
- Return type:
InstalledVersion | None
- require(package: str, slot: str) InstalledVersion
Like
get()but raisesDeviceManagerErrorwhen absent.- Parameters:
package (str)
slot (str)
- Return type:
- package(package: str) InstalledPackage
Every installed version of package (empty when none).
- Parameters:
package (str)
- Return type:
- list() list[InstalledPackage]
Every package with at least one installed version, by name.
- Return type:
list[InstalledPackage]
- info(package: str) PackageInfo
The package-level record of package (empty fields when nothing is known).
- Parameters:
package (str)
- Return type:
- remember(package: str, **fields: str) PackageInfo
Merge non-empty fields into the package-level record; returns it.
- Parameters:
package (str)
fields (str)
- Return type:
- env_dir(installed: InstalledVersion) pathlib.Path
The environment directory of installed (its
path, else the package dir).- Parameters:
installed (InstalledVersion)
- Return type:
pathlib.Path
- resolve(spec: plesty.server.model.device.DeviceSpec) InstalledVersion | None
The installed version that serves spec, or
Nonewhen one must be installed.The most recent install among those that
InstalledVersion.satisfies()the spec wins — for an unpinned PyPI spec that is the newest install, for a git branch the last pull.- Parameters:
- Return type:
InstalledVersion | None
- forget(package: str, slot: str, remove_env: bool = False) bool
Drop the record of package at slot;
Truewhen it existed.- Parameters:
package (str) – Distribution name.
slot (str) – Version (release) or
git-<ref>(checkout).remove_env (bool) – Also delete a release’s environment directory.
- Return type:
bool
- exception plesty.server.model.DeviceManagerError
Bases:
ValueErrorAn installed-version record is missing or inconsistent.
Initialize self. See help(type(self)) for accurate signature.
- class plesty.server.model.InstalledPackage
All installed versions of one device module.
- Variables:
package – Distribution name.
versions – Records keyed by slot (version, or
git-<ref>), oldest install first.
- package: str
- versions: collections.abc.Mapping[str, InstalledVersion]
- __iter__() collections.abc.Iterator[InstalledVersion]
Iterate over the versions, oldest install first.
- Return type:
collections.abc.Iterator[InstalledVersion]
- __len__() int
Number of installed versions.
- Return type:
int
- __contains__(version: object) bool
Whether version (a slot, or a release version) is installed.
- Parameters:
version (object)
- Return type:
bool
- property latest: InstalledVersion | None
The most recently installed version, or
Nonewhen empty.- Return type:
InstalledVersion | None
- class plesty.server.model.InstalledVersion
One version of one device module present on the bench.
- Variables:
package – PyPI distribution name, e.g.
plesty-pm100d.version – The installed release as reported by the environment.
source –
SOURCE_PYPI,SOURCE_GITorSOURCE_LOCAL.git – Repository URL for a git source, else
None.ref – Branch, tag or commit that was requested for a git source.
commit – The commit actually checked out for a git source.
installed_utc – ISO timestamp of the install.
python – Version of the interpreter in the environment.
job_id – The install job that produced it, when known.
path – Where the environment lives when it is not the default
<home>/packages/<package>/<version>/— a git checkout, or a local repository, whose.venvis the environment.
- package: str
- version: str
- source: str = 'pypi'
- git: str | None = None
- ref: str | None = None
- commit: str | None = None
- installed_utc: str = ''
- python: str = ''
- job_id: str | None = None
- path: str = ''
- __post_init__() None
Validate the record.
- Return type:
None
- property is_checkout: bool
Whether the environment is a
.venvinside a repository — git or local.- Return type:
bool
- property slot: str
the version for a release,
git-<ref>for a checkout.A checkout moves — its version changes with every pull — so it is kept by the ref it tracks, and two checkouts at the same commit (two refs) never share a record.
- Type:
What identifies the environment within the package
- Return type:
str
- property key: tuple[str, str]
(package, slot)— what identifies the environment.- Return type:
tuple[str, str]
- satisfies(spec: plesty.server.model.device.DeviceSpec) bool
Whether this install is what spec asks for.
A PyPI spec is satisfied by the pinned version (or any PyPI version when unpinned); a git spec by an install from the same repository at the same ref (or
v<version>), a commit hash matching by prefix. A local repository satisfies exactly the specs that name its folder (path), and nothing else: loading one never changes what an existing declaration runs.- Parameters:
- Return type:
bool
- to_dict() dict[str, Any]
JSON form.
- Return type:
dict[str, Any]
- classmethod from_dict(data: collections.abc.Mapping[str, Any]) InstalledVersion
Rebuild a record from
to_dict()output (extra keys ignored).- Parameters:
data (collections.abc.Mapping[str, Any])
- Return type:
- class plesty.server.model.PackageInfo
What the bench knows about a module as a project — independent of any install.
Learned from the catalogue (
adopt) or from a git install, kept in<home>/packages/<package>/package.jsonand never asked again: the repository a module comes from, its project page, its latest release.- Variables:
package – Distribution name.
repo_url – Clone URL of the module’s repository.
web_url – Project page (GitLab),
""when unknown.latest_tag – Latest release tag seen (
v0.2.1),""when none.version – Latest release version seen,
""when none.vendor – Hub vendor group,
""when unknown.description – One line,
""when unknown.module_type – What the module is —
device,experiment, … — as its[tool.plesty] module_typesays;""when unknown.
- package: str
- repo_url: str = ''
- web_url: str = ''
- latest_tag: str = ''
- version: str = ''
- vendor: str = ''
- description: str = ''
- module_type: str = ''
- to_dict() dict[str, Any]
JSON form.
- Return type:
dict[str, Any]
- classmethod from_dict(data: collections.abc.Mapping[str, Any]) PackageInfo
Rebuild from
to_dict()output (extra keys ignored).- Parameters:
data (collections.abc.Mapping[str, Any])
- Return type:
- merged(**fields: str) PackageInfo
A copy with the non-empty fields replacing the current values.
- Parameters:
fields (str)
- Return type:
- plesty.server.model.ENV_FILENAME = '.env'
- plesty.server.model.parse_env(text: str) dict[str, str]
Parse dotenv text into a mapping (later keys win).
- Parameters:
text (str)
- Return type:
dict[str, str]
- plesty.server.model.read_env(path: str | os.PathLike[str]) dict[str, str]
Parse the file at path; empty when it does not exist.
- Parameters:
path (str | os.PathLike[str])
- Return type:
dict[str, str]
- plesty.server.model.render_env(values: collections.abc.Mapping[str, str]) str
Render a mapping as dotenv text (one
KEY=VALUEper line, quoted when needed).- Parameters:
values (collections.abc.Mapping[str, str])
- Return type:
str
- exception plesty.server.model.FleetError
Bases:
ValueErrorA fleet file or device declaration is malformed.
Initialize self. See help(type(self)) for accurate signature.
- plesty.server.model.JOB_KIND = 'field-test'
- plesty.server.model.REPORT_BASENAME = 'reports/field-test-run'
- plesty.server.model.STANDARD_GATES: tuple[str, Ellipsis] = ('discovery', 'connect_lifecycle', 'param_roundtrip', 'param_constraints', 'functions',...
- plesty.server.model.TIER_ARTIFACTS: collections.abc.Mapping[str, str]
- plesty.server.model.TIER_SCRIPTS: collections.abc.Mapping[str, str]
- exception plesty.server.model.FieldTestError
Bases:
plesty.server.model.errors.FleetErrorA field test cannot be set up as asked.
Initialize self. See help(type(self)) for accurate signature.
- class plesty.server.model.FieldTestReport
What a field test published — the summary a bench needs, not the whole document.
- Variables:
path – The
field-test*.jsonfile.tier –
hostorclient, from the file name.instrument – The
reports/<instrument>/directory name.module – Module name from the document.
version – Module version the run tested.
ok – Overall outcome.
passed – Gates passed.
failed – Gates failed.
skipped – Gates skipped.
gates – Per-gate results, in run order.
findings – Count of findings per severity (
error/warning/info).modified_utc – ISO timestamp of the file — when the run ended.
- path: pathlib.Path
- tier: str
- instrument: str
- module: str
- version: str
- ok: bool
- passed: int
- failed: int
- skipped: int
- gates: tuple[GateResult, Ellipsis] = ()
- findings: collections.abc.Mapping[str, int]
- modified_utc: str = ''
- property summary: str
pm100d 0.2.1 [host] ok 9/9style.- Type:
One line
- Return type:
str
- classmethod from_path(path: pathlib.Path) FieldTestReport
Read a published report.
- Raises:
FieldTestError – When the file is not a field-test document.
- Parameters:
path (pathlib.Path)
- Return type:
- class plesty.server.model.FieldTestRun
One field-test request.
- Variables:
tier –
host(instrument, server must be stopped) orclient(running server).address –
--address— host tier: instrument address ormock; client tier:tcp://…;Nonelets the script use.env.gates – Run only these gates (
None= all).repetitions –
--repetitionsfor the timing gates (None= script default).keep_going – Carry on after a failed gate.
keep_server – Host tier: leave a running server alone (only right for
mockor another instrument).extra – Further arguments passed to the script unchanged.
- tier: str = 'host'
- address: str | None = None
- gates: tuple[str, Ellipsis] | None = None
- repetitions: int | None = None
- keep_going: bool = False
- keep_server: bool = False
- extra: tuple[str, Ellipsis] = ()
- __post_init__() None
Validate the request.
- Return type:
None
- property script: str
The script this request runs, relative to the checkout.
- Return type:
str
- property artifact: str
The published file name this tier writes.
- Return type:
str
- property needs_instrument: bool
Whether the run opens the instrument itself (host tier, not
mock).- Return type:
bool
- argv(report_base: str | None = REPORT_BASENAME, supports: collections.abc.Collection[str] | None = None) list[str]
The script’s arguments for this request.
- Parameters:
report_base (str | None) –
--reportfor the host tier’s internal.md/.jsonlpair;Noneleaves it to the script.supports (collections.abc.Collection[str] | None) – The option names the script accepts (from its
--help), orNoneto assume the current scaffold. Older scaffolds take--port PORTand--mockwhere the current one takes--address; the request is spelled in whichever the script understands, and options it lacks are left out.
- Return type:
list[str]
- command(python: pathlib.Path, checkout: pathlib.Path, supports: collections.abc.Collection[str] | None = None) list[str]
The full command line: python running the tier’s script in checkout.
- Parameters:
python (pathlib.Path) – The checkout’s interpreter.
checkout (pathlib.Path) – The module checkout.
supports (collections.abc.Collection[str] | None) – The script’s option names (see
argv()).
- Raises:
FieldTestError – When the checkout has no script for this tier.
- Return type:
list[str]
- to_dict() dict[str, Any]
Record form (stored on the job’s
detail).- Return type:
dict[str, Any]
- classmethod from_dict(data: collections.abc.Mapping[str, Any]) FieldTestRun
Rebuild a request from
to_dict()output.- Parameters:
data (collections.abc.Mapping[str, Any])
- Return type:
- class plesty.server.model.GateResult
One gate of a published report.
- name: str
- status: str
- duration_s: float
- reason: str
- plesty.server.model.field_test_script(checkout: pathlib.Path, tier: str = 'host') pathlib.Path | None
The tier’s script inside checkout, or
Nonewhen the module has none.- Raises:
FieldTestError – On an unknown tier.
- Parameters:
checkout (pathlib.Path)
tier (str)
- Return type:
pathlib.Path | None
- plesty.server.model.find_reports(checkout: pathlib.Path, since_utc: str | None = None) list[FieldTestReport]
Every published field-test report under
<checkout>/reports/, newest first.- Parameters:
checkout (pathlib.Path) – The module checkout.
since_utc (str | None) – Only reports modified at or after this ISO timestamp — what a run that started then produced.
- Return type:
list[FieldTestReport]
- plesty.server.model.gates_in_help(text: str) tuple[str, Ellipsis]
The gate names a script’s
--helpoffers for--gates, in its order; empty if none.- Parameters:
text (str)
- Return type:
tuple[str, Ellipsis]
- plesty.server.model.options_in_help(text: str) set[str]
The long options an argparse
--helptext mentions (--address,--mock…).- Parameters:
text (str)
- Return type:
set[str]
- plesty.server.model.FLEET_FILENAME = 'fleet.yaml'
- plesty.server.model.FLEET_VERSION = 1
- class plesty.server.model.Fleet
A parsed fleet file.
- Variables:
devices – Specs keyed by device name, in file order.
experiments – Experiment specs keyed by name, in file order.
home –
home:from the file, orNone.index_url –
index_url:from the file, orNone.path – Where it was read from, or
Nonefor an in-memory fleet.benches –
benches:as a setup file writes it, carried through unread; seeplesty.server.model.setup.parse_setup().
- devices: collections.abc.Mapping[str, plesty.server.model.device.DeviceSpec]
- experiments: collections.abc.Mapping[str, plesty.server.model.experiment.ExperimentSpec]
- home: pathlib.Path | None = None
- index_url: str | None = None
- path: pathlib.Path | None = None
- benches: collections.abc.Mapping[str, Any]
- __getitem__(name: str) plesty.server.model.device.DeviceSpec
The spec of device name;
KeyErrorwhen undeclared.- Parameters:
name (str)
- Return type:
- __contains__(name: object) bool
Whether name is a declared device.
- Parameters:
name (object)
- Return type:
bool
- __iter__() Any
Iterate over the specs in file order.
- Return type:
Any
- __len__() int
Number of declared devices.
- Return type:
int
- property autostart: list[plesty.server.model.device.DeviceSpec]
The specs
fleet upstarts.- Return type:
- property is_setup: bool
Whether this is an experiment’s setup rather than one of a bench’s fleets.
A setup names its
benches:; a bench’s fleet never does. It is committed with the experiment, so the bench only reads it: written back, it lost every comment and gained the ports this bench chose (#48).- Return type:
bool
- classmethod from_mapping(raw: collections.abc.Mapping[str, Any], path: pathlib.Path | None = None) Fleet
Build a fleet from a parsed YAML document.
- Parameters:
raw (collections.abc.Mapping[str, Any]) – The document.
path (pathlib.Path | None) – Where it came from, for error messages and
path.
- Raises:
FleetError – On a wrong schema version or malformed entries.
- Return type:
- to_mapping() dict[str, Any]
The YAML document form of this fleet.
- Return type:
dict[str, Any]
- _copy(**changes: Any) Fleet
A copy of this fleet with changes applied.
Every mutator goes through here rather than rebuilding the fleet positionally, so a field added between two others cannot silently shift what the next argument means.
- Parameters:
changes (Any)
- Return type:
- with_device(spec: plesty.server.model.device.DeviceSpec) Fleet
A copy with spec added or replaced under its name.
- Parameters:
- Return type:
- without_device(name: str) Fleet
A copy without device name (no error when absent).
- Parameters:
name (str)
- Return type:
- with_experiment(spec: plesty.server.model.experiment.ExperimentSpec) Fleet
A copy with experiment spec added or replaced under its name.
- Raises:
FleetError – If a device already holds that name — a run directory, a job key and a log are keyed by it.
- Parameters:
- Return type:
- without_experiment(name: str) Fleet
A copy without experiment name (no error when absent).
- Parameters:
name (str)
- Return type:
- renamed(old: str, new: str) Fleet
A copy with device old declared under new, where it already sits.
Rebuilding the mapping rather than dropping and re-adding is the whole point: the fleet file is written in key order, so a device the operator renames stays on the line it was on instead of moving to the bottom.
- Parameters:
old (str) – The declared name.
new (str) – The name to give it; must be free.
- Raises:
FleetError – When old is not declared, new already is, or new is not a name every bench can turn into a file name.
- Return type:
- plesty.server.model.find_fleet(explicit: str | os.PathLike[str] | None, home: pathlib.Path) pathlib.Path | None
Locate the fleet file a command should consult.
- Parameters:
explicit (str | os.PathLike[str] | None) – A path the user gave (
-f); returned as-is when set.home (pathlib.Path) – The bench home, whose
fleet.yamlis the last resort after the working directory’s.
- Returns:
The first existing candidate, or
Nonewhen no fleet file exists.- Return type:
pathlib.Path | None
- plesty.server.model.load_fleet(path: str | os.PathLike[str]) Fleet
Read and validate a fleet file.
- Parameters:
path (str | os.PathLike[str]) – The YAML file.
- Raises:
FleetError – When the file is missing or malformed.
- Return type:
- plesty.server.model.save_fleet(fleet: Fleet, path: str | os.PathLike[str]) pathlib.Path
Write a fleet file.
- Parameters:
fleet (Fleet) – The fleet to serialize.
path (str | os.PathLike[str]) – Destination file; parents are created.
- Returns:
The written path.
- Return type:
pathlib.Path
- plesty.server.model.HOME_ENV = 'PLESTY_SERVER_HOME'
- class plesty.server.model.Home
Layout of the plesty-server home directory.
- Variables:
root – The directory everything lives under.
- root: pathlib.Path
- classmethod resolve(root: str | os.PathLike[str] | None = None) Home
Build a home from an explicit path or the environment default.
- Parameters:
root (str | os.PathLike[str] | None) – Directory to use;
Noneselectsdefault_home().- Return type:
- property venvs: pathlib.Path
One virtual environment per installed device, keyed by device name.
- Return type:
pathlib.Path
- property logs: pathlib.Path
One append-only log per device server.
- Return type:
pathlib.Path
- property state: pathlib.Path
One JSON record per running server (pid, port, start time).
- Return type:
pathlib.Path
- property run: pathlib.Path
Working directories the servers run in; plesty-lib writes
logs/there.- Return type:
pathlib.Path
- property repos: pathlib.Path
Git checkouts of device modules installed from a repository.
- Return type:
pathlib.Path
- property jobs: pathlib.Path
One JSON record per long-running job (install, update, field test, command).
- Return type:
pathlib.Path
- property fleets: pathlib.Path
Where the bench keeps its fleets, one file each (
<home>/fleets/<name>.yaml).- Return type:
pathlib.Path
- property default_fleet: pathlib.Path
The fleet a new bench starts with, empty (
<home>/fleets/default.yaml).- Return type:
pathlib.Path
- fleet_file(name: str) pathlib.Path
The file of the fleet called name.
- Parameters:
name (str)
- Return type:
pathlib.Path
- property data: pathlib.Path
Where the devices write while the bench has no Plesty share (#43).
- Return type:
pathlib.Path
- property demo: pathlib.Path
Where the welcome’s demo keeps its runs, and its spectrometer replays them (#43).
- Return type:
pathlib.Path
- property tools: pathlib.Path
Tools the bench installed for itself (the portable git on Windows).
- Return type:
pathlib.Path
- property packages: pathlib.Path
one environment per (package, version), side by side.
- Type:
Installed device modules
- Return type:
pathlib.Path
- package_dir(package: str, version: str) pathlib.Path
Environment of package at version.
- Parameters:
package (str)
version (str)
- Return type:
pathlib.Path
- package_record(package: str, version: str) pathlib.Path
Record file of package at version (beside its environment).
- Parameters:
package (str)
version (str)
- Return type:
pathlib.Path
- property last_fleet: pathlib.Path
Pointer file naming the fleet the console used last (
<home>/last-fleet).- Return type:
pathlib.Path
- package_info(package: str) pathlib.Path
The package-level record of package: repository, project page, latest release.
- Parameters:
package (str)
- Return type:
pathlib.Path
- checkout(package: str, ref: str | None) pathlib.Path
Checkout directory of package at ref (git sources only).
Refs may contain
/(feat/x); the directory name flattens them.- Parameters:
package (str)
ref (str | None)
- Return type:
pathlib.Path
- job_file(job_id: str) pathlib.Path
Record file of job job_id.
- Parameters:
job_id (str)
- Return type:
pathlib.Path
- job_log(job_id: str) pathlib.Path
Log file of job job_id.
- Parameters:
job_id (str)
- Return type:
pathlib.Path
- venv(name: str) pathlib.Path
Venv directory of the device name.
- Parameters:
name (str)
- Return type:
pathlib.Path
- log(name: str) pathlib.Path
The current log file of the device name.
Each server start, and each Clear log, opens a new file named with its time (
new_log());logs/<name>.currentnames the one in use. Without a pointer — a log written before there were any — it is the singlelogs/<name>.logevery start used to append to.- Parameters:
name (str)
- Return type:
pathlib.Path
- new_log(name: str) pathlib.Path
Start a new log file for name, make it the current one, and return it.
Named
<name>-<YYYYMMDD-HHMMSS>.log. Older files stay: a clear never truncates a file a running server writes, which is what left an 11.7 MB log no reader could get through (#23).- Parameters:
name (str)
- Return type:
pathlib.Path
- state_file(name: str) pathlib.Path
Process-state file of the device name.
- Parameters:
name (str)
- Return type:
pathlib.Path
- run_dir(name: str) pathlib.Path
Working directory of the device name’s server process.
- Parameters:
name (str)
- Return type:
pathlib.Path
- property runs: pathlib.Path
Where experiment runs land, one directory per declared experiment.
A measurement’s data is not a device’s working directory and does not belong under
run/: it outlives the process that wrote it, it is what the operator came for, and a purge that clears working directories must not reach it.- Return type:
pathlib.Path
- run_root(name: str) pathlib.Path
Root the runs of experiment name go under.
One root per declared experiment, so
plesty.lib.experiment.Runandlatest_runread it exactly as they read a checkout’sruns/.- Parameters:
name (str)
- Return type:
pathlib.Path
- plesty.server.model.default_home() pathlib.Path
The home directory the environment or the packaged config designates.
- Returns:
$PLESTY_SERVER_HOMEwhen set, elserunning.homefromconfig.yamlwith~expanded.- Return type:
pathlib.Path
- plesty.server.model.CANCELLED_EXIT = -9
- plesty.server.model.LOG_CHUNK = 65536
- plesty.server.model.LOST_EXIT = -1
- class plesty.server.model.Job
One unit of long-running work.
- Variables:
id –
<name>-<kind>-<timestamp>, unique per bench.name – Device instance the job belongs to.
kind –
install,update,field-test,command…command – The command line.
cwd – Working directory.
pid – Process id while it runs.
started_utc – ISO timestamp of the launch.
finished_utc – ISO timestamp of the end, or
Nonewhile running.returncode – Exit code once finished (
Nonewhile running;LOST_EXITwhen the process vanished without one).log – Path of the log file.
detail – Kind-specific data (e.g. the reports a field test wrote).
- id: str
- name: str
- kind: str
- command: list[str]
- cwd: str
- pid: int | None
- started_utc: str
- finished_utc: str | None = None
- returncode: int | None = None
- log: str = ''
- detail: dict[str, Any]
- property running: bool
Whether the job has not finished yet.
- Return type:
bool
- property state: str
running,done(exit 0),failed(any other exit).- Return type:
str
- to_dict() dict[str, Any]
JSON form, with the derived
stateincluded.- Return type:
dict[str, Any]
- exception plesty.server.model.JobError
Bases:
RuntimeErrorA job record does not exist or cannot be read.
Initialize self. See help(type(self)) for accurate signature.
- class plesty.server.model.JobStore(home: plesty.server.model.home.Home)
Job records and logs under a
Home.Bind to a home.
- Parameters:
home (plesty.server.model.home.Home) – The bench home.
- home
- create(name: str, kind: str, command: list[str], cwd: str | os.PathLike[str], pid: int | None = None, detail: collections.abc.Mapping[str, Any] | None = None) Job
Open a new record and return it (state
running).- Parameters:
name (str) – Device instance the job belongs to.
kind (str) – Job kind, part of the id.
command (list[str]) – The command line.
cwd (str | os.PathLike[str]) – Working directory.
pid (int | None) – Process id when already known.
detail (collections.abc.Mapping[str, Any] | None) – Kind-specific data stored on the record.
- Return type:
- save(job: Job) pathlib.Path
Write job to its record file; returns the path.
- Parameters:
job (Job)
- Return type:
pathlib.Path
- get(job_id: str) Job | None
The record of job_id, or
Nonewhen unknown or unreadable.- Parameters:
job_id (str)
- Return type:
Job | None
- require(job_id: str) Job
Like
get()but raisesJobErrorwhen unknown.- Parameters:
job_id (str)
- Return type:
- list(name: str | None = None, kind: str | None = None) list[Job]
Jobs on record, newest first, optionally filtered by device and kind.
- Parameters:
name (str | None)
kind (str | None)
- Return type:
list[Job]
- finish(job_id: str, returncode: int) Job
Close the record of job_id with returncode; returns it.
- Parameters:
job_id (str)
returncode (int)
- Return type:
- refresh(job: Job, alive: collections.abc.Callable[[int], bool], exit_code: collections.abc.Callable[[str], int | None]) Job
Settle a
runningrecord against what the process layer knows.- Parameters:
job (Job) – The record to bring up to date (mutated and saved when it ends).
alive (collections.abc.Callable[[int], bool]) – Whether a pid is still running.
exit_code (collections.abc.Callable[[str], int | None]) – The exit code left for a job id, or
Nonewhen none.
- Returns:
job, finished when an exit code exists or the pid is gone (
LOST_EXITthen), unchanged while it still runs.- Return type:
- log(job_id: str, offset: int = 0, limit: int = LOG_CHUNK) tuple[str, int]
Read the job log from byte offset.
- Parameters:
job_id (str) – The job.
offset (int) – Where the previous read stopped (0 for the start).
limit (int) – Maximum bytes to return.
- Returns:
The text read and the offset to continue from. Decoding is lenient — a chunk may cut a multi-byte character.
- Return type:
tuple[str, int]
- log_end(job_id: str, limit: int = LOG_END) tuple[str, int, int]
The end of the job log; see
log_end().- Parameters:
job_id (str)
limit (int)
- Return type:
tuple[str, int, int]
- log_before(job_id: str, end: int, limit: int = LOG_END) tuple[str, int]
The part of the job log before byte end; see
log_before().- Parameters:
job_id (str)
end (int)
limit (int)
- Return type:
tuple[str, int]
- tail(job_id: str, lines: int = 50) str
The last lines lines of the job log (empty when there is none yet).
- Parameters:
job_id (str)
lines (int)
- Return type:
str
- plesty.server.model.tail_file(path: pathlib.Path, lines: int, limit: int = TAIL_LIMIT) str
The last lines lines of path, read from at most its last limit bytes.
One read of a bounded span. The loop this replaced prepended each 8 KB block to everything read so far until enough newlines turned up — on a file with none (a truncated log a server kept writing at its old offset fills with NULs) that is quadratic in the file’s size, and an 11.7 MB log hung the console, the agent and every reader with it (#23). A line longer than limit is shown from its last limit bytes.
- Parameters:
path (pathlib.Path)
lines (int)
limit (int)
- Return type:
str
- plesty.server.model.PEERS_FILENAME = 'peers.yaml'
- plesty.server.model.PEERS_VERSION = 1
- class plesty.server.model.Peer
One bench this master drives.
- Variables:
name – What the console calls it — the Host column’s value, and unique among peers. Not required to be the node’s hostname: a bench is named for the rig it runs, which is what an operator looks for.
address – Where the node’s agent listens:
host,host:portor a full ZMQ endpoint. Resolved to an endpoint where it is used, so that this model needs nothing of the client.token – The node’s shared secret, or empty when it checks none.
data – Where that bench sees the lab’s shared data disk — the same disk every bench sees, each under its own path. Empty when unset.
- name: str
- address: str
- token: str = ''
- data: str = ''
- property guarded: bool
Whether a secret is sent to this node (never the secret itself).
- Return type:
bool
- property host: str
The machine the bench runs on, without its agent’s port or scheme.
tcp://lab-bench-03:5550,lab-bench-03:5550andlab-bench-03are alllab-bench-03: the device servers on that bench listen on their own ports of the same machine.- Return type:
str
- validate() Peer
Return self, having refused a peer that could not be reached.
- Raises:
FleetError – When the name or the address is empty.
- Return type:
- to_mapping() dict[str, Any]
This peer’s entry in the document, without its name.
- Return type:
dict[str, Any]
- classmethod from_mapping(name: str, raw: Any) Peer
Build the peer name from its entry.
- Raises:
FleetError – When the entry is not a mapping or carries a key this version does not know.
- Parameters:
name (str)
raw (Any)
- Return type:
- plesty.server.model.load_peers(home: plesty.server.model.home.Home) list[Peer]
The nodes home declares, empty when it declares none.
- Raises:
FleetError – When the file cannot be read or is malformed. A master whose list is broken is told so — an empty table would say the nodes are gone, which is a different thing entirely.
- Parameters:
- Return type:
list[Peer]
- plesty.server.model.parse_peers(document: Any) list[Peer]
Every peer of a
peers.yamldocument, in the order it declares them.- Raises:
FleetError – When the document, its
peerskey or any entry is malformed.- Parameters:
document (Any)
- Return type:
list[Peer]
- plesty.server.model.peers_file(home: plesty.server.model.home.Home) pathlib.Path
Where home keeps the node list.
- Parameters:
- Return type:
pathlib.Path
- plesty.server.model.save_peers(home: plesty.server.model.home.Home, peers: list[Peer]) pathlib.Path
Write peers to home; returns the path.
The file holds the nodes’ shared secrets, so it is made readable by its owner alone — the same guard, and the same Windows caveat, as the agent’s own settings.
- Raises:
FleetError – When a peer is incomplete or two share a name.
- Parameters:
peers (list[Peer])
- Return type:
pathlib.Path
- plesty.server.model.AGENT_PORT = 5550
- plesty.server.model.DEFAULT_TCP_PORT = 5555
- plesty.server.model.DEVICE_PORT_BASE = 5551
- plesty.server.model.allocate_port(taken: collections.abc.Iterable[int], base: int = DEVICE_PORT_BASE, is_free: collections.abc.Callable[[int], bool] = port_is_free) int
The lowest free port from base up, skipping taken and the agent’s.
- Parameters:
taken (collections.abc.Iterable[int]) – Ports already spoken for on this bench.
base (int) – Where counting starts.
is_free (collections.abc.Callable[[int], bool]) – Asks the host whether a port can be bound; injected by tests.
- Returns:
A port no other device on the bench holds and nothing on the host is listening on.
- Raises:
FleetError – When counting runs past the end of the port range.
- Return type:
int
- plesty.server.model.declares_port(args: tuple[str, Ellipsis], env: collections.abc.Mapping[str, str]) bool
Whether args or env name the port themselves.
A declaration that names its own port is left alone — the bench allocates only for devices that would otherwise take the default and collide.
- Parameters:
args (tuple[str, Ellipsis])
env (collections.abc.Mapping[str, str])
- Return type:
bool
- plesty.server.model.port_from(args: tuple[str, Ellipsis], env: collections.abc.Mapping[str, str]) int
Resolve the TCP port a server binds from its args and environment.
- Parameters:
args (tuple[str, Ellipsis]) – Command-line arguments passed to
python -m <module>.env (collections.abc.Mapping[str, str]) – Environment values the fleet sets for the process.
- Returns:
The port to probe, falling back to
DEFAULT_TCP_PORT.- Return type:
int
- plesty.server.model.port_is_free(port: int, host: str = '127.0.0.1') bool
Whether port can actually be bound right now.
The fleet file and the process records say what this bench believes it is using. A server that outlived its record, or any other program on the machine, believes nothing — and the socket is the only thing that knows.
The socket option differs because the platforms disagree about what
SO_REUSEADDRmeans. On POSIX it says “a port left inTIME_WAITis still free”, which is the question. On Windows it says “bind even if another socket is listening here” — so the probe succeeded against a live server and every busy port reported free, which silently disabled everything built on this: the port a start moves away from, and the portallocate_port()hands out.SO_EXCLUSIVEADDRUSEis the Windows way to ask the question POSIX answers withSO_REUSEADDR.- Parameters:
port (int)
host (str)
- Return type:
bool
- plesty.server.model.port_listening(port: int, host: str = '127.0.0.1', timeout: float = 0.3) bool
Whether something accepts TCP connections on port right now.
The complement of
port_is_free()for a port a server holds: a device server bindstcp://*, and on some hosts a specific-address bind still succeeds beside a wildcard listener — connecting is the one test that answers the question everywhere.- Parameters:
port (int)
host (str)
timeout (float)
- Return type:
bool
- plesty.server.model.EXITED = 'exited'
- plesty.server.model.RUNNING = 'running'
- plesty.server.model.STARTING = 'starting'
- plesty.server.model.STATES
- plesty.server.model.STOPPED = 'stopped'
- class plesty.server.model.ProcessRecord
What the supervisor persists about a started server.
- Variables:
name – Device instance name.
pid – Process id of the launcher that owns the server.
port – TCP port it was told to bind.
started_utc – ISO timestamp of the launch.
command – The full command line.
cwd – Working directory the server runs in.
log – Path of the log file its output goes to.
python – The interpreter — what a relaunch has to repeat.
module – The
python -mtarget — likewise.args – The spec’s arguments — likewise.
env – The spec’s environment — likewise.
package – Distribution the server runs, for listings.
version – Its installed version, for listings.
relayed – Its waiter copies the output into the log and can switch it to a new file while it runs.
Falsefor a server an older bench started, whose log is the server’s own handle (#23).
- name: str
- pid: int
- port: int
- started_utc: str
- command: list[str]
- cwd: str
- log: str
- python: str = ''
- module: str = ''
- args: list[str] = []
- env: dict[str, str]
- package: str = ''
- version: str = ''
- relayed: bool = False
- to_dict() dict[str, Any]
JSON form.
- Return type:
dict[str, Any]
- classmethod from_dict(data: collections.abc.Mapping[str, Any]) ProcessRecord
Rebuild a record from
to_dict()output (extra keys ignored).- Parameters:
data (collections.abc.Mapping[str, Any])
- Return type:
- classmethod load(path: pathlib.Path) ProcessRecord | None
Read a record file;
Nonewhen absent or unreadable.- Parameters:
path (pathlib.Path)
- Return type:
ProcessRecord | None
- save(path: pathlib.Path) pathlib.Path
Write the record to path; returns it.
- Parameters:
path (pathlib.Path)
- Return type:
pathlib.Path
- class plesty.server.model.ProcessStatus
The observed state of one device server.
- Variables:
name – Device instance name.
state – One of
STATES.pid – Process id when a record exists.
port – Probed port when a record exists.
started_utc – Launch time when a record exists.
log – Log path when a record exists.
returncode – Exit code for an
exitedserver, when the launcher recorded one (-1when it vanished without).detail – For an exited server, the tail of its log — why it died.
- name: str
- state: str
- pid: int | None = None
- port: int | None = None
- started_utc: str | None = None
- log: str | None = None
- returncode: int | None = None
- detail: str = ''
- property alive: bool
Whether the process exists (running or still starting).
- Return type:
bool
- to_dict() dict[str, Any]
JSON form (what
statusprints and the agent returns).- Return type:
dict[str, Any]
- plesty.server.model.MARKER = '[TRAFFIC]'
- class plesty.server.model.TrafficRecord
One served request, as the server reported it.
- Variables:
when – The log line’s own prefix, verbatim;
""when it had none.type – Request type —
call,write,query,connect…target – What it acted on: a function or parameter name, or
"".client – Which client asked.
outcome –
okorerror.ms – How long the server took, in milliseconds.
delivered – Whether the reply reached the client.
error – Exception type when outcome is not
ok, else"".
- when: str
- type: str
- target: str
- client: str
- outcome: str
- ms: float
- delivered: bool
- error: str
- property ok: bool
Whether this exchange both succeeded and arrived.
- Return type:
bool
- property note: str
The one thing a reader needs to see about a record that is not plain.
- Return type:
str
- plesty.server.model.parse_traffic(text: str) list[TrafficRecord]
Every traffic record in text, oldest first.
Tolerant by design: a log holds ordinary server lines, and a truncated tail can begin mid-line. Anything that is not a well-formed record is skipped rather than raising — a monitor that refuses a damaged log shows nothing exactly when something is wrong.
- Parameters:
text (str) – A slice of a server log.
- Return type:
list[TrafficRecord]