#
# SPDX-FileCopyrightText: <text>Copyright 2025 Arm Limited and/or its
# affiliates <open-source-office@arm.com></text>
#
# SPDX-License-Identifier: MIT
"""
Central loader for config, with optional BUILD_IMAGE_DIR and FVP_BINARY
substitution. Supports both list- and mapping-style 'platforms' sections
in YAML.
"""
import os
import yaml
from typing import Any, Dict, Optional
[docs]
def _expand(obj: Any) -> Any:
"""
Expand ${ENV} in all strings.
:param obj: Python objects like strings, lists, and dictionaries are
transformed.
:returns: The environment variables and user-home markers expanded
wherever applicable.
"""
if isinstance(obj, str):
return os.path.expanduser(os.path.expandvars(obj))
if isinstance(obj, list):
return [_expand(x) for x in obj]
if isinstance(obj, dict):
return {k: _expand(v) for k, v in obj.items()}
return obj
[docs]
def _set_env_vars(build_dir: Optional[str], fvp_binary: Optional[str]) -> None:
"""
Set process environment variables for FVP configuration.
:param build_dir: Path to set as ``BUILD_DIR``. If ``None``,
the variable is not set.
:param fvp_binary: Path to set as ``FVP_BINARY``. If ``None``,
the variable is not set.
:returns: None
"""
if build_dir:
os.environ["BUILD_DIR"] = build_dir.rstrip(os.sep)
if fvp_binary:
os.environ["FVP_BINARY"] = fvp_binary.rstrip(os.sep)
[docs]
def _load_yaml_expanded(path: str) -> Dict[str, Any]:
"""
Load YAML configuration from a file and expand environment variables.
:param path: Path to a YAML configuration file.
:returns: Parsed and expanded YAML content as a dictionary.
:raises FileNotFoundError: If the YAML file cannot be found.
:raises yaml.YAMLError: If the YAML content cannot be parsed.
"""
with open(path, "r", encoding="utf-8") as f:
data = yaml.safe_load(f) or {}
return _expand(data)
[docs]
class Config:
"""
Central config loader to load YAML, set environment variable and expose
platforms as a dict keyed by name.
"""
def __init__(
self,
path: str,
build_dir: Optional[str] = None,
fvp_binary: Optional[str] = None,
) -> None:
"""Create a configuration loader and normalize the YAML structure.
:param path: Path to a YAML file containing framework configuration.
:param build_dir: Sets ``BUILD_DIR`` in the process environment.
:param fvp_binary: Sets ``FVP_BINARY`` in the process environment.
:returns: ``None``
:raises FileNotFoundError: If the provided ``path`` does not exist.
:raises yaml.YAMLError: If the YAML content cannot be parsed.
"""
_set_env_vars(build_dir, fvp_binary)
data = _load_yaml_expanded(path)
[docs]
self.build_dir = build_dir
[docs]
self.fvp_binary = fvp_binary
[docs]
def to_dict(self) -> Dict[str, Any]:
"""
Return the full expanded YAML content as a dictionary.
:returns: A shallow copy of the expanded YAML content.
"""
return dict(self._raw)