plesty.server.model.experiment ============================== .. py:module:: plesty.server.model.experiment .. autoapi-nested-parse:: One experiment as the fleet declares it, and what its module says it takes. A device and an experiment are declared almost alike — a package, a version or a repository and ref, arguments and an environment — and installed by exactly the same path, which is keyed by the package and knows nothing of devices. The differences are what this module is for: * **An experiment binds no port and is not a daemon.** There is no `port` and no `autostart`: nothing probes it for liveness and `fleet up` does not start it. It runs when an operator runs it, once, to the end of its plan. * **It is installed from its repository, not from a release.** Its ``config/*.yaml`` and ``.env.example`` are in the checkout and not in the wheel, so a release install would leave nothing to configure. * **It declares what it takes.** ``python -m --manifest`` prints the document :class:`~plesty.lib.experiment.Manifest` describes, and the console builds its settings from that rather than from anything written down here. The manifest is read from the module, never cached into the fleet: a fleet that carried a copy would be a second declaration to keep in step. Attributes ---------- .. autoapisummary:: plesty.server.model.experiment._KNOWN_KEYS plesty.server.model.experiment.DEFAULT_CONFIG Exceptions ---------- .. autoapisummary:: plesty.server.model.experiment.ManifestError Classes ------- .. autoapisummary:: plesty.server.model.experiment.ExperimentSpec plesty.server.model.experiment.Parameter plesty.server.model.experiment.ExperimentManifest Functions --------- .. autoapisummary:: plesty.server.model.experiment._parameters plesty.server.model.experiment._environment plesty.server.model.experiment._number Module Contents --------------- .. py:data:: _KNOWN_KEYS .. py:data:: DEFAULT_CONFIG :value: 'config/default.yaml' .. py:class:: ExperimentSpec One experiment as the fleet declares it. :ivar name: Instance name — the key its runs and jobs are recorded under; unique per bench. :ivar package: PyPI distribution of the experiment module. :ivar version: Pinned release, or ``None`` for the newest at install time. :ivar git: Repository URL to install from; an experiment is normally installed this way, since its configuration is in the checkout. :ivar ref: Branch, tag or commit for a git source; ``None`` = ``v`` when a version is given, else the default branch. :ivar path: A local repository to run instead of an install — the folder *Hub ▸ Load from…* loaded. Only a declaration naming it runs it. :ivar module: Import path run with ``python -m``; derived from *package*. :ivar config: Configuration file, relative to the checkout. :ivar args: Arguments appended to ``python -m ``, beyond the ones the console supplies itself (``--config``, ``--run-root``, ``--resume``). :ivar env: Environment set for the run on top of the bench's own. .. py:attribute:: name :type: str .. py:attribute:: package :type: str .. py:attribute:: version :type: str | None :value: None .. py:attribute:: git :type: str | None :value: None .. py:attribute:: ref :type: str | None :value: None .. py:attribute:: path :type: str | None :value: None .. py:attribute:: module :type: str :value: '' .. py:attribute:: config :type: str :value: 'config/default.yaml' .. py:attribute:: args :type: tuple[str, Ellipsis] :value: () .. py:attribute:: env :type: collections.abc.Mapping[str, str] .. py:method:: __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. .. py:property:: git_ref :type: str | None The ref a git install checks out, or ``None`` for the default branch. .. py:property:: requirement :type: str The pip requirement a release install resolves. .. py:method:: 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. :param python: Interpreter of the module's environment. :param run_root: Directory the run's checkpoint directory goes in. :param resume: Run id to continue, or ``None`` for a new run. :param config: The configuration file, when the run has its own; the declared one by default. Passed once: a second ``--config`` would win only by coming last. :returns: The command line. .. py:method:: manifest_command(python: str) -> list[str] Build the command that asks the module what it takes. :param python: Interpreter of the module's environment. :returns: The command line; it connects to nothing and needs no configuration. .. py:method:: devices_command(python: str, config: str) -> list[str] Build the command that asks which devices a run of *config* uses. :param python: Interpreter of the module's environment. :param config: The configuration file the run will read. :returns: The command line; it connects to nothing. .. py:method:: from_mapping(name: str, raw: collections.abc.Mapping[str, Any]) -> ExperimentSpec :classmethod: Build a spec from one ``experiments:`` entry. :param name: The instance name the entry is keyed by. :param raw: The entry. :raises FleetError: On unknown keys or a malformed value. .. py:method:: to_mapping() -> dict[str, Any] The declaration's YAML form, derived defaults left out. .. py:exception:: ManifestError Bases: :py:obj:`RuntimeError` Raised when a module's manifest cannot be read or makes no sense. Initialize self. See help(type(self)) for accurate signature. .. py:class:: 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. :ivar key: How the configuration addresses it, ``group.parameter`` for a grouped one. :ivar group: The group it belongs to. :ivar name: Its name within the group. :ivar dtype: Declared type name; ``yaml`` for a value that is a document rather than a scalar. :ivar unit: Physical unit, or ``""`` for a count, or ``None``. :ivar description: What it means. :ivar default: What the module uses when the configuration omits it. :ivar minimum: Lower bound, or ``None``. :ivar maximum: Upper bound, or ``None``. :ivar options: Allowed values, which make it a choice. .. py:attribute:: key :type: str .. py:attribute:: group :type: str .. py:attribute:: name :type: str .. py:attribute:: dtype :type: str :value: 'str' .. py:attribute:: unit :type: str | None :value: None .. py:attribute:: description :type: str :value: '' .. py:attribute:: default :type: Any :value: None .. py:attribute:: minimum :type: float | None :value: None .. py:attribute:: maximum :type: float | None :value: None .. py:attribute:: options :type: tuple[Any, Ellipsis] | None :value: None .. py:property:: is_document :type: bool Whether its value is a document rather than a scalar. .. py:class:: ExperimentManifest What a module answered when asked what it takes. :ivar module: Import path the manifest names. :ivar title: Human title of the experiment. :ivar config: The configuration file the module uses by default. :ivar run_root: Where the module puts runs when nothing overrides it. :ivar viz: Import path of its viewer, or ``None`` when it ships none. :ivar parameters: Every declared configuration parameter, in file order. :ivar environment: The variables the run reads, each with whether it is required and what it is for. :ivar chooses_devices: Whether the module names the devices of its ``setup.yaml`` a configuration uses (``--devices``); without it every device is served (plesty-lib#62). .. py:attribute:: module :type: str .. py:attribute:: title :type: str :value: '' .. py:attribute:: config :type: str :value: 'config/default.yaml' .. py:attribute:: run_root :type: str :value: 'runs' .. py:attribute:: viz :type: str | None :value: None .. py:attribute:: parameters :type: tuple[Parameter, Ellipsis] :value: () .. py:attribute:: environment :type: tuple[tuple[str, str, bool], Ellipsis] :value: () .. py:attribute:: chooses_devices :type: bool :value: False .. py:property:: groups :type: list[str] The parameter groups, in the order they were declared. .. py:method:: in_group(group: str) -> list[Parameter] The parameters of *group*, in declaration order. .. py:property:: required_env :type: list[str] The environment variables a run cannot do without. .. py:method:: missing_env(values: collections.abc.Mapping[str, str]) -> list[str] The required variables *values* does not set, or sets empty. :param values: 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. .. py:method:: parse(text: str) -> ExperimentManifest :classmethod: Read a manifest from what ``--manifest`` printed. :param text: The command's standard output. :returns: The manifest. :raises ManifestError: If the output is not the document it should be. .. py:function:: _parameters(schema: collections.abc.Mapping[str, Any]) -> list[Parameter] Flatten a manifest's grouped schema into parameters. A malformed entry is skipped rather than raising: the console is showing what a module said about itself, and one unreadable parameter is not a reason to offer none of the others. :param schema: The manifest's ``schema`` block. :returns: The parameters, groups in declaration order. .. py:function:: _environment(raw: Any) -> list[tuple[str, str, bool]] Read the manifest's environment declarations. :param raw: The manifest's ``environment`` block. :returns: One ``(name, description, required)`` per readable entry. .. py:function:: _number(value: Any) -> float | None Return *value* as a float, or ``None`` when it is not one.