Skip to content

Commit c356a40

Browse files
Fix _get_default_engine_netcdf to check for h5netcdf (#10557)
Co-authored-by: Deepak Cherian <[email protected]>
1 parent e71c341 commit c356a40

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

doc/whats-new.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ Bug fixes
3232

3333
- Fix transpose of boolean arrays read from disk. (:issue:`10536`)
3434
By `Deepak Cherian <https://github.com/dcherian>`_.
35-
35+
- Fix detection of the ``h5netcdf`` backend. Xarray now selects ``h5netcdf`` if the default ``netCDF4`` engine is not available (:issue:`10401`, :pull:`10557`).
36+
By `Scott Staniewicz <https://github.com/scottstanie>`_.
3637

3738
Documentation
3839
~~~~~~~~~~~~~

xarray/backends/api.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import importlib.util
34
import os
45
from collections.abc import (
56
Callable,
@@ -122,23 +123,21 @@ def _get_default_engine_gz() -> Literal["scipy"]:
122123
return engine
123124

124125

125-
def _get_default_engine_netcdf() -> Literal["netcdf4", "scipy"]:
126-
engine: Literal["netcdf4", "scipy"]
127-
try:
128-
import netCDF4 # noqa: F401
126+
def _get_default_engine_netcdf() -> Literal["netcdf4", "h5netcdf", "scipy"]:
127+
candidates: list[tuple[str, str]] = [
128+
("netcdf4", "netCDF4"),
129+
("h5netcdf", "h5netcdf"),
130+
("scipy", "scipy.io.netcdf"),
131+
]
129132

130-
engine = "netcdf4"
131-
except ImportError: # pragma: no cover
132-
try:
133-
import scipy.io.netcdf # noqa: F401
133+
for engine, module_name in candidates:
134+
if importlib.util.find_spec(module_name) is not None:
135+
return cast(Literal["netcdf4", "h5netcdf", "scipy"], engine)
134136

135-
engine = "scipy"
136-
except ImportError as err:
137-
raise ValueError(
138-
"cannot read or write netCDF files without "
139-
"netCDF4-python or scipy installed"
140-
) from err
141-
return engine
137+
raise ValueError(
138+
"cannot read or write NetCDF files because none of "
139+
"'netCDF4-python', 'h5netcdf', or 'scipy' are installed"
140+
)
142141

143142

144143
def _get_default_engine(path: str, allow_remote: bool = False) -> T_NetcdfEngine:

xarray/tests/test_backends_api.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
from __future__ import annotations
22

3+
import sys
34
from numbers import Number
45

56
import numpy as np
67
import pytest
78

89
import xarray as xr
9-
from xarray.backends.api import _get_default_engine
10+
from xarray.backends.api import _get_default_engine, _get_default_engine_netcdf
1011
from xarray.tests import (
1112
assert_identical,
1213
assert_no_warnings,
1314
requires_dask,
15+
requires_h5netcdf,
1416
requires_netCDF4,
1517
requires_scipy,
1618
)
@@ -29,6 +31,17 @@ def test__get_default_engine() -> None:
2931
assert engine_default == "netcdf4"
3032

3133

34+
@requires_h5netcdf
35+
def test_default_engine_h5netcdf(monkeypatch):
36+
"""Test the default netcdf engine when h5netcdf is the only importable module."""
37+
38+
monkeypatch.delitem(sys.modules, "netCDF4", raising=False)
39+
monkeypatch.delitem(sys.modules, "scipy", raising=False)
40+
monkeypatch.setattr(sys, "meta_path", [])
41+
42+
assert _get_default_engine_netcdf() == "h5netcdf"
43+
44+
3245
def test_custom_engine() -> None:
3346
expected = xr.Dataset(
3447
dict(a=2 * np.arange(5)), coords=dict(x=("x", np.arange(5), dict(units="s")))

0 commit comments

Comments
 (0)