One instrument, one repository
A PLESTY module is a whole project: its own repository, its own version, its
own documentation, its own release. A powermeter is not a file inside a lab's
codebase — it is plesty-pm100d, installable by anyone, at a version they
choose.
That costs more repositories than a single shared codebase would. What it buys is the thing a lab actually needs:
- A bench installs exactly what it needs. Three instruments means three packages at three pinned versions, not one codebase carrying drivers for hardware this bench has never seen.
- Versions move independently. Fixing a spectrometer does not oblige anyone with a rotation stage to upgrade anything.
- A module outlives the experiment it was written for. The one that measured something in 2024 is still installable, at the version it was measured with, because nothing rewrote it in place.
- Ownership is legible. One repository has one changelog, one issue tracker and one set of maintainers.
What a module declares about itself
Everything the platform decides about a module, it decides from the module's own metadata rather than from where the module happens to sit.
[tool.plesty]
standard = "quantum"
module_type = "device"
module_type is one of device, analyzer, experiment or core, and it
selects which rules apply. A device is held to the device contract — schemas,
a status contract, a documented API pipeline. An analyzer is held to the
analyzer contract: a public Analyzer subclass with declared input and output
schemas, exercised on schema-generated synthetic inputs. An experiment is held
to the experiment contract instead. Declaring nothing means the type-specific gates
report N/A rather than failing, which is what lets a utility package live
under the same standard without pretending to be an instrument.
standard is the quality tier the module is checked against. It is derived
from the release version when it is not set — below 0.1.0 pixel, below 1.0.0
nebula, from 1.0.0 quantum — so a module tightens as it matures rather
than being held to a release standard on its first day. See
Quality Gates for what each tier demands.
What a device module declares to the world
A device is the one module type that other programs drive at runtime, so it publishes two machine-readable schemas next to its code:
| File | Declares |
|---|---|
schema_param.json |
Settings: type, unit, default, allowed range, the instrument command behind it, and a description |
schema_func.json |
Operations: input parameters with their types and ranges, and what comes back |
Those files are the contract. They are what the server validates incoming
calls against, what describe() returns to a client that has never heard of
this instrument, and what the published documentation is generated from —
which is why documentation cannot drift from what the server accepts. A
client asks the server what it can do; nothing about a specific instrument is
compiled into the client.
Names follow from one decision
Every module shares the plesty namespace, and the rest is derived:
| Artifact | Convention | Example |
|---|---|---|
| Project directory | plesty-<kebab-name> |
plesty-power-meter |
| Source package | plesty/<module_name>/ |
plesty/power_meter/ |
| PyPI distribution | plesty-<kebab-name> |
plesty-power-meter |
| Python import | plesty.<module_name> |
plesty.power_meter |
plesty init strips the plesty- prefix to infer the module name, so naming
the project names all four. The shared namespace is why plesty.pm100d and
plesty.lib coexist without either owning the plesty package.
Read next
- Build a Device — the same contract from the inside: scaffold, base class, schemas, server, tests.
- Quality Gates — what
standardselects, gate by gate. - TCP Communication — the protocol a device module serves.