@@ -168,6 +168,64 @@ def skip_if_zarr_format_2(reason: str):
168168
169169ON_WINDOWS = sys .platform == "win32"
170170default_value = object ()
171+
172+
173+ def _check_compression_codec_available (codec : str | None ) -> bool :
174+ """Check if a compression codec is available in the netCDF4 library.
175+
176+ Parameters
177+ ----------
178+ codec : str or None
179+ The compression codec name (e.g., 'zstd', 'blosc_lz', etc.)
180+
181+ Returns
182+ -------
183+ bool
184+ True if the codec is available, False otherwise.
185+ """
186+ if codec is None or codec in ("zlib" , "szip" ):
187+ # These are standard and should be available
188+ return True
189+
190+ if not has_netCDF4 :
191+ return False
192+
193+ try :
194+ import os
195+ import tempfile
196+
197+ import netCDF4
198+
199+ # Try to create a file with the compression to test availability
200+ with tempfile .NamedTemporaryFile (suffix = ".nc" , delete = False ) as tmp :
201+ tmp_path = tmp .name
202+
203+ try :
204+ nc = netCDF4 .Dataset (tmp_path , "w" , format = "NETCDF4" )
205+ nc .createDimension ("x" , 10 )
206+
207+ # Attempt to create a variable with the compression
208+ if codec and codec .startswith ("blosc" ):
209+ nc .createVariable (
210+ "test" , "f4" , ("x" ,), compression = codec , blosc_shuffle = 1
211+ )
212+ else :
213+ nc .createVariable ("test" , "f4" , ("x" ,), compression = codec )
214+
215+ nc .close ()
216+ os .unlink (tmp_path )
217+ return True
218+ except (RuntimeError , netCDF4 .NetCDF4MissingFeatureException ):
219+ # Codec not available
220+ if os .path .exists (tmp_path ):
221+ with contextlib .suppress (OSError ):
222+ os .unlink (tmp_path )
223+ return False
224+ except Exception :
225+ # Any other error, assume codec is not available
226+ return False
227+
228+
171229dask_array_type = array_type ("dask" )
172230
173231if TYPE_CHECKING :
@@ -2263,12 +2321,48 @@ def test_setncattr_string(self) -> None:
22632321 None ,
22642322 "zlib" ,
22652323 "szip" ,
2266- "zstd" ,
2267- "blosc_lz" ,
2268- "blosc_lz4" ,
2269- "blosc_lz4hc" ,
2270- "blosc_zlib" ,
2271- "blosc_zstd" ,
2324+ pytest .param (
2325+ "zstd" ,
2326+ marks = pytest .mark .xfail (
2327+ not _check_compression_codec_available ("zstd" ),
2328+ reason = "zstd codec not available in netCDF4 installation" ,
2329+ ),
2330+ ),
2331+ pytest .param (
2332+ "blosc_lz" ,
2333+ marks = pytest .mark .xfail (
2334+ not _check_compression_codec_available ("blosc_lz" ),
2335+ reason = "blosc_lz codec not available in netCDF4 installation" ,
2336+ ),
2337+ ),
2338+ pytest .param (
2339+ "blosc_lz4" ,
2340+ marks = pytest .mark .xfail (
2341+ not _check_compression_codec_available ("blosc_lz4" ),
2342+ reason = "blosc_lz4 codec not available in netCDF4 installation" ,
2343+ ),
2344+ ),
2345+ pytest .param (
2346+ "blosc_lz4hc" ,
2347+ marks = pytest .mark .xfail (
2348+ not _check_compression_codec_available ("blosc_lz4hc" ),
2349+ reason = "blosc_lz4hc codec not available in netCDF4 installation" ,
2350+ ),
2351+ ),
2352+ pytest .param (
2353+ "blosc_zlib" ,
2354+ marks = pytest .mark .xfail (
2355+ not _check_compression_codec_available ("blosc_zlib" ),
2356+ reason = "blosc_zlib codec not available in netCDF4 installation" ,
2357+ ),
2358+ ),
2359+ pytest .param (
2360+ "blosc_zstd" ,
2361+ marks = pytest .mark .xfail (
2362+ not _check_compression_codec_available ("blosc_zstd" ),
2363+ reason = "blosc_zstd codec not available in netCDF4 installation" ,
2364+ ),
2365+ ),
22722366 ],
22732367 )
22742368 @requires_netCDF4_1_6_2_or_above
0 commit comments