bootstrap

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

Replaces configmodule’s import-time side effects. Phase 1 (discovery) parses the environment and repo settings.toml files — no user code runs. 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.

class otto.bootstrap.BootstrapResult(env: OttoEnvSettings, repos: list[Repo], errors: list[~otto.bootstrap.BootstrapError] = <factory>)

Bases: object

Everything bootstrap produced: environment, repos, contained errors.

env : OttoEnvSettings
repos : list[Repo]
errors : list[BootstrapError]
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 + contained 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.