@@ -168,6 +168,64 @@ def skip_if_zarr_format_2(reason: str):
168
168
169
169
ON_WINDOWS = sys .platform == "win32"
170
170
default_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
+
171
229
dask_array_type = array_type ("dask" )
172
230
173
231
if TYPE_CHECKING :
@@ -2263,12 +2321,48 @@ def test_setncattr_string(self) -> None:
2263
2321
None ,
2264
2322
"zlib" ,
2265
2323
"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
+ ),
2272
2366
],
2273
2367
)
2274
2368
@requires_netCDF4_1_6_2_or_above
0 commit comments