models.settings

Pydantic boundary specs for .otto/settings.toml and the OTTO_* env.

These validate the settings dict (extra='forbid') and build the unchanged runtime objects (DockerSettings/DockerImage/DockerCompose frozen dataclasses, OsProfile, the reservation backend) via to_runtime() — the same two-type split the option/host specs use.

Leaf isolation: this module must NOT import from otto.configmodule at module top — doing so triggers configmodule/__init__’s app bootstrap. Runtime types from configmodule.repo are imported lazily inside to_runtime() and under TYPE_CHECKING for annotations only.

class otto.models.settings.DockerImageSpec(*, name: str, dockerfile: Path, context: Path, target: str | None = None, build_args: dict[str, Any] = {})

Bases: OttoModel

name : str
dockerfile : Path
context : Path
target : str | None
build_args : dict[str, Any]
to_runtime() DockerImage
class otto.models.settings.DockerComposeSpec(*, path: Path, default_host: str | None = None, services: tuple[str, ...] = ())

Bases: OttoModel

path : Path
default_host : str | None
services : tuple[str, ...]
to_runtime() DockerCompose
class otto.models.settings.DockerSettingsSpec(*, registry_url: str = 'docker.io', images: list[DockerImageSpec] = [], composes: list[DockerComposeSpec] = [])

Bases: OttoModel

registry_url : str
images : list[DockerImageSpec]
composes : list[DockerComposeSpec]
to_runtime() DockerSettings
class otto.models.settings.OsProfileSpec(*, base: str, **extra_data: Any)

Bases: OttoModel

A named [os_profiles.<name>] bundle: a required base host-class name plus an open bag of raw default field values merged beneath each host.

extra='allow' collects the non-base keys; the per-field typo guard runs later, in register_os_profile (against the base class’s slots), so the bundle stays raw here exactly as a hosts.json entry would be.

base : str
property defaults : dict[str, Any]
class otto.models.settings.ReservationConfigSpec(*, backend: str = 'none', url: str | None = None, **extra_data: Any)

Bases: OttoModel

The otto-owned [reservations] envelope: backend + optional url.

extra='allow' keeps the backend-specific [reservations.<backend>] sub-table open — otto-core cannot type a third-party backend’s kwargs.

backend : str
url : str | None
class otto.models.settings.LabConfigSpec(*, backend: str = 'json', **extra_data: Any)

Bases: OttoModel

The otto-owned [lab] envelope: which host-source backend to use.

extra='allow' keeps the backend-specific [lab.<backend>] sub-table open — otto-core cannot type a third-party backend’s kwargs. Defaults to the built-in "json" backend so repos with no [lab] block behave exactly as before.

backend : str
class otto.models.settings.ReservationEntry(*, user: str, resources: list[str], expires: datetime | None = None)

Bases: OttoModel

user : str
resources : list[str]
expires : datetime | None
class otto.models.settings.ReservationFile(*, version: 1, reservations: list[ReservationEntry] = [])

Bases: OttoModel

The version: 1 JSON reservation file the built-in JSON backend reads.

version : Literal[1]
reservations : list[ReservationEntry]
class otto.models.settings.SettingsModel(*, name: str, version: str, lab_data_type: str = 'json', coverage: dict[str, Any] = {}, labs: list[Path] = [], valid_labs: list[str] = [], libs: list[Path] = [], tests: list[Path] = [], init: list[str] = [], host_preferences: dict[str, dict[str, Any]] = {}, os_profiles: dict[str, OsProfileSpec] = {}, docker: DockerSettingsSpec = DockerSettingsSpec(registry_url='docker.io', images=[], composes=[]), lab: LabConfigSpec = LabConfigSpec(backend='json'), reservations: ReservationConfigSpec = ReservationConfigSpec(backend='none', url=None))

Bases: OttoModel

Boundary model for a repo’s .otto/settings.toml (post ${sut_dir} expansion). extra='forbid' turns a typo’d top-level key into an error.

name : str
version : str
lab_data_type : str
coverage : dict[str, Any]
labs : list[Path]
valid_labs : list[str]
libs : list[Path]
tests : list[Path]
init : list[str]
host_preferences : dict[str, dict[str, Any]]
os_profiles : dict[str, OsProfileSpec]
docker : DockerSettingsSpec
lab : LabConfigSpec
reservations : ReservationConfigSpec
class otto.models.settings.OttoEnvSettings

Bases: BaseSettings

Typed view of the OTTO_* environment surface. Single source of truth for the variables otto reads programmatically. (The six CLI-option vars are read by Typer’s envvar= at parse time; this model documents the whole surface and is the reader for the non-CLI reads: sut_dirs, field_default, compose_suffix, and the completion-cache xdir.)

sut_dirs existence-checking is done by configmodule.env.load_otto_env so a missing dir raises FileNotFoundError (not a wrapped ValidationError).

sut_dirs : Annotated[list[Path], NoDecode]
lab : str | None
xdir : Path | None
log_days : int
log_level : str
log_rich : bool
field_default : str | None
field_products : str | None
compose_suffix : str | None