Skip to content
Open
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
5 changes: 4 additions & 1 deletion graph_weather/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from .data.nnja_ai import SensorDataset
except ImportError:
SensorDataset = None
from .data.weather_station_reader import WeatherStationReader
try:
from .data.weather_station_reader import WeatherStationReader
except ImportError:
WeatherStationReader = None
from .models.analysis import GraphWeatherAssimilator
from .models.forecast import GraphWeatherForecaster
15 changes: 12 additions & 3 deletions graph_weather/data/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
"""Dataloaders and data processing utilities"""

from .anemoi_dataloader import AnemoiDataset
from .nnja_ai import SensorDataset
from .weather_station_reader import WeatherStationReader
try:
from .anemoi_dataloader import AnemoiDataset
except ImportError:
AnemoiDataset = None
try:
from .nnja_ai import SensorDataset
except ImportError:
SensorDataset = None
try:
from .weather_station_reader import WeatherStationReader
except ImportError:
WeatherStationReader = None
42 changes: 42 additions & 0 deletions tests/test_optional_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Tests that graph_weather.data degrades gracefully without optional heavy deps.

pandas, xarray, anemoi.datasets, and nnja-ai are not declared dependencies of the
graph_weather package, so a plain `pip install graph_weather` may not have them
available. Importing graph_weather.data should not crash in that case - each
optional dataset class should just fall back to None.
"""

import builtins
import importlib
import sys

import pytest

OPTIONAL_MODULES = ("pandas", "xarray", "anemoi.datasets", "nnja_ai")


@pytest.fixture
def hide_optional_deps(monkeypatch):
"""Make imports of the optional heavy deps raise ImportError, like a fresh install."""
real_import = builtins.__import__

def fake_import(name, *args, **kwargs):
if name in OPTIONAL_MODULES or any(name.startswith(mod + ".") for mod in OPTIONAL_MODULES):
raise ImportError(f"No module named '{name}' (blocked for test)")
return real_import(name, *args, **kwargs)

monkeypatch.setattr(builtins, "__import__", fake_import)

# Drop any already-imported copies so the blocked import actually gets exercised.
for name in list(sys.modules):
if name.split(".")[0] in ("graph_weather",) or name in OPTIONAL_MODULES:
monkeypatch.delitem(sys.modules, name, raising=False)


def test_data_package_imports_without_optional_deps(hide_optional_deps):
"""graph_weather.data should import cleanly with pandas/xarray/anemoi/nnja-ai missing."""
data = importlib.import_module("graph_weather.data")

assert data.AnemoiDataset is None
assert data.SensorDataset is None
assert data.WeatherStationReader is None
Loading