Source code for hydromodpy.project.accessors

"""Helper accessors exposed on :class:`hydromodpy.project.Project`.

Split from :mod:`hydromodpy.project.facade` to keep the facade focused on the
run/lifecycle API.
"""

from __future__ import annotations

import builtins
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    import pandas as pd

    from hydromodpy.project.facade import Project
    from hydromodpy.results.run import Run


[docs] class ProjectDataAccessor: """Helper exposed as ``project.data``. Lists input-data cache entries used by the project, locates a specific :class:`~hydromodpy.data.loading.entry.DataEntry`, and reports missing variables. """ def __init__(self, project: Project) -> None: self._project = project def list(self, variable: str | None = None) -> pd.DataFrame: import pandas as pd loaded = self._project.data_loaded if variable is not None: loaded = {v for v in loaded if v == variable} return pd.DataFrame({"variable": sorted(loaded)}) def missing(self) -> builtins.list[str]: plan_types = getattr(self._project._ctx.data_plan, "types", ()) or () loaded = self._project.data_loaded return [t for t in plan_types if t not in loaded]
[docs] class ProjectRunsAccessor: """Helper exposed as ``project.runs``. Thin wrapper around :class:`~hydromodpy.results.catalog.Catalog` that pre-filters queries by the current project name. """ def __init__(self, project: Project) -> None: self._project = project def list(self) -> pd.DataFrame: store = self._project._store if store is None: import pandas as pd return pd.DataFrame() return store.list_simulations(project=self._project._project_name) def find(self, **filters: Any) -> builtins.list[Run]: store = self._project._store if store is None: return [] return store.find(project=self._project._project_name, **filters) def latest(self) -> Run | None: df = self.list() if df.empty: return None return self._project._store[df.iloc[-1]["sim_id"]] def best(self, metric: str) -> Run | None: store = self._project._store if store is None: return None return store.best(self._project._project_name, metric=metric)
[docs] def delete(self, sim_id: str, *, remove_storage: bool = True) -> None: """Delete a simulation from the catalog (and optionally its artefacts).""" store = self._project._store if store is None: return store.delete(sim_id, remove_storage=remove_storage)