Skip to content

Python API

Every bosh subcommand delegates to a Python function in the same package, so the CLI is reproducible from Python in two or three lines. This page is auto-generated from the docstrings — if anything reads oddly, it's a hint to improve the docstring in source.

Quick reference

Task Function
Parse a descriptor (path / URL / dict / JSON) load
Validate (structural + semantic + lint) validate
Generate a sample invocation generate
Resolve to argv resolve
Shell-safe display string simulate
Run the tool launch
Run descriptor tests run_tests
Tree view pprint
JSON Schema artifacts export_all

Loading

load

load(source: str | Path | dict[str, Any]) -> AnyDescriptor

Load a descriptor from a file path, URL, dict, or JSON string.

The schema-version field selects the model. Unknown versions raise DescriptorLoadError.

DescriptorLoadError

Bases: Exception

Raised when a descriptor cannot be parsed or its schema-version is unknown.

Validation

Top-level

validate

validate(source: str | Path | dict[str, Any]) -> ValidationResult

Validate a descriptor and return a ValidationResult.

ValidationResult dataclass

ValidationResult(
    descriptor: AnyDescriptor | None = None,
    errors: list[ValidationError] = list(),
    warnings: list[LintIssue] = list(),
)

Outcome of validating a descriptor.

ok property

ok: bool

True if there are no hard errors. Warnings do not affect this.

ValidationError dataclass

ValidationError(location: str, message: str)

A single validation failure with a JSON-pointer-style location.

Lint advisories

lint

lint(descriptor: AnyDescriptor) -> list[LintIssue]

Return advisory issues for a successfully loaded descriptor.

LintIssue dataclass

LintIssue(field: str, message: str, level: str = 'warning')

A non-blocking advisory about a descriptor.

Cross-field semantic checks

check

check(descriptor: AnyDescriptor) -> list[ValidationError]

Run all semantic checks; return every error found.

Example generation

generate

generate(descriptor: AnyDescriptor, complete: bool = False) -> dict[str, Any]

Return a sample invocation dict for descriptor.

By default, required inputs are populated. With complete=True, optional inputs are populated as well. Sub-command unions pick the first candidate.

Flag inputs are treated as effectively optional regardless of their declared optional field — at the runtime layer a flag's absence and value=false are indistinguishable, so a minimum invocation omits all flags. (This matches the v0.5+styx spec author's note that optional has no meaning for Flag inputs.)

Execution

resolve

resolve(descriptor: AnyDescriptor, invocation: dict[str, Any]) -> list[str]

Validate the invocation and return the resolved argv token list.

Three layers run before resolution: structural (Pydantic), cross-input (requires/disables/value-requires/value-disables), and group constraints. Any failure raises :class:InvocationValidationError.

simulate

simulate(descriptor: AnyDescriptor, invocation: dict[str, Any]) -> str

Return the resolved command-line as a shell-safe string.

launch

launch(
    descriptor: AnyDescriptor,
    invocation: dict[str, Any],
    *,
    runtime: str = "local",
    cwd: Path | None = None,
    runtime_args: list[str] | None = None,
    stream: bool = True,
    capture: bool = True,
) -> LaunchResult

Resolve the invocation and run the tool under the chosen runtime.

LaunchResult dataclass

LaunchResult(
    command: list[str],
    runtime: str,
    exit_code: int,
    stdout: str,
    stderr: str,
    duration_seconds: float,
    outputs: list[ResolvedOutput] = list(),
)

Outcome of a launch: what was run, what came back, what was declared.

ResolvedOutput dataclass

ResolvedOutput(
    id: str,
    name: str,
    path: Path | None = None,
    exists: bool = False,
    content: str | None = None,
)

A declared output after the run.

path is set for file-based outputs (path-template / conditional-path-template); content is set for stdio-based outputs (stdout-output / stderr-output). The two are mutually exclusive.

resolve_output_paths

resolve_output_paths(
    descriptor: AnyDescriptor, invocation: dict[str, Any], cwd: Path
) -> list[ResolvedOutput]

Resolve every declared file output against the invocation values.

Stdio outputs (stdout-output / stderr-output) are populated by :func:boutiques.execution.launch.launch after the run, since they need the captured output content.

resolve_stdio_outputs

resolve_stdio_outputs(
    descriptor: AnyDescriptor, stdout: str, stderr: str
) -> list[ResolvedOutput]

Populate ResolvedOutput entries for any declared stdout-/stderr-output.

collect_file_mounts

collect_file_mounts(
    descriptor: AnyDescriptor, invocation: dict[str, Any]
) -> list[Path]

Return absolute parent dirs of every File-typed value in the invocation.

RunResult dataclass

RunResult(exit_code: int, stdout: str, stderr: str, duration_seconds: float)

Outcome of a single runtime execution.

RuntimeError_

Bases: RuntimeError

Raised when a runtime can't satisfy a descriptor (e.g. missing image).

Invocation model

invocation_model_for

invocation_model_for(
    descriptor_or_subcommand: AnyDescriptor | SubCommandType,
) -> type[BaseModel]

Return a Pydantic model that validates invocations for the given target.

Works for top-level descriptors and recursively for SubCommandType instances. The id discriminator field expected on sub-command union members is injected by _subcommand_model, not here.

InvocationModelError

Bases: Exception

Raised when the invocation model cannot be built for a descriptor.

validate_invocation

validate_invocation(
    descriptor: AnyDescriptor, invocation: dict[str, Any]
) -> list[ValidationError]

Validate invocation against descriptor; return every error found.

InvocationValidationError

InvocationValidationError(errors: list[ValidationError])

Bases: Exception

Raised when an invocation fails any of the validation tiers.

Test runner

run_tests

run_tests(
    descriptor: AnyDescriptor,
    *,
    runtime: str = "local",
    cwd: Path | None = None,
) -> TestRunResults

Run every test case declared on descriptor.

TestRunResults dataclass

TestRunResults(descriptor_name: str, cases: list[TestCaseResult] = list())

Outcome of running every test case in a descriptor.

TestCaseResult dataclass

TestCaseResult(
    name: str,
    exit_code: int,
    duration_seconds: float,
    failures: list[str] = list(),
)

Outcome of running one test case.

Pretty-printing

pprint

pprint(descriptor: AnyDescriptor, *, console: Console | None = None) -> None

Print a tree view of descriptor to the console.

build_tree

build_tree(descriptor: AnyDescriptor) -> Tree

Return the :class:rich.tree.Tree representing a descriptor.

JSON Schema export

schema_for

schema_for(version: str) -> dict[str, Any]

Return the JSON Schema for a given Boutiques schema version.

export_all

export_all(out_dir: Path) -> list[Path]

Write descriptor.schema.json for every known version under out_dir.

VERSIONS module-attribute

VERSIONS: dict[str, type[BaseModel]] = {
    "0.5": Descriptor,
    "0.5+styx": Descriptor,
}

Descriptor models

Pydantic models live under boutiques.models.v05 and boutiques.models.v05_styx. For day-to-day use, load returns the right one based on the descriptor's schema-version; the models themselves are documented mostly via the specification. The JSON Schema artifacts under docs/schema/ are generated from these models.