bootstrap

otto’s composition root: repo discovery + contained user-code registration.

Replaces config’s import-time side effects. Phase 1 (discovery) parses the environment and repo settings.toml files — no user code runs. Between phase 1 and phase 2 the dependency pass (config.dependencies) validates each repo’s declared dependencies, skips repos whose required deps are unsatisfied (framed DependencyErrors), and orders phase-2 registration topologically (stable — sut-dir order when no deps are declared). Phase 2 (registration) imports each repo’s init modules and test files, wrapping every user-module exec so one broken file becomes a framed BootstrapError instead of bricking the process. Lab loading is deliberately NOT part of bootstrap — it happens lazily at first access.

bootstrap() is idempotent: the CLI entrypoint calls it before argv parsing, open_context() calls it lazily, and repeated calls return the same BootstrapResult.

exception otto.bootstrap.BootstrapError(sut_dir: Any, source: str, cause: BaseException)

Bases: Exception

One user file failed to load during bootstrap registration.

exception otto.bootstrap.DependencyError(sut_dir: Any, message: str)

Bases: BootstrapError

A repo’s declared dependencies cannot be satisfied (or a dependency was skipped).

class otto.bootstrap.BootstrapWarning(sut_dir: Any, message: str)

Bases: object

A non-fatal dependency finding: rendered at startup, never gates dispatch.

sut_dir : Any
message : str
class otto.bootstrap.BootstrapResult(env: OttoEnvSettings, repos: list[Repo], errors: list[~otto.bootstrap.BootstrapError] = <factory>, warnings: list[~otto.bootstrap.BootstrapWarning] = <factory>)

Bases: object

Everything bootstrap produced: environment, repos, contained errors.

env : OttoEnvSettings
repos : list[Repo]
errors : list[BootstrapError]
warnings : list[BootstrapWarning]
otto.bootstrap.discover() tuple[OttoEnvSettings, list[Repo]]

Phase 1: env + repo discovery (settings parse only — no user code). Cached.

Per-repo config-data failures (unreadable or malformed settings.toml) get the same containment as phase-2 user-code failures: the repo is skipped and a framed BootstrapError is recorded, surfacing via bootstrap().errors (help degrades, real dispatch fails loud). Env-level failures (bad OTTO_SUT_DIRS / OTTO_* values) still raise — with no environment there is nothing to degrade to.

otto.bootstrap.bootstrap() BootstrapResult

Run the composition root (idempotent): discovery, dependency pass, registration.

otto.bootstrap.set_completion_names(names: dict[str, Any] | None) None

Install the completion-cache snapshot (fast path; set by the CLI entry).

otto.bootstrap.get_completion_names() dict[str, Any] | None

Return the completion-cache snapshot, or None outside the fast path.