From 4ca81ca8a6a951d5a0a782bea71c739aef1bb8ef Mon Sep 17 00:00:00 2001 From: Stephan Finkensieper Date: Thu, 31 Oct 2024 10:39:18 +0000 Subject: [PATCH 1/2] Fix CF writer crashing with netcdf devel --- satpy/tests/writer_tests/test_cf.py | 2 +- satpy/writers/cf_writer.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/satpy/tests/writer_tests/test_cf.py b/satpy/tests/writer_tests/test_cf.py index 1a72894108..eba2cd537f 100644 --- a/satpy/tests/writer_tests/test_cf.py +++ b/satpy/tests/writer_tests/test_cf.py @@ -542,7 +542,7 @@ def test_no_warning_if_backends_match(self, scene, filename, monkeypatch): import netCDF4 with monkeypatch.context() as m: m.setattr(netCDF4, "__version__", "1.6.0") - m.setattr(netCDF4, "__netcdf4libversion__", "4.9.0") + m.setattr(netCDF4, "__netcdf4libversion__", "4.9.0-development") m.setattr(xr, "__version__", "2022.12.0") with warnings.catch_warnings(): scene.save_datasets(filename=filename, writer="cf") diff --git a/satpy/writers/cf_writer.py b/satpy/writers/cf_writer.py index fdcdbd4e8c..25a60ee28f 100644 --- a/satpy/writers/cf_writer.py +++ b/satpy/writers/cf_writer.py @@ -390,8 +390,11 @@ def _backend_versions_match(): def _get_backend_versions(): import netCDF4 + + # Make libnetcdf development version compatible with PEP440 + libnetcdf_version = netCDF4.__netcdf4libversion__.replace("development", "dev") return { "netCDF4": Version(netCDF4.__version__), - "libnetcdf": Version(netCDF4.__netcdf4libversion__), + "libnetcdf": Version(libnetcdf_version), "xarray": Version(xr.__version__) } From 8df630d3ca871afa0687dc3231fd22315d4a555a Mon Sep 17 00:00:00 2001 From: Stephan Finkensieper Date: Fri, 1 Nov 2024 07:54:26 +0000 Subject: [PATCH 2/2] Make libnetcdf version parsing more robust --- satpy/tests/writer_tests/test_cf.py | 15 +++++++++++---- satpy/writers/cf_writer.py | 25 ++++++++++++++++++++----- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/satpy/tests/writer_tests/test_cf.py b/satpy/tests/writer_tests/test_cf.py index eba2cd537f..ba305fbe58 100644 --- a/satpy/tests/writer_tests/test_cf.py +++ b/satpy/tests/writer_tests/test_cf.py @@ -528,12 +528,19 @@ def _assert_encoding_as_expected(self, filename, expected): assert f["test-array"].dtype == expected["dtype"] assert f["test-array"].encoding["complevel"] == expected["complevel"] - def test_warning_if_backends_dont_match(self, scene, filename, monkeypatch): + @pytest.mark.parametrize( + "versions", + [ + {"netCDF4": "1.5.0", "libnetcdf": "4.9.1-development"}, + {"netCDF4": "1.6.0", "libnetcdf": "invalid-version"} + ] + ) + def test_warning_if_backends_dont_match(self, scene, filename, monkeypatch, versions): """Test warning if backends don't match.""" import netCDF4 with monkeypatch.context() as m: - m.setattr(netCDF4, "__version__", "1.5.0") - m.setattr(netCDF4, "__netcdf4libversion__", "4.9.1") + m.setattr(netCDF4, "__version__", versions["netCDF4"]) + m.setattr(netCDF4, "__netcdf4libversion__", versions["libnetcdf"]) with pytest.warns(UserWarning, match=r"Backend version mismatch"): scene.save_datasets(filename=filename, writer="cf") @@ -542,7 +549,7 @@ def test_no_warning_if_backends_match(self, scene, filename, monkeypatch): import netCDF4 with monkeypatch.context() as m: m.setattr(netCDF4, "__version__", "1.6.0") - m.setattr(netCDF4, "__netcdf4libversion__", "4.9.0-development") + m.setattr(netCDF4, "__netcdf4libversion__", "4.9.0") m.setattr(xr, "__version__", "2022.12.0") with warnings.catch_warnings(): scene.save_datasets(filename=filename, writer="cf") diff --git a/satpy/writers/cf_writer.py b/satpy/writers/cf_writer.py index 25a60ee28f..c0b7fd827b 100644 --- a/satpy/writers/cf_writer.py +++ b/satpy/writers/cf_writer.py @@ -158,7 +158,7 @@ import numpy as np import xarray as xr -from packaging.version import Version +from packaging.version import InvalidVersion, Version from satpy.cf.coords import EPOCH # noqa: F401 (for backward compatibility) from satpy.writers import Writer @@ -390,11 +390,26 @@ def _backend_versions_match(): def _get_backend_versions(): import netCDF4 - - # Make libnetcdf development version compatible with PEP440 - libnetcdf_version = netCDF4.__netcdf4libversion__.replace("development", "dev") + libnetcdf_version = _parse_libnetcdf_version( + netCDF4.__netcdf4libversion__ + ) return { "netCDF4": Version(netCDF4.__version__), - "libnetcdf": Version(libnetcdf_version), + "libnetcdf": libnetcdf_version, "xarray": Version(xr.__version__) } + + +def _parse_libnetcdf_version(version_str): + # Make libnetcdf development version compatible with PEP440 + version_str = version_str.replace("development", "dev") + try: + return Version(version_str) + except InvalidVersion: + warnings.warn( + f"Unable to parse netcdf-c version {version_str}, " + f"using 0.0.0 as fallback", + UserWarning, + stacklevel=3 + ) + return Version("0.0.0")