host.os_profile

Named OS profiles: a higher-level selector layered over the host base classes.

The osType field in lab data selects an OsProfile; the value is stamped onto the constructed host’s osType attribute as the profile selector. A profile records which base registered host class to build (e.g. UnixHost or EmbeddedHost) plus a bundle of default field values that the storage factory merges beneath each host’s own fields. This lets many hosts that share a characteristic bundle (e.g. a particular Zephyr build’s command_frame / filesystem / max_filename_len) name that bundle once instead of copy-pasting it into every hosts.json entry.

Profiles are authorable two ways, both feeding the same registry:

  • Data — an [os_profiles.<name>] table in .otto/settings.toml (parsed by Repo._parseOsProfiles), registered at settings parse time.

  • Coderegister_os_profile() called from an init module listed in .otto/settings.toml (the same hook otto.host.command_frame.register_command_frame() uses), so third-party libraries can ship profiles. Init modules import after settings parse, so a code registration overrides a data table of the same name (last writer wins).

The registry mirrors command_frame._FRAME_CLASSES and embedded_filesystem._FILESYSTEM_CLASSES.

A companion registry — _HOST_CLASSES / register_host_class() — maps a name to a concrete RemoteHost subclass. Built-in classes (unixUnixHost, embeddedEmbeddedHost, zephyrZephyrHost) are registered at module load. An OsProfile names one of these via its base field, and registering a class auto-registers a same-named trivial profile, so osType: <name> resolves with no extra config.

Registering a custom host class

To ship a host subclass from an external repo:

  1. Subclass EmbeddedHost or UnixHost (whichever family fits).

  2. Call register_host_class('myos', MyHost) from an init module listed in .otto/settings.toml — the same hook otto.host.command_frame.register_command_frame() uses.

  3. Optionally call register_os_profile('myos-v1', base='myos', defaults={...}) to layer a per-build data bundle (e.g. a specific command_frame, max_filename_len, or osName) over the class, selectable via osType: myos-v1 in hosts.json.

ZephyrHost is the in-tree worked example: it subclasses EmbeddedHost, declares Zephyr- specific defaults, and is registered under "zephyr" at module load.

otto.host.os_profile.BaseFamily

The name of a registered host class an OsProfile builds.

Built-ins: unix (UnixHost), embedded (EmbeddedHost), zephyr (ZephyrHost). Register more with register_host_class().

class otto.host.os_profile.OsProfile(name, base, defaults=<factory>)

Bases: object

A named bundle of host defaults over a base family.

The defaults dict holds raw values exactly as a hosts.json entry would (strings for command_frame / filesystem, dicts for the *_options tables, plain scalars otherwise). The storage factory merges them beneath the host’s own fields and runs its existing string→instance coercion, so the profile never has to build typed objects itself.

name : --is-rst--:py:class:`str`

The osType selector this profile is registered under.

base : --is-rst--:py:class:`str`

Name of the registered host class the profile builds (e.g. unix, embedded, zephyr, or a custom class registered via register_host_class()).

defaults : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:data:`~typing.Any`]

Raw field defaults merged beneath a host’s own hosts.json fields.

otto.host.os_profile.register_host_class(name, cls)

Register a host class so lab data can select it by osType.

Mirrors otto.host.command_frame.register_command_frame(). Call from an init module listed in .otto/settings.toml to ship a custom host subclass. Registering a class also registers a trivial same-named OsProfile (base=name, empty defaults), so osType: name resolves with no extra config. Re-registering replaces the prior class.

Return type:

None

Raises

ValueError

If cls is not a RemoteHost subclass.

otto.host.os_profile.build_host_class(name)

Return the host class registered under name (raising on miss).

Return type:

type

otto.host.os_profile.get_host_class(name)

Return the host class registered under name, or None.

Non-raising counterpart to build_host_class(), for callers that produce their own error (e.g. otto.storage.factory.validate_host_dict()).

Return type:

type | None

otto.host.os_profile.register_os_profile(name, base, defaults=None)

Register an OsProfile so lab data can select it by osType.

Call from an init module listed in .otto/settings.toml — the same pattern otto.host.command_frame.register_command_frame() follows. Re-registering a name replaces the previous profile (last writer wins); overriding a built-in (unix / embedded / zephyr) logs a warning.

Return type:

None

Parameters

namestr

The osType string lab-data entries will use to select this profile.

basestr

Name of a registered host class (e.g. 'unix' or 'embedded').

defaultsdict[str, Any] | None

Raw field defaults merged beneath each host’s own fields. Keys are validated against the base class’s fields.

Raises

ValueError

If base is not a registered host class name, or if a defaults key is not a field on the base class (a likely typo).

otto.host.os_profile.build_os_profile(name)

Return the OsProfile registered under name.

Used by otto.storage.factory.create_host_from_dict() to resolve a host’s osType to its base family and default bundle.

Return type:

OsProfile

Raises

ValueError

If name is not registered. The error lists the registered names so a typo is diagnosable from the message alone.

otto.host.os_profile.get_os_profile(name)

Return the registered OsProfile for name, or None.

Non-raising counterpart to build_os_profile(), used by otto.storage.factory.validate_host_dict() so validation can produce its own error message.

Return type:

OsProfile | None

otto.host.os_profile.registered_profile_names()

Return the sorted names of all currently registered profiles.

Return type:

list[str]