Source code for hydromodpy.data.managers.plan

"""Immutable runtime objects for resolved data-manager activation.

The planner emits one ``DataLoadPlan`` per launcher run. The plan is consumed
by orchestration code for transparency/debugging.
"""

from __future__ import annotations

from dataclasses import dataclass, field


[docs] @dataclass(frozen=True) class DataLoadPlan: """Resolved data-manager activation plan. ``explicit_types`` come from ``[data].types``. ``inferred_types`` are appended by planner rules. ``reasons_by_type`` records why each inferred family was activated, for example a geology support requested by the domain or an ocean boundary condition requested by flow. """ explicit_types: tuple[str, ...] = field(default_factory=tuple) inferred_types: tuple[str, ...] = field(default_factory=tuple) reasons_by_type: dict[str, tuple[str, ...]] = field(default_factory=dict) @property def types(self) -> tuple[str, ...]: """Return the ordered union of explicit and inferred manager types.""" merged: list[str] = [] seen: set[str] = set() # Keep deterministic order: explicit declarations first, then inferred. for type_name in (*self.explicit_types, *self.inferred_types): if type_name in seen: continue seen.add(type_name) merged.append(type_name) return tuple(merged)
[docs] def has(self, type_name: str) -> bool: """Return ``True`` when *type_name* is active in the resolved plan.""" normalized = str(type_name).strip().lower() return normalized in self.types
[docs] def reasons_for(self, type_name: str) -> tuple[str, ...]: """Return planner reasons recorded for *type_name*.""" normalized = str(type_name).strip().lower() return self.reasons_by_type.get(normalized, ())