protomotions.utils.config_utils module#
- protomotions.utils.config_utils.is_union(ann)[source]#
Whether a resolved annotation is a union in either spelling.
- protomotions.utils.config_utils.declaring_module(cls, name)[source]#
The module of the class in
cls’s MRO that declares fieldname.A field’s annotation string (
from __future__ import annotations) names types imported where the field is DECLARED; a subclass in another module inherits the field without those imports, so the string is evaluated against the declaring class’s module, astyping.get_type_hintsdoes. Falls back tocls.__module__for a name no class in the MRO annotates.
- protomotions.utils.config_utils.resolve_field_annotation(cls, name)[source]#
The resolved annotation of
cls.name, from that field alone; raises TypeError naming the field when the annotation string cannot be evaluated.The one per-field resolver shared by the B4 saved form (
config_schema) and the B3 override funnel. Resolving the whole class (get_type_hints) would fail whenever any OTHER field carries a name that does not resolve; resolving per field keeps one unrelated sibling from breaking every field being saved or overridden. The field’s type must be importable at the level of the module that DECLARES the field (an inherited field resolves in its base class’s module, asget_type_hintsdoes; config.py imports MdpComponent and TerminationRule there) and spelled so this Python can evaluate it (PEP 604 unions and builtin generics need 3.10 / 3.9); an annotation that does not resolve is a real error, not a case to silence by returningAny(which would drop the None-for-non-Optional refusal at save).
- protomotions.utils.config_utils.coerce(value, ann, path, cls, name)[source]#
Coerce a parsed literal to a field’s declared annotation (never its runtime value).
- protomotions.utils.config_utils.apply_overrides(configs, overrides, roots=None)[source]#
Apply
{root.path: value}overrides to an ExperimentConfigs in place.The leaf is typed by its dataclass annotation, never by the runtime value, so a typo or a wrong type fails at parse time naming the field.
rootslimits which roots are applied (None= all), which lets the build funnel applyrobotandsimulatorearly and the rest after the build. Returns the coerced{path: value}that landed, for the undo check.
- protomotions.utils.config_utils.read_override(configs, path)[source]#
Read the current value at a
root.pathoverride path on an ExperimentConfigs.Walks the way the funnel does (a dict step by key, a dataclass or any other object by attribute). The inference derivation and the build-time undo check read back through this to see whether a builder step changed an early override.
- protomotions.utils.config_utils.parse_cli_overrides(override_strings)[source]#
Parse command-line override strings into a dictionary.
Supports the format: “key=value” where value can be: - Numbers: “env.max_episode_length=1000” - Floats: “agent.learning_rate=1e-5” - Booleans: “env.enable_terrain=True” - Strings: “env.terrain.type=flat” - None: “env.early_termination=None”
- Parameters:
override_strings (list) – List of “key=value” strings
- Returns:
Dictionary of parsed overrides
- Raises:
ValueError – If any override string is not in “key=value” format or key is empty.
- Return type:
Example
parse_cli_overrides([“env.max_episode_length=1000”, “simulator.num_envs=4096”]) # Returns: {“env.max_episode_length”: 1000, “simulator.num_envs”: 4096}