bloc.yaml_utils#

YAML utilities for Bloc: comment-aware parsing and deep merge.

Uses ruamel.yaml to preserve and extract inline comments from YAML files. Comment convention: # [<unit>] <description> [| <remark>]

Example YAML:

initial:
  G_PW_IN: 111  # [kW] Generator power IN
  G_ETA: 0.80   # [-] Generator efficiency

Attributes#

Functions#

load_yaml_raw(path)

Load a YAML file preserving comments (ruamel.yaml round-trip mode).

extract_comment_metadata(data[, section])

Extract inline comment metadata from a YAML section.

extract_header_comments(path)

Extract leading comments from a YAML file (before the first key).

get_bloc_version_info()

Get Bloc version and git commit hash.

deep_merge(base, overlay)

Deep-merge overlay into base. Overlay values win.

load_yaml_with_inheritance(path)

Load YAML config with optional from: inheritance.

load_scenario(base_path[, overlay_path])

Load a scenario by deep-merging an optional overlay onto a base YAML.

expand_scenarios(base_raw)

Expand a STONE YAML's scenarios: / sweeps: blocks.

resolve_dotted(path)

Import module:attr and return attr.

Module Contents#

bloc.yaml_utils.load_yaml_raw(path)#

Load a YAML file preserving comments (ruamel.yaml round-trip mode).

Parameters:

path (str or Path) – Path to the YAML file.

Returns:

The parsed YAML data with comments preserved.

Return type:

CommentedMap

bloc.yaml_utils.extract_comment_metadata(data, section='initial')#

Extract inline comment metadata from a YAML section.

Parses comments following the convention # [unit] description [| remark].

Parameters:
  • data (CommentedMap) – Parsed YAML data (from load_yaml_raw()).

  • section (str) – The top-level section to extract from (default "initial").

Returns:

{key: {"value": ..., "unit": str, "description": str, "remark": str}}

Return type:

dict

bloc.yaml_utils.extract_header_comments(path)#

Extract leading comments from a YAML file (before the first key).

These are typically the file description, update log, etc.

Parameters:

path (str or Path) – Path to the YAML file.

Returns:

Each line of header comments (with # prefix stripped).

Return type:

list of str

bloc.yaml_utils.get_bloc_version_info()#

Get Bloc version and git commit hash.

Returns:

{"version": str, "commit": str}

Return type:

dict

bloc.yaml_utils.deep_merge(base, overlay)#

Deep-merge overlay into base. Overlay values win.

Parameters:
  • base (dict) – The base dictionary.

  • overlay (dict) – The overlay dictionary (overrides take precedence).

Returns:

A new dictionary with the merged result.

Return type:

dict

bloc.yaml_utils.load_yaml_with_inheritance(path)#

Load YAML config with optional from: inheritance.

If a top-level from key is present, that file is loaded first (recursively) and deep-merged with the current file content (excluding from). Relative from paths are resolved against the current file directory.

bloc.yaml_utils.load_scenario(base_path, overlay_path=None)#

Load a scenario by deep-merging an optional overlay onto a base YAML.

If the overlay has a top-level from key, it must match the base filename (e.g. from: SPRING_A3_BG_20260212.yaml when base is that file); otherwise a ValueError is raised. The from key is not merged into the result (metadata only).

Parameters:
  • base_path (str or Path) – Path to the base YAML file.

  • overlay_path (str or Path or None) – Path to the overlay YAML file. If None, only the base is returned.

Returns:

The merged configuration dictionary (plain dict, no comments).

Return type:

dict

bloc.yaml_utils.INPUT_VARIABLE_MAP: dict[str, tuple[str, str, str]]#
bloc.yaml_utils.OUTPUT_VARIABLE_MAP: dict[str, tuple[str, str, str]]#
bloc.yaml_utils.INPUT_CATEGORIES: dict[str, list[str]]#
bloc.yaml_utils.NESTED_INPUT_MAP: dict[str, dict[str, tuple[str, str, str]]]#
bloc.yaml_utils.OUTPUT_CATEGORIES: dict[str, list[str]]#
bloc.yaml_utils.ENERGY_THERMAL_INLET_KEYS: list[str] = ['G_PW_IN (kW)', 'HHV_torch_input (kW)', 'HHV_2nd_inj_input (kW)']#
bloc.yaml_utils.ENERGY_THERMAL_OUTLET_KEYS: list[str] = ['Heat_residual (kW)', 'HHV_pre_quench (kW)', 'Heat_losses_reactor (kW)', 'Torch_generator_losses (kW)']#
bloc.yaml_utils.ELEMENT_BALANCE_DEFAULT_H: float = 0.95#
bloc.yaml_utils.ELEMENT_BALANCE_DEFAULT_C: float = 0.95#
bloc.yaml_utils.TF_INPUT_VARIABLE_MAP: dict[str, tuple[str, str, str]]#
bloc.yaml_utils.TF_OUTPUT_VARIABLE_MAP: dict[str, tuple[str, str, str]]#
bloc.yaml_utils.TF_INPUT_CATEGORIES: dict[str, list[str]]#
bloc.yaml_utils.TF_OUTPUT_CATEGORIES: dict[str, list[str]]#
bloc.yaml_utils.TF_DEFAULT_CONSTRAINTS: list[dict]#
bloc.yaml_utils.SIM_KPI_EXTRACTORS: dict[str, Any]#
bloc.yaml_utils.SIM_FIGURE_GENERATORS: dict[str, Any]#
bloc.yaml_utils.STONE_FIGURE_GENERATORS: dict[str, Any]#
bloc.yaml_utils.expand_scenarios(base_raw)#

Expand a STONE YAML’s scenarios: / sweeps: blocks.

A STONE YAML may declare parameter variations directly inline, avoiding the need for a glob of overlay files. Supported forms:

scenarios:

Explicit list of {id, set?, metadata?} entries. set is a nested dict deep-merged into the base (using deep_merge(), which already supports id-keyed list merging for nodes / connections). metadata is injected into the resulting merged metadata block.

sweeps:

Dict mapping axis name → {path: "<dotted.path>", values: [...]}. All axes are crossed as a Cartesian product; each combination becomes one scenario with id formed from the axis values. path uses dot-notation into the base config (no list indexing).

If both blocks are present, sweeps are expanded first and then each sweep point is multiplied by the explicit scenarios list (if any).

When neither block is present, returns a single (scenario_id, base) tuple using metadata.scenario_id or "BASE".

Parameters:

base_raw (dict) – The raw base YAML (top-level scenarios / sweeps blocks are consumed; they are stripped from every returned merged dict).

Returns:

[(scenario_id, merged_config_dict), ...]. Each merged dict is a deep copy that no longer contains scenarios / sweeps.

Return type:

list of tuple

bloc.yaml_utils.resolve_dotted(path)#

Import module:attr and return attr.

Used by the STONE calculation-note entry point to resolve export.kpi_fn: <dotted> into a callable without requiring a Python caller to import and pass it in.

Parameters:

path (str) – Dotted path of the form "package.module:attribute".

Returns:

The resolved attribute.

Return type:

Any

Raises:
  • ValueError – If path does not contain a : separator.

  • ImportError – If the module cannot be imported.

  • AttributeError – If the module does not define the requested attribute.