Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,476 changes: 740 additions & 736 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies = [
"xarray (>=2025.2.0,<2027.0.0)",
"pydantic-settings (>=2.8.1,<3.0.0)",
"httpx (>=0.27.0,<0.29.0)",
"aiofiles (>=24.1.0,<25.0.0)",
"aiofiles (>=24.1.0,<26.0.0)",
"cfgrib (>=0.9.15.0,<0.10.0.0)",
"netcdf4 (>=1.7.2,<2.0.0)",
"dask (>=2025.4.1,<2027.0.0)",
Expand All @@ -35,9 +35,9 @@ DEP002 = ["cfgrib", "dask", "netcdf4"]
[tool.poetry.group.dev.dependencies]
coverage = "^7.8.0"
pre-commit = "^4.2.0"
deptry = "^0.23.0"
deptry = ">0.23.0"
Comment thread
spiani marked this conversation as resolved.
pytest = "^8.3.5"
pytest-asyncio = "^0.26.0"
pytest-asyncio = "^1.4.0"


[tool.pytest.ini_options]
Expand Down
25 changes: 15 additions & 10 deletions src/ogs_riverger/efas/efas_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
from tempfile import TemporaryDirectory
from typing import Any
from typing import Literal
from typing import TYPE_CHECKING
from uuid import uuid1
from zipfile import ZipFile

import dask
import numpy as np
import xarray as xr

if TYPE_CHECKING:
import xarray as xr
else:
import ogs_riverger.utils.lazy_xarray as xr

import ogs_riverger.efas.download_tools as efas_download
from ogs_riverger.efas.download_tools import EfasDataSource
Expand Down Expand Up @@ -81,7 +86,7 @@ def read_efas_data_files(
config_content: Iterable[RiverConfigElement],
efas_domain_file: PathLike,
pool: None | Pool = None,
) -> xr.Dataset:
) -> "xr.Dataset":
"""Reads and merges the content of multiple downloaded EFAS data files.

EFAS data files are distributed as GRIB or NetCDF files, optionally
Expand Down Expand Up @@ -149,9 +154,9 @@ def read_efas_data_files(
def _read_raw_content_of_efas_file(
file_path: Path,
config_content: Iterable[RiverConfigElement],
efas_domain: xr.Dataset,
efas_domain: "xr.Dataset",
temp_dir: Path,
) -> xr.Dataset:
) -> "xr.Dataset":
"""
Reads the raw content of an EFAS file.

Expand Down Expand Up @@ -224,8 +229,8 @@ def _read_raw_content_of_efas_file(
def _read_raw_content_of_unzipped_efas_file(
file_path: Path,
config_content: Iterable[RiverConfigElement],
efas_domain: xr.Dataset,
) -> xr.Dataset:
efas_domain: "xr.Dataset",
) -> "xr.Dataset":
"""
Reads and processes the raw content of an unzipped EFAS file to extract
specific river data based on given configurations and EFAS domain.
Expand Down Expand Up @@ -409,9 +414,9 @@ def _read_raw_content_of_unzipped_efas_file(
def _read_single_efas_file(
file_path: Path,
config_content: Iterable[RiverConfigElement],
efas_domain: xr.Dataset,
efas_domain: "xr.Dataset",
temp_dir: Path,
) -> xr.Dataset:
) -> "xr.Dataset":
"""Determines the type of EFAS file and processes it accordingly.

This function reads the EFAS file content and examines its structure to
Expand Down Expand Up @@ -497,7 +502,7 @@ def _read_single_efas_file(
)


def _read_efas_forecast_file(dataset: xr.Dataset):
def _read_efas_forecast_file(dataset: "xr.Dataset"):
"""Read the content of a forecast EFAS file.

This function is called by `_read_single_efas_file` when the file has
Expand Down Expand Up @@ -550,7 +555,7 @@ def _read_efas_forecast_file(dataset: xr.Dataset):
return dataset_sliced


def _read_efas_operative_grib_file(dataset: xr.Dataset):
def _read_efas_operative_grib_file(dataset: "xr.Dataset"):
"""Read the content of an operative EFAS file.

This function is called by `_read_single_efas_file` when the file has
Expand Down
11 changes: 8 additions & 3 deletions src/ogs_riverger/read_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,14 @@ def _apply_biogeochemical_profile(
):
biogeochemical = {}
if "biogeochemical_profile" in raw_river:
biogeochemical = profiles[
raw_river["biogeochemical_profile"]
].copy()
profile_name = raw_river["biogeochemical_profile"]
if profile_name not in profiles:
raise ValueError(
f'River "{raw_river["name"]}" references a '
f'biogeochemical profile "{profile_name}" that is not '
f"defined in the configuration file."
Comment thread
spiani marked this conversation as resolved.
)
biogeochemical = profiles[profile_name].copy()

if "biogeochemical" in raw_river:
biogeochemical.update(raw_river["biogeochemical"])
Expand Down
24 changes: 24 additions & 0 deletions src/ogs_riverger/utils/lazy_xarray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Lazy proxy for xarray.

Importing this module does *not* import xarray. The real import happens only
when an attribute (e.g. ``xr.Dataset``, ``xr.open_dataset``) is first
accessed, via the module-level ``__getattr__`` hook defined in PEP 562.

Usage::

import ogs_riverger.utils.lazy_xarray as xr

ds = xr.open_dataset(...) # xarray is imported here, on first access
"""

_XARRAY = None


def __getattr__(name: str):
global _XARRAY
if _XARRAY is None:
import xarray

_XARRAY = xarray

return getattr(_XARRAY, name)
7 changes: 7 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ def config_file_example(tmp_path):
"temperature_variation": 5,
"average_salinity": 5
},
"bgc_profiles": {
"tyr": {
"B1c": 100,
"B1n": 10,
"B1p": 1
}
},
"default_model": "stem_flux",
"rivers": [
{
Expand Down
Loading