configmodule¶
The configmodule package handles environment variables, repository discovery, settings parsing, and lab loading.
-
class otto.configmodule.configmodule.ConfigModule(repos, lab, reservation_backend=
None, identity=None, skip_reservation_check=False)¶ Bases:
object- repos : --is-rst--:py:class:`list`\ \[:py:class:`~otto.configmodule.repo.Repo`]¶
Repos under test.
- lab : --is-rst--:py:class:`~otto.configmodule.lab.Lab`¶
All lab information, like hosts, version information, etc.
-
reservation_backend : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`~otto.reservations.protocol.ReservationBackend`] =
None¶ Configured reservation backend, or
Noneif the repo has no[reservations]settings wired up yet.
-
identity : --is-rst--:py:data:`~typing.Optional`\ \[:py:class:`~otto.reservations.identity.ResolvedIdentity`] =
None¶ Effective reservation identity for this invocation (set by the top-level CLI callback after parsing
--as-user).
-
skip_reservation_check : --is-rst--:py:class:`bool` =
False¶ Truewhen-R/--skip-reservation-checkis on the command line.
- logRepoCommits()¶
- class otto.configmodule.configmodule.ConfigModuleManager¶
Bases:
object- property configModule : ConfigModule¶
- otto.configmodule.configmodule.getConfigModule()¶
- otto.configmodule.configmodule.tryGetConfigModule()¶
Return the active ConfigModule, or None if none has been set.
Unlike
getConfigModule(), this does not raise when the singleton is uninitialized. Used by code paths (e.g. the reservationgate) that must be callable from unit tests which invoke subcommand apps directly without going through the top-levelmaincallback.- Return type:¶
Optional[ConfigModule]
-
otto.configmodule.configmodule.setConfigModule(configModule=
None, lab=None, repos=None, reservation_backend=None, identity=None, skip_reservation_check=False)¶
-
otto.configmodule.configmodule.all_hosts(pattern=
None, *, include_containers=False, ssh_options=None, telnet_options=None, sftp_options=None, scp_options=None, ftp_options=None, nc_options=None)¶ Yield the active lab’s real remote hosts, optionally filtered by regex.
This is the fleet generator: by default it yields only real
RemoteHostinstances and skipsDockerContainerHostentries, since containers aren’t operated on as part of the host fleet (e.g.otto monitor, coverage collection). Containers remain reachable for targeted use via tab completion andget_host— neither of which goes through this generator. Passinclude_containers=Trueto yield container hosts as well.- Parameters:¶
pattern – Compiled regex matched against each host’s
idviapattern.search(). When None (the default), all hosts are yielded.include_containers – When
True, also yieldDockerContainerHostentries. Defaults toFalse.ssh_options, telnet_options, sftp_options, scp_options,
ftp_options, nc_options – Optional per-call option overrides. When supplied, each yielded host is a fresh
dataclasses.replace()-style copy whose corresponding*_optionsfield is replaced by the caller’s instance (wholesale replacement, not per-key merge). The new host has a freshConnectionManagerconstructed with the override options, so the override values shape whichever connection opens first. Stored hosts inlab.hostsare untouched. When no overrides are passed, the stored instances are yielded as-is so identity is preserved. Hop resolution is internal and is not affected by overrides.
- Yields:¶
RemoteHost – Each matching host from the lab configuration.
Examples
>>> import re >>> # assuming hosts: carrot_seed, tomato_seed, pepper_seed >>> seeds = list(all_hosts(re.compile(r"tomato")))- Return type:¶
Generator[RemoteHost,Any,Any]
-
async otto.configmodule.configmodule.do_for_all_hosts(method, *args, pattern=
None, concurrent=True, include_containers=False, ssh_options=None, telnet_options=None, sftp_options=None, scp_options=None, ftp_options=None, nc_options=None, **kwargs)¶ Call an async host method on every matching host.
- Parameters:¶
method – Unbound async method (e.g.
RemoteHost.oneshot).*args – Positional arguments forwarded to method after the host.
pattern – Compiled regex filter passed to
all_hosts().concurrent – When
True(default), run all calls viaasyncio.gatherwithreturn_exceptions=True. WhenFalse, execute serially.include_containers – Forwarded to
all_hosts(). WhenFalse(default), container hosts are excluded.ssh_options, telnet_options, sftp_options, scp_options,
ftp_options, nc_options – Optional per-call option overrides forwarded to
all_hosts(). See its docstring for semantics.**kwargs – Keyword arguments forwarded to method.
- Return type:¶
dict[str,Union[TypeVar(T),BaseException]]- Returns:¶
A dict keyed by host ID. Values are the return of method, or a
BaseExceptionif that host’s call failed.
Examples
>>> import re >>> from otto.host import RemoteHost >>> results = await do_for_all_hosts( ... RemoteHost.oneshot, "uname -a", ... pattern=re.compile(r"router"), ... )
-
async otto.configmodule.configmodule.run_on_all_hosts(cmds, pattern=
None, concurrent=True, timeout=None, *, include_containers=False, ssh_options=None, telnet_options=None, sftp_options=None, scp_options=None, ftp_options=None, nc_options=None)¶ Run commands on every matching host via
RemoteHost.run().Convenience wrapper around
do_for_all_hosts()for the most common use case.- Parameters:¶
cmds – Command string or list of command strings.
pattern – Compiled regex filter passed to
all_hosts().concurrent – When
True(default), run all calls viaasyncio.gather. WhenFalse, execute serially.timeout – Per-host timeout forwarded to
run.include_containers – Forwarded to
do_for_all_hosts(). WhenFalse(default), container hosts are excluded.ssh_options, telnet_options, sftp_options, scp_options,
ftp_options, nc_options – Optional per-call option overrides forwarded to
do_for_all_hosts().
- Return type:¶
dict[str,RunResult|BaseException]- Returns:¶
A dict keyed by host ID. Values are
RunResultinstances, or aBaseExceptionif that host’s call failed.
Examples
>>> results = await run_on_all_hosts("uname -a")
-
otto.configmodule.configmodule.get_host(host_id, *, ssh_options=
None, telnet_options=None, sftp_options=None, scp_options=None, ftp_options=None, nc_options=None)¶ Return the host registered under host_id in the active lab.
- Parameters:¶
host_id – Unique host id (as produced by
RemoteHost.id).ssh_options, telnet_options, sftp_options, scp_options,
ftp_options, nc_options – Optional per-call option overrides. Each non-
Noneargument replaces the corresponding*_optionsfield on a returned copy wholesale; the copy is built viadataclasses.replace()so the new host’sConnectionManageris constructed with the override options from the start. The stored host (and any connection it owns) is untouched. With no overrides, the stored instance is returned unchanged soget_host('x') is get_host('x')still holds. Hop resolution is internal and is not affected by overrides.
- Return type:¶
Environment variables that are needed before parsing CLI arguments
- class otto.configmodule.env.OttoEnv¶
Bases:
objectOtto environment variables
- sutDirs : --is-rst--:py:class:`list`\ \[:py:class:`~pathlib.Path`]¶
- class otto.configmodule.lab.Lab(name, resources=<factory>, hosts=<factory>)¶
Bases:
object- name : --is-rst--:py:class:`str`¶
Name of this lab.
- resources : --is-rst--:py:class:`set`\ \[:py:class:`str`]¶
Resources required to reserve this lab.
- hosts : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:class:`~otto.host.host.Host`]¶
Host objects, keyed by unique host id.
-
otto.configmodule.lab.getLab(labnames, search_paths=
None, defaults=None)¶ Perform all actions necessary to build a Lab object based on a list of lab names.
Parameters¶
- labnamesstr | list[str]
Name(s) of lab data to retrieve.
- search_pathslist[Path] | None
Directories to search for lab data.
- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults applied to every host in the resulting lab. Keys are
*_optionstable names; values are per-field dicts merged beneath each host’s own options.
Returns¶
- Lab
Fully defined lab instance.
-
class otto.configmodule.repo.DockerImage(name, dockerfile, context, target=
None, build_args=())¶ Bases:
objectA Dockerfile-built image declared by a project.
- name : --is-rst--:py:class:`str`¶
Short logical name used in tags and CLI selection.
- dockerfile : --is-rst--:py:class:`~pathlib.Path`¶
Absolute path to the Dockerfile.
- context : --is-rst--:py:class:`~pathlib.Path`¶
Absolute path to the build context directory.
-
target : --is-rst--:py:class:`str` | :py:obj:`None` =
None¶ Optional multi-stage build target.
-
build_args : --is-rst--:py:class:`tuple`\ \[:py:class:`tuple`\ \[:py:class:`str`, :py:class:`str`], :py:data:`...<Ellipsis>`] =
()¶ Frozen list of (name, value) build args. Tuples (not dicts) so the container is hashable and order is preserved for context-hash inputs.
-
class otto.configmodule.repo.DockerCompose(path, default_host=
None, services=())¶ Bases:
objectA docker-compose file contributed by a project.
- path : --is-rst--:py:class:`~pathlib.Path`¶
Absolute path to the compose YAML file.
-
default_host : --is-rst--:py:class:`str` | :py:obj:`None` =
None¶ Lab host id where this stack should run by default. Overridden by
otto docker up --on <host>.
-
services : --is-rst--:py:class:`tuple`\ \[:py:class:`str`, :py:data:`...<Ellipsis>`] =
()¶ Service names declared in the compose file. Used to synthesize container host ids for tab-completion without parsing YAML at completion-fast-path time. The runtime is the source of truth and will warn on mismatch with
docker compose config --services.
-
class otto.configmodule.repo.DockerSettings(registry_url=
'docker.io', images=(), composes=())¶ Bases:
objectPer-repo docker configuration parsed from [docker] in settings.toml.
-
registry_url : --is-rst--:py:class:`str` =
'docker.io'¶ Default registry. Overridable per-image via the image’s tag prefix.
-
images : --is-rst--:py:class:`tuple`\ \[:py:class:`~otto.configmodule.repo.DockerImage`, :py:data:`...<Ellipsis>`] =
()¶ Images this project knows how to build.
-
composes : --is-rst--:py:class:`tuple`\ \[:py:class:`~otto.configmodule.repo.DockerCompose`, :py:data:`...<Ellipsis>`] =
()¶ Compose files this project contributes.
-
registry_url : --is-rst--:py:class:`str` =
- class otto.configmodule.repo.CollectedTest(nodeid, name, path, cls_name)¶
Bases:
objectA single test item collected from a SUT repo’s test directories.
Attributes¶
- nodeid :
Full pytest node ID, e.g.
dir/test_x.py::ClassName::test_fn. Suitable for use directly as theSUITEargument tootto test.- name :
Test function name only, e.g.
test_fn.- path :
Absolute path to the test file.
- cls_name :
Class name if the test belongs to a class, else
None.
- nodeid : --is-rst--:py:class:`str`¶
- name : --is-rst--:py:class:`str`¶
- path : --is-rst--:py:class:`~pathlib.Path`¶
- cls_name : --is-rst--:py:class:`str` | :py:obj:`None`¶
- class otto.configmodule.repo.Repo(sutDir, settings=<factory>)¶
Bases:
object- sutDir : --is-rst--:py:class:`~pathlib.Path`¶
SUT directory from which the settings came.
- name : --is-rst--:py:class:`str`¶
Product/repo name
- version : --is-rst--:py:class:`~otto.configmodule.version.Version`¶
Product version
- labs : --is-rst--:py:class:`list`\ \[:py:class:`~pathlib.Path`]¶
Paths to lab data
- libs : --is-rst--:py:class:`list`\ \[:py:class:`~pathlib.Path`]¶
Extra paths to add to the PYTHONPATH
- init : --is-rst--:py:class:`list`\ \[:py:class:`str`]¶
Module paths that need to be imported during otto init.
Modules containing instructions are an example of modules that need to be imported eagerly.
- tests : --is-rst--:py:class:`list`\ \[:py:class:`~pathlib.Path`]¶
Directories that contain test suites.
- host_defaults : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:class:`dict`\ \[:py:class:`str`, :py:data:`~typing.Any`]]¶
Per-protocol option defaults applied to every host loaded under this repo’s labs. Keys are
*_optionstable names (ssh_options,telnet_options, etc.); values are dicts whose keys correspond to fields on the matching options dataclass.
- settings : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:data:`~typing.Any`]¶
Repo settings dict as parsed from the settings.toml file
- docker_settings : --is-rst--:py:class:`~otto.configmodule.repo.DockerSettings`¶
Parsed [docker] table — image build definitions, compose files, and registry URL. Defaults to an empty
DockerSettingswhen the section is absent.
- getInstructionsPanel()¶
Build a Rich panel listing all instructions contributed by this repo.
Instructions are attributed to this repo by matching each registered instruction’s module against the module prefixes in
init.- Return type:¶
Panel
- collectTests()¶
Collect all tests from this repo’s configured test directories.
Performs a single pytest collection pass (no tests are executed). The returned list can be passed to any of the
get*Panelmethods so that multiple listing options share one collection run.- Return type:¶
list[CollectedTest]
Returns¶
- list[CollectedTest]
One entry per discovered test item, in collection order.
- getTestsPanel(items)¶
Rich panel listing every individual test with its full run syntax.
Each line shows
otto test <absolute-path>::[Class::]test_fnwhich can be copy-pasted directly to run that specific test regardless of the current working directory.- Return type:¶
Panel
Parameters¶
- items :
Pre-collected tests from
collectTests().
- getTestFilesPanel(items)¶
Rich panel listing unique test files with their run syntax.
Each line shows
otto test <absolute-path>which runs all tests in that file.- Return type:¶
Panel
Parameters¶
- items :
Pre-collected tests from
collectTests().
- getTestSuitesPanel(items)¶
Rich panel listing unique test suites with their run syntax.
Only class-based tests are listed, using just
ClassName— the subcommand name passed directly tootto test ClassName. Bare functions (not part of a class) are omitted since they have no correspondingotto testsubcommand. Entries are de-duplicated and preserve collection order.- Return type:¶
Panel
Parameters¶
- items :
Pre-collected tests from
collectTests().
- getOttoSettingsPath()¶
Create the path to the otto settings TOML file.
- Return type:¶
Path
Returns¶
Path to the otto settings TOML file.
Raises¶
- FileNotFoundError
If the TOML file is not found.
- property reservationSettings : dict[str, Any]¶
Return the
[reservations]settings sub-dict with ${sutDir} expanded.Returns an empty dict when the section is absent. Every string value (including nested tables) has
${sutDir}substituted so the reservation backend can use the same path-expansion convention as the other repo settings.
- importTestFiles()¶
Import test_*.py files from each configured tests directory.
This triggers
@register_suite()decorators, which populateotto.suite.register._SUITE_REGISTRYat import time. The registry is later consumed bycli/test.pyto add sub-Typers totesting_app.- Return type:¶
None
- applySettings()¶
- async setGitDescription()¶
- async setCommitHash()¶
- property commit¶
- property description¶
- property commitName : str¶