configmodule¶
The configmodule package handles environment variables, repository discovery, settings parsing, and lab loading.
Fleet host access and host-dispatch helpers for the active lab.
-
otto.configmodule.configmodule.all_hosts(pattern: Pattern[str] | None =
None, *, include_containers: bool =False, term: str | None =None, transfer: str | None =None, ssh_options: SshOptions | None =None, telnet_options: TelnetOptions | None =None, sftp_options: SftpOptions | None =None, scp_options: ScpOptions | None =None, ftp_options: FtpOptions | None =None, nc_options: NcOptions | None =None) Generator[RemoteHost, Any, Any]¶ Yield the active lab’s real remote hosts, optionally filtered by regex.
This is the fleet generator: it yields every network-reached
RemoteHostin the active lab — bothUnixHost(SSH/telnet to a shell) andEmbeddedHost(telnet to an RTOS console).DockerContainerHostentries are skipped by default because 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. 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.term, transfer – optional active-protocol override; see
_apply_option_overrides.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. Override keys that don’t correspond to a field on a given host are silently dropped — e.g.ssh_optionsis ignored for anEmbeddedHost, which only carriestelnet_options. When no applicable overrides remain, the stored instance is yielded as-is so identity is preserved. Hop resolution is internal and is not affected by overrides.
- Yields:¶
RemoteHost – Each matching
UnixHostorEmbeddedHostfrom the lab configuration.
Examples
Filter the active lab’s hosts by id pattern (see Using otto as a library for a runnable, in-memory example):
import re seeds = list(all_hosts(re.compile(r"tomato")))
-
async otto.configmodule.configmodule.do_for_all_hosts(method: Callable[[...], Awaitable[T]], *args: Any, pattern: Pattern[str] | None =
None, concurrent: bool =True, include_containers: bool =False, term: str | None =None, transfer: str | None =None, ssh_options: SshOptions | None =None, telnet_options: TelnetOptions | None =None, sftp_options: SftpOptions | None =None, scp_options: ScpOptions | None =None, ftp_options: FtpOptions | None =None, nc_options: NcOptions | None =None, **kwargs: Any) dict[str, T | BaseException]¶ Call an async host method on every matching host.
- Parameters:¶
method – Unbound async method (e.g.
UnixHost.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.term, transfer – optional active-protocol override; see
_apply_option_overrides.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.
- Returns:¶
A dict keyed by host ID. Values are the return of method, or a
BaseExceptionif that host’s call failed.
Examples
Call an unbound async method on every matching host:
import re from otto.host import UnixHost results = await do_for_all_hosts( UnixHost.oneshot, "uname -a", pattern=re.compile(r"router"), )
-
async otto.configmodule.configmodule.run_on_all_hosts(cmds: list[str] | str, pattern: Pattern[str] | None =
None, concurrent: bool =True, timeout: float | None =None, *, include_containers: bool =False, term: str | None =None, transfer: str | None =None, ssh_options: SshOptions | None =None, telnet_options: TelnetOptions | None =None, sftp_options: SftpOptions | None =None, scp_options: ScpOptions | None =None, ftp_options: FtpOptions | None =None, nc_options: NcOptions | None =None) dict[str, RunResult | BaseException]¶ Run commands on every matching host via
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.term, transfer – optional active-protocol override; see
_apply_option_overrides.ssh_options, telnet_options, sftp_options, scp_options,
ftp_options, nc_options – Optional per-call option overrides forwarded to
do_for_all_hosts().
- Returns:¶
A dict keyed by host ID. Values are
RunResultinstances, or aBaseExceptionif that host’s call failed.
Examples
Run a command on every matching host:
results = await run_on_all_hosts("uname -a")
-
otto.configmodule.configmodule.get_host(host_id: str, *, term: str | None =
None, transfer: str | None =None, ssh_options: SshOptions | None =None, telnet_options: TelnetOptions | None =None, sftp_options: SftpOptions | None =None, scp_options: ScpOptions | None =None, ftp_options: FtpOptions | None =None, nc_options: NcOptions | None =None) UnixHost¶ Return the host registered under host_id in the active lab.
- Parameters:¶
host_id – Unique host id (as produced by
UnixHost.id).term, transfer – optional active-protocol override; see
_apply_option_overrides.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.
Environment variables that are needed before parsing CLI arguments.
-
otto.configmodule.env.validate_path(path: Path | None, must_exist: bool =
True) None¶ Validate that path exists when must_exist is
True.Raises
FileNotFoundErrorif the path is set but does not exist on disk. ANonepath is always accepted (the env var was not set).
- otto.configmodule.env.load_otto_env() OttoEnvSettings¶
Construct the OTTO_* env settings and validate that every sut_dir exists.
Raises FileNotFoundError (the historical OttoEnv() startup contract).
Lab dataclass and lab-loading utilities for assembling a host registry from lab data.
- class otto.configmodule.lab.Lab(name: str, resources: set[str] = <factory>, hosts: dict[str, Host] = <factory>)¶
Bases:
objectContainer for a named lab environment and its registered hosts.
A
Labaggregates theHostobjects parsed from lab data files under a single name. Multiple labs can be merged via+to build a composite environment that spans several lab data sources.
-
otto.configmodule.lab.load_lab(labnames: str | list[str], search_paths: list[Path] | None =
None, preferences: dict[str, dict[str, Any]] | None =None, repository: LabRepository | None =None) Lab¶ Build a Lab object from one or more lab names.
Parameters¶
- labnamesstr | list[str]
Name(s) of lab data to retrieve (a comma-separated string is split).
- search_pathslist[Path] | None
Directories searched by the default json backend. Ignored when
repositoryis supplied.- preferencesdict[str, dict[str, Any]] | None
The unified
{selector: {capability: [...] | option_table: {key: val}}}product-preference table applied to every host in the resulting lab.Nonereproduces today’s behavior.- repositoryLabRepository | None
A pre-built host-source backend (e.g. from
otto.storage.build_lab_repository()). WhenNone, a built-in json backend oversearch_pathsis used — preserving library/script behavior.
Returns¶
- Lab
Fully defined lab instance.
Repo settings loading, parsing, and test-collection helpers for SUT repositories.
-
class otto.configmodule.repo.DockerImage(name: str, dockerfile: Path, context: Path, target: str | None =
None, build_args: tuple[tuple[str, str], ...] =())¶ Bases:
objectA Dockerfile-built image declared by a project.
-
class otto.configmodule.repo.DockerCompose(path: Path, default_host: str | None =
None, services: tuple[str, ...] =())¶ Bases:
objectA docker-compose file contributed by a project.
-
class otto.configmodule.repo.DockerSettings(registry_url: str =
'docker.io', images: tuple[DockerImage, ...] =(), composes: tuple[DockerCompose, ...] =())¶ Bases:
objectPer-repo docker configuration parsed from [docker] in settings.toml.
-
registry_url : str =
'docker.io'¶ Default registry. Overridable per-image via the image’s tag prefix.
-
images : tuple[DockerImage, ...] =
()¶ Images this project knows how to build.
-
composes : tuple[DockerCompose, ...] =
()¶ Compose files this project contributes.
-
registry_url : str =
- class otto.configmodule.repo.CollectedTest(nodeid: str, name: str, path: Path, cls_name: str | None)¶
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.
- class otto.configmodule.repo.Repo(sut_dir: ~pathlib.Path, settings: dict[str, ~typing.Any] = <factory>)¶
Bases:
objectRuntime representation of a single SUT (system-under-test) repository.
Parsed from
.otto/settings.tomlat construction time (via__post_init__). Holds the resolved paths for lab data, test directories, and init modules, plus Docker and OS-profile settings contributed by that repo. MultipleRepoinstances are managed by the configmodule package whenOTTO_SUT_DIRSlists more than one directory.- valid_labs : list[str]¶
Lab names this repo supports (by
labsmembership), e.g. an embedded product that only runs in an embedded lab. Empty when the key is unset.Parsed here; enforcement — rejecting a selected
--labthat is not in this list, and treating an empty list as “the repo must declare its labs” rather than allow-all — is intentionally deferred to lab-selection time and not yet wired in. Parsing must not silently treat unset as allow-all.
- init : list[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.
- host_preferences : dict[str, dict[str, Any]]¶
Unified per-selector product preferences:
{regex_selector: {capability: [ordered backends] | option_table: {key: val}}}. The factory matches each host’sidagainst the selectors (definition-order cascade) and partitions the result into capability selections (forwarded to the resolver) and option-value defaults (applied per-key, product-wins).
- os_profiles : dict[str, OsProfile]¶
Named OS profiles declared by this repo’s
[os_profiles]settings, keyed by profile name. Each is also registered into the global os-profile registry at parse time so lab-data entries can select it by name in theos_typefield. Seeotto.host.os_profile.register_os_profile().
- logging_capture : list[str]¶
Explicit top-level logger prefixes from
[logging] capturewhoselogging.getLogger(__name__)records otto should route into its sinks, in addition to the package prefixes auto-derived frominit/libs. Seeproduct_log_prefixes().
- docker_settings : DockerSettings¶
Parsed [docker] table — image build definitions, compose files, and registry URL. Defaults to an empty
DockerSettingswhen the section is absent.
- get_lab_panel() Panel¶
Build a Rich panel listing all lab names available from this repo’s host source.
- get_instructions_panel() Panel¶
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.
- collect_tests() list[CollectedTest]¶
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.Returns¶
- list[CollectedTest]
One entry per discovered test item, in collection order.
- get_tests_panel(items: list[CollectedTest]) Panel¶
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.Parameters¶
- items :
Pre-collected tests from
collect_tests().
- get_test_files_panel(items: list[CollectedTest]) Panel¶
Rich panel listing unique test files with their run syntax.
Each line shows
otto test <absolute-path>which runs all tests in that file.Parameters¶
- items :
Pre-collected tests from
collect_tests().
- get_test_suites_panel(items: list[CollectedTest]) Panel¶
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.Parameters¶
- items :
Pre-collected tests from
collect_tests().
- get_otto_settings_path() Path¶
Create the path to the otto settings TOML file.
Returns¶
Path to the otto settings TOML file.
Raises¶
- FileNotFoundError
If the TOML file is not found.
- product_log_prefixes() set[str]¶
Top-level package names whose
getLogger(__name__)records otto captures.The set is declared init module roots, immediate sub-packages of each
libsdir, and explicit[logging] captureentries.
- property reservation_settings : dict[str, Any]¶
Return the
[reservations]settings sub-dict with ${sut_dir} expanded.Returns an empty dict when the section is absent. Every string value (including nested tables) has
${sut_dir}substituted so the reservation backend can use the same path-expansion convention as the other repo settings.
- property lab_settings : dict[str, Any]¶
Return the
[lab]settings sub-dict with${sut_dir}expanded.Returns an empty dict when the section is absent, so the host-source factory falls back to the built-in
jsonbackend over this repo’slabssearch paths.
- import_init_modules() None¶
Import each module path listed in
self.init.Importing these modules triggers any registration side effects they perform at module level — e.g. registering custom hosts, products, or term/transfer backends, or defining
@instructioncommands.
- import_test_files() None¶
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.
- apply_settings() None¶
Apply all repo settings.
Extends
sys.pathwith configured lib directories, imports init modules, and imports test files to trigger suite registration.
- async set_git_description() None¶
Populate
_git_descriptionfromgit describeoutput.Sets
_git_descriptionto the parenthesised tag description on success, or to an empty string whengit describefails (e.g. no tags exist in the repo).
- property commit : str | None¶
Return the full HEAD commit SHA, fetching it on first access if needed.
- property description : str | None¶
Return the cached
git describestring, fetching it on first access.The value is the parenthesised tag
"(<tag>)"on success, or""when no tags exist (Nonebefore the first access).
- otto.configmodule.repo.apply_repo_settings(repos: list[Repo]) None¶
Call
apply_settings()on eachRepoin repos in order.
- otto.configmodule.repo.get_repos(repos: list[Path]) list[Repo]¶
Create Repo objects from the list of provided repo paths.
Parameters¶
repos : List of paths to repos under test.
Returns¶
List of Repo objects
Raises¶
- FileNotFoundError
If a repo’s settings TOML file is not found.
Semantic version parsing for product version strings declared in settings.toml.
- class otto.configmodule.version.Version(version: str)¶
Bases:
objectParsed semantic version (major.minor.patch) from a product version string.
Constructed by passing a
"major.minor.patch"string to the constructor, which validates the format and populates the three integer fields.reprreturns the original dotted string.