Skip to content

parameter_paths

parameter_paths

Private schema-aware parameter path primitives.

Classes:

Name Description
ParameterPath

Canonical path to a parameter field.

ParameterFieldKind

Schema classification for a parameter field.

ParameterField

One indexed field in a parameter schema.

ParameterAlias

One accepted compatibility name and its canonical parameter path.

ResolvedParameterName

A parameter name resolved to one canonical path.

UnknownParameterName

A parameter name not present in the schema.

AmbiguousParameterName

A bare parameter name with multiple canonical candidates.

ParameterSchema

Indexed field paths for one Parameters model type.

Functions:

Name Description
format_parameter_path

Join path segments into the canonical dotted string.

classify_parameter_annotation

Classify a Pydantic field annotation as a branch or leaf.

split_parameter_path

Split a parameter name into a canonical path.

insert_parameter_value

Insert a value at an already resolved path.

ParameterPath(parts) dataclass

Canonical path to a parameter field.

ParameterFieldKind

Bases: Enum

Schema classification for a parameter field.

ParameterField(path, kind) dataclass

One indexed field in a parameter schema.

ParameterAlias(name, path) dataclass

One accepted compatibility name and its canonical parameter path.

ResolvedParameterName(path) dataclass

A parameter name resolved to one canonical path.

UnknownParameterName(name) dataclass

A parameter name not present in the schema.

AmbiguousParameterName(name, candidates) dataclass

A bare parameter name with multiple canonical candidates.

ParameterSchema(model_type, fields, aliases) dataclass

Indexed field paths for one Parameters model type.

Methods:

Name Description
from_model

Build a schema from Pydantic field annotations.

resolve

Resolve a canonical dotted or bare parameter name.

require

Resolve one name or raise a user-facing configuration error.

normalize_aliases

Translate declared aliases to canonical paths, with aliases taking precedence.

from_model(model_type) classmethod

Build a schema from Pydantic field annotations.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
@classmethod
def from_model(cls, model_type: type[Parameters]) -> Self:
    """Build a schema from Pydantic field annotations."""
    from .parameters import Parameters

    if not issubclass(model_type, Parameters):
        raise TypeError(f"Expected a Parameters model type, received {model_type!r}.")
    fields = tuple(_iter_parameter_fields(model_type))
    aliases = tuple(_iter_parameter_aliases(model_type))
    field_paths = {field.path for field in fields}
    for alias in aliases:
        if alias.path not in field_paths:
            raise TypeError(
                f"Parameter alias {alias.name!r} on {model_type.__name__} targets unknown path {str(alias.path)!r}."
            )
    return cls(model_type=model_type, fields=fields, aliases=aliases)

resolve(name, *, infer_bare_name=True)

Resolve a canonical dotted or bare parameter name.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def resolve(self, name: str, *, infer_bare_name: bool = True) -> ParameterNameResolution:
    """Resolve a canonical dotted or bare parameter name."""
    if PARAMETER_PATH_SEPARATOR in name:
        try:
            requested = split_parameter_path(name)
        except ValueError:
            return UnknownParameterName(name)
        if any(field.path == requested for field in self.fields):
            return ResolvedParameterName(requested)
        return _resolution_from_candidates(name, self._alias_candidates(name))

    if (top_level := next((field.path for field in self.fields if field.path.parts == (name,)), None)) is not None:
        return ResolvedParameterName(top_level)
    if aliases := self._alias_candidates(name):
        return _resolution_from_candidates(name, aliases)
    if not infer_bare_name:
        return UnknownParameterName(name)
    return _resolution_from_candidates(name, self._fields_ending_with(name))

require(name, *, infer_bare_name=True)

Resolve one name or raise a user-facing configuration error.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def require(self, name: str, *, infer_bare_name: bool = True) -> ParameterPath:
    """Resolve one name or raise a user-facing configuration error."""
    resolution = self.resolve(name, infer_bare_name=infer_bare_name)
    if (
        not infer_bare_name
        and isinstance(resolution, UnknownParameterName)
        and PARAMETER_PATH_SEPARATOR not in name
    ):
        inferred = self._fields_ending_with(name)
        if len(inferred) == 1:
            path = inferred[0]
            parent = path.parts[0]
            raise ParameterError(
                f"Nested parameter name {name!r} is not a direct override; "
                f"use {str(path)!r} or pass the {parent!r} mapping."
            )
        if len(inferred) > 1:
            resolution = AmbiguousParameterName(name, inferred)

    match resolution:
        case ResolvedParameterName() as resolved:
            return resolved.path
        case UnknownParameterName() as unknown:
            kind = "path" if PARAMETER_PATH_SEPARATOR in name else "name"
            raise ParameterError(f"Unknown parameter {kind} {unknown.name!r}.")
        case AmbiguousParameterName() as ambiguous:
            raise _ambiguous_error("name", ambiguous.name, ambiguous.candidates)
    raise ParameterError(f"Unexpected parameter resolution for {name!r}.")

normalize_aliases(source)

Translate declared aliases to canonical paths, with aliases taking precedence.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def normalize_aliases(self, source: Mapping[str, object]) -> dict[str, object]:
    """Translate declared aliases to canonical paths, with aliases taking precedence."""
    values = dict(source)
    for name, field_info in self.model_type.model_fields.items():
        nested_type = _nested_parameters_type(field_info.annotation)
        value = values.get(name)
        if nested_type is not None and isinstance(value, Mapping):
            values[name] = ParameterSchema.from_model(nested_type).normalize_aliases(
                cast(Mapping[str, object], value)
            )

    for name in tuple(values):
        if name in self.model_type.model_fields:
            continue
        candidates = self._alias_candidates(name)
        if not candidates:
            continue
        match _resolution_from_candidates(name, candidates):
            case AmbiguousParameterName() as ambiguous:
                raise _ambiguous_error("alias", name, ambiguous.candidates)
            case ResolvedParameterName() as resolved:
                _set_parameter_value(values, resolved.path, values.pop(name))
            case UnknownParameterName():
                pass
    return values

format_parameter_path(parts)

Join path segments into the canonical dotted string.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def format_parameter_path(parts: Iterable[str]) -> str:
    """Join path segments into the canonical dotted string."""
    return PARAMETER_PATH_SEPARATOR.join(parts)

classify_parameter_annotation(annotation)

Classify a Pydantic field annotation as a branch or leaf.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def classify_parameter_annotation(annotation: object) -> ParameterFieldKind:
    """Classify a Pydantic field annotation as a branch or leaf."""
    if _nested_parameters_type(annotation) is not None:
        return ParameterFieldKind.BRANCH
    return ParameterFieldKind.LEAF

split_parameter_path(name, separator=PARAMETER_PATH_SEPARATOR)

Split a parameter name into a canonical path.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def split_parameter_path(name: str, separator: str = PARAMETER_PATH_SEPARATOR) -> ParameterPath:
    """Split a parameter name into a canonical path."""
    if not separator:
        raise ValueError("A parameter path separator cannot be empty.")
    parts = tuple(name.split(separator))
    if any(not part for part in parts):
        raise ValueError(f"Invalid parameter path {name!r}: empty segment.")
    return ParameterPath(parts)

insert_parameter_value(target, path, value)

Insert a value at an already resolved path.

Source code in src/nemo_safe_synthesizer/configurator/parameter_paths.py
def insert_parameter_value(target: dict[str, object], path: ParameterPath, value: object) -> None:
    """Insert a value at an already resolved path."""
    current = target
    for index, part in enumerate(path.parts[:-1]):
        value_at_part = current.get(part)
        if isinstance(value_at_part, dict):
            current = cast(dict[str, object], value_at_part)
            continue
        if part in current:
            prefix = format_parameter_path(path.parts[: index + 1])
            raise ValueError(f"Conflicting override paths for {str(path)!r}: {prefix!r} already has a parent value.")
        nested: dict[str, object] = {}
        current[part] = nested
        current = nested
    leaf = path.parts[-1]
    if leaf in current:
        raise ValueError(f"Conflicting override paths for {str(path)!r}: nested values already exist below this path.")
    current[leaf] = value