Source code for FIREQ_CLIENT.yaml_preprocessor
"""Preprocessing of experiment YAML configuration files."""
from typing import Any, TypeAlias
import yaml
# A value coming from (or resolved in) a YAML file.
YamlValue: TypeAlias = str | int | float | bool | None | list["YamlValue"] | dict[str, "YamlValue"]
[docs]
def resolve_placeholders(data: dict[str, Any]) -> dict[str, Any]:
"""Resolve the placeholders in a YAML config dict.
Given a dict with keys 'preprocess', 'variables', 'sys_config',
replace all "%variable_name" placeholders in sys_config (and anywhere else)
with the actual values from 'preprocess', then return a dict containing
only 'variables' and the resolved 'sys_config'.
:param data: raw YAML configuration.
:type data: dict[str, Any]
:return: dict with the resolved 'sys_config' and the unchanged 'variables'.
:rtype: dict[str, Any]
"""
preprocess = data.get("preprocess", {})
variables = data.get("variables", {})
sys_config = data.get("sys_config", {})
def resolve_value(value: YamlValue) -> YamlValue:
"""Recursively replace strings starting with '%' by preprocess values.
:param value: value to resolve.
:type value: YamlValue
:return: the resolved value.
:rtype: YamlValue
"""
if isinstance(value, str) and value.startswith("%"):
key = value[1:] # strip the leading '%'
if key in preprocess:
return preprocess[key]
# If not found, raise error
else:
raise ValueError(f"Undefined variable: {key}")
elif isinstance(value, dict):
# in case of dict, resolve for all key, value pairs
return {k: resolve_value(v) for k, v in value.items()}
elif isinstance(value, list):
return [resolve_value(item) for item in value]
else:
return value
if preprocess:
resolved_config = resolve_value(sys_config)
else:
resolved_config = sys_config
return {
"variables": variables,
"sys_config": resolved_config,
}
[docs]
def load_and_resolve(yaml_path: str) -> dict[str, Any]:
"""Load a YAML file and resolve all '%...' placeholders.
:param yaml_path: path to the YAML file.
:type yaml_path: str
:return: dict with the resolved configuration.
:rtype: dict[str, Any]
"""
with open(yaml_path, encoding="utf-8") as f:
data = yaml.safe_load(f)
return resolve_placeholders(data)