diff --git a/xarray/namedarray/utils.py b/xarray/namedarray/utils.py index 3490a76aa8d..e4267637e17 100644 --- a/xarray/namedarray/utils.py +++ b/xarray/namedarray/utils.py @@ -60,6 +60,9 @@ def module_available(module: str, minversion: str | None = None) -> bool: if minversion is not None: version = importlib.metadata.version(module) + if version is None: + return False + return Version(version) >= Version(minversion) return True diff --git a/xarray/tests/test_namedarray.py b/xarray/tests/test_namedarray.py index 09ff1795ef4..93960735e13 100644 --- a/xarray/tests/test_namedarray.py +++ b/xarray/tests/test_namedarray.py @@ -18,7 +18,7 @@ _ShapeType_co, ) from xarray.namedarray.core import NamedArray, from_array -from xarray.namedarray.utils import fake_target_chunksize +from xarray.namedarray.utils import fake_target_chunksize, module_available from xarray.tests import requires_cftime if TYPE_CHECKING: @@ -666,3 +666,26 @@ def test_fake_target_chunksize_cftime() -> None: assert faked_chunksize == 73 assert dtype == np.float64 + + +def test_module_available_version_none() -> None: + """module_available should return False gracefully when metadata.version returns None.""" + import importlib.metadata as _metadata + + original_version = _metadata.version + + def mock_version(name: str) -> str | None: + if name == "packaging": + return None + return original_version(name) + + _metadata.version = mock_version + try: + assert module_available("packaging", minversion="1.0.0") is False + finally: + _metadata.version = original_version + + +def test_module_available_valid() -> None: + """module_available should return True for an installed module with version check.""" + assert module_available("packaging", minversion="0.0.1") is True