h5netcdf 1.3.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of h5netcdf might be problematic. Click here for more details.
- h5netcdf/__init__.py +1 -0
- h5netcdf/_version.py +2 -2
- h5netcdf/attrs.py +2 -2
- h5netcdf/core.py +554 -87
- h5netcdf/dimensions.py +6 -9
- h5netcdf/legacyapi.py +26 -5
- h5netcdf/tests/test_h5netcdf.py +607 -63
- {h5netcdf-1.3.0.dist-info → h5netcdf-1.4.0.dist-info}/METADATA +26 -27
- h5netcdf-1.4.0.dist-info/RECORD +16 -0
- {h5netcdf-1.3.0.dist-info → h5netcdf-1.4.0.dist-info}/WHEEL +1 -1
- h5netcdf-1.3.0.dist-info/RECORD +0 -16
- {h5netcdf-1.3.0.dist-info → h5netcdf-1.4.0.dist-info}/AUTHORS.txt +0 -0
- {h5netcdf-1.3.0.dist-info → h5netcdf-1.4.0.dist-info}/LICENSE +0 -0
- {h5netcdf-1.3.0.dist-info → h5netcdf-1.4.0.dist-info}/top_level.txt +0 -0
h5netcdf/tests/test_h5netcdf.py
CHANGED
|
@@ -15,7 +15,11 @@ from pytest import raises
|
|
|
15
15
|
|
|
16
16
|
import h5netcdf
|
|
17
17
|
from h5netcdf import legacyapi
|
|
18
|
-
from h5netcdf.core import
|
|
18
|
+
from h5netcdf.core import (
|
|
19
|
+
NOT_A_VARIABLE,
|
|
20
|
+
CompatibilityError,
|
|
21
|
+
VLType,
|
|
22
|
+
)
|
|
19
23
|
|
|
20
24
|
try:
|
|
21
25
|
import h5pyd
|
|
@@ -103,18 +107,21 @@ _vlen_string = "foo"
|
|
|
103
107
|
|
|
104
108
|
|
|
105
109
|
def is_h5py_char_working(tmp_netcdf, name):
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
if not isinstance(tmp_netcdf, h5py.File):
|
|
111
|
+
h5 = get_hdf5_module(tmp_netcdf)
|
|
112
|
+
# https://github.com/Unidata/netcdf-c/issues/298
|
|
113
|
+
with h5.File(tmp_netcdf, "r") as ds:
|
|
114
|
+
return is_h5py_char_working(ds, name)
|
|
115
|
+
|
|
116
|
+
v = tmp_netcdf[name]
|
|
117
|
+
try:
|
|
118
|
+
assert array_equal(v, _char_array)
|
|
119
|
+
return True
|
|
120
|
+
except Exception as e:
|
|
121
|
+
if re.match("^Can't read data", e.args[0]):
|
|
122
|
+
return False
|
|
123
|
+
else:
|
|
124
|
+
raise
|
|
118
125
|
|
|
119
126
|
|
|
120
127
|
def write_legacy_netcdf(tmp_netcdf, write_module):
|
|
@@ -164,6 +171,16 @@ def write_legacy_netcdf(tmp_netcdf, write_module):
|
|
|
164
171
|
v = ds.createVariable("var_len_str", str, ("x"))
|
|
165
172
|
v[0] = "foo"
|
|
166
173
|
|
|
174
|
+
enum_dict = dict(one=1, two=2, three=3, missing=255)
|
|
175
|
+
enum_type = ds.createEnumType(np.uint8, "enum_t", enum_dict)
|
|
176
|
+
v = ds.createVariable(
|
|
177
|
+
"enum_var",
|
|
178
|
+
enum_type,
|
|
179
|
+
("x",),
|
|
180
|
+
fill_value=enum_dict["missing"],
|
|
181
|
+
)
|
|
182
|
+
v[0:3] = [1, 2, 3]
|
|
183
|
+
|
|
167
184
|
ds.close()
|
|
168
185
|
|
|
169
186
|
|
|
@@ -214,6 +231,13 @@ def write_h5netcdf(tmp_netcdf):
|
|
|
214
231
|
v = ds.create_variable("var_len_str", ("x",), dtype=dt)
|
|
215
232
|
v[0] = _vlen_string
|
|
216
233
|
|
|
234
|
+
enum_dict = dict(one=1, two=2, three=3, missing=255)
|
|
235
|
+
enum_type = ds.create_enumtype(np.uint8, "enum_t", enum_dict)
|
|
236
|
+
v = ds.create_variable(
|
|
237
|
+
"enum_var", ("x",), dtype=enum_type, fillvalue=enum_dict["missing"]
|
|
238
|
+
)
|
|
239
|
+
v[0:3] = [1, 2, 3]
|
|
240
|
+
|
|
217
241
|
ds.close()
|
|
218
242
|
|
|
219
243
|
|
|
@@ -231,6 +255,7 @@ def read_legacy_netcdf(tmp_netcdf, read_module, write_module):
|
|
|
231
255
|
)
|
|
232
256
|
assert set(ds.variables) == set(
|
|
233
257
|
[
|
|
258
|
+
"enum_var",
|
|
234
259
|
"foo",
|
|
235
260
|
"y",
|
|
236
261
|
"z",
|
|
@@ -242,6 +267,8 @@ def read_legacy_netcdf(tmp_netcdf, read_module, write_module):
|
|
|
242
267
|
]
|
|
243
268
|
)
|
|
244
269
|
|
|
270
|
+
assert set(ds.enumtypes) == set(["enum_t"])
|
|
271
|
+
|
|
245
272
|
assert set(ds.groups) == set(["subgroup"])
|
|
246
273
|
assert ds.parent is None
|
|
247
274
|
v = ds.variables["foo"]
|
|
@@ -325,6 +352,12 @@ def read_legacy_netcdf(tmp_netcdf, read_module, write_module):
|
|
|
325
352
|
assert v.shape == (10,)
|
|
326
353
|
assert "y" in ds.groups["subgroup"].dimensions
|
|
327
354
|
|
|
355
|
+
enum_dict = dict(one=1, two=2, three=3, missing=255)
|
|
356
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
357
|
+
assert enum_type.enum_dict == enum_dict
|
|
358
|
+
v = ds.variables["enum_var"]
|
|
359
|
+
assert array_equal(v, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
360
|
+
|
|
328
361
|
ds.close()
|
|
329
362
|
|
|
330
363
|
|
|
@@ -342,6 +375,7 @@ def read_h5netcdf(tmp_netcdf, write_module, decode_vlen_strings):
|
|
|
342
375
|
)
|
|
343
376
|
variables = set(
|
|
344
377
|
[
|
|
378
|
+
"enum_var",
|
|
345
379
|
"foo",
|
|
346
380
|
"z",
|
|
347
381
|
"intscalar",
|
|
@@ -418,7 +452,7 @@ def read_h5netcdf(tmp_netcdf, write_module, decode_vlen_strings):
|
|
|
418
452
|
assert list(v.attrs) == []
|
|
419
453
|
|
|
420
454
|
v = ds["var_len_str"]
|
|
421
|
-
assert h5py.check_dtype(vlen=v.dtype)
|
|
455
|
+
assert h5py.check_dtype(vlen=v.dtype) is str
|
|
422
456
|
if getattr(ds, "decode_vlen_strings", True):
|
|
423
457
|
assert v[0] == _vlen_string
|
|
424
458
|
else:
|
|
@@ -440,6 +474,12 @@ def read_h5netcdf(tmp_netcdf, write_module, decode_vlen_strings):
|
|
|
440
474
|
assert ds["/subgroup/y_var"].shape == (10,)
|
|
441
475
|
assert ds["/subgroup"].dimensions["y"].size == 10
|
|
442
476
|
|
|
477
|
+
enum_dict = dict(one=1, two=2, three=3, missing=255)
|
|
478
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
479
|
+
assert enum_type.enum_dict == enum_dict
|
|
480
|
+
v = ds.variables["enum_var"]
|
|
481
|
+
assert array_equal(v, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
482
|
+
|
|
443
483
|
ds.close()
|
|
444
484
|
|
|
445
485
|
|
|
@@ -494,6 +534,16 @@ def test_fileobj(decode_vlen_strings):
|
|
|
494
534
|
read_h5netcdf(fileobj, h5netcdf, decode_vlen_strings)
|
|
495
535
|
|
|
496
536
|
|
|
537
|
+
def test_h5py_file_obj(tmp_local_netcdf, decode_vlen_strings):
|
|
538
|
+
with h5py.File(tmp_local_netcdf, "w") as h5py_f:
|
|
539
|
+
write_h5netcdf(h5py_f)
|
|
540
|
+
read_h5netcdf(h5py_f, h5netcdf, decode_vlen_strings)
|
|
541
|
+
|
|
542
|
+
# The h5py File object should still be open & usable, although the
|
|
543
|
+
# h5netcdf file object has been closed.
|
|
544
|
+
assert isinstance(h5py_f["foo"], h5py.Dataset)
|
|
545
|
+
|
|
546
|
+
|
|
497
547
|
def test_repr(tmp_local_or_remote_netcdf):
|
|
498
548
|
write_h5netcdf(tmp_local_or_remote_netcdf)
|
|
499
549
|
f = h5netcdf.File(tmp_local_or_remote_netcdf, "a")
|
|
@@ -645,8 +695,6 @@ def check_invalid_netcdf4(var, i):
|
|
|
645
695
|
|
|
646
696
|
|
|
647
697
|
def test_invalid_netcdf4(tmp_local_or_remote_netcdf):
|
|
648
|
-
if tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
649
|
-
pytest.skip("netCDF4 package does not work with remote HDF5 files")
|
|
650
698
|
h5 = get_hdf5_module(tmp_local_or_remote_netcdf)
|
|
651
699
|
with h5.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
652
700
|
var, var2 = create_invalid_netcdf_data()
|
|
@@ -714,8 +762,6 @@ def check_invalid_netcdf4_mixed(var, i):
|
|
|
714
762
|
|
|
715
763
|
|
|
716
764
|
def test_invalid_netcdf4_mixed(tmp_local_or_remote_netcdf):
|
|
717
|
-
if tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
718
|
-
pytest.skip("netCDF4 package does not work with remote HDF5 files")
|
|
719
765
|
h5 = get_hdf5_module(tmp_local_or_remote_netcdf)
|
|
720
766
|
with h5.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
721
767
|
var, var2 = create_invalid_netcdf_data()
|
|
@@ -790,15 +836,16 @@ def test_hierarchical_access_auto_create(tmp_local_or_remote_netcdf):
|
|
|
790
836
|
ds.close()
|
|
791
837
|
|
|
792
838
|
|
|
793
|
-
def test_Netcdf4Dimid(
|
|
839
|
+
def test_Netcdf4Dimid(tmp_local_or_remote_netcdf):
|
|
794
840
|
# regression test for https://github.com/h5netcdf/h5netcdf/issues/53
|
|
795
|
-
with h5netcdf.File(
|
|
841
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
796
842
|
f.dimensions["x"] = 1
|
|
797
843
|
g = f.create_group("foo")
|
|
798
844
|
g.dimensions["x"] = 2
|
|
799
845
|
g.dimensions["y"] = 3
|
|
800
846
|
|
|
801
|
-
|
|
847
|
+
h5 = get_hdf5_module(tmp_local_or_remote_netcdf)
|
|
848
|
+
with h5.File(tmp_local_or_remote_netcdf, "r") as f:
|
|
802
849
|
# all dimension IDs should be present exactly once
|
|
803
850
|
dim_ids = {f[name].attrs["_Netcdf4Dimid"] for name in ["x", "foo/x", "foo/y"]}
|
|
804
851
|
assert dim_ids == {0, 1, 2}
|
|
@@ -859,9 +906,6 @@ def test_failed_read_open_and_clean_delete(tmpdir):
|
|
|
859
906
|
def test_create_variable_matching_saved_dimension(tmp_local_or_remote_netcdf):
|
|
860
907
|
h5 = get_hdf5_module(tmp_local_or_remote_netcdf)
|
|
861
908
|
|
|
862
|
-
# if h5 is not h5py:
|
|
863
|
-
# pytest.xfail("https://github.com/h5netcdf/h5netcdf/issues/48")
|
|
864
|
-
|
|
865
909
|
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
866
910
|
f.dimensions["x"] = 2
|
|
867
911
|
f.create_variable("y", data=[1, 2], dimensions=("x",))
|
|
@@ -885,11 +929,6 @@ def test_invalid_netcdf_error(tmp_local_or_remote_netcdf):
|
|
|
885
929
|
f.create_variable(
|
|
886
930
|
"lzf_compressed", data=[1], dimensions=("x"), compression="lzf"
|
|
887
931
|
)
|
|
888
|
-
# invalid
|
|
889
|
-
with pytest.raises(h5netcdf.CompatibilityError):
|
|
890
|
-
f.create_variable("complex", data=1j)
|
|
891
|
-
with pytest.raises(h5netcdf.CompatibilityError):
|
|
892
|
-
f.attrs["complex_attr"] = 1j
|
|
893
932
|
with pytest.raises(h5netcdf.CompatibilityError):
|
|
894
933
|
f.create_variable("scaleoffset", data=[1], dimensions=("x",), scaleoffset=0)
|
|
895
934
|
|
|
@@ -1192,19 +1231,19 @@ def test_reading_special_datatype_created_with_c_api(tmp_local_netcdf):
|
|
|
1192
1231
|
pass
|
|
1193
1232
|
|
|
1194
1233
|
|
|
1195
|
-
def test_nc4_non_coord(
|
|
1234
|
+
def test_nc4_non_coord(tmp_local_or_remote_netcdf):
|
|
1196
1235
|
# Here we generate a few variables and coordinates
|
|
1197
1236
|
# The default should be to track the order of creation
|
|
1198
1237
|
# Thus, on reopening the file, the order in which
|
|
1199
1238
|
# the variables are listed should be maintained
|
|
1200
1239
|
# y -- refers to the coordinate y
|
|
1201
1240
|
# _nc4_non_coord_y -- refers to the data y
|
|
1202
|
-
with h5netcdf.File(
|
|
1241
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
1203
1242
|
f.dimensions = {"x": None, "y": 2}
|
|
1204
1243
|
f.create_variable("test", dimensions=("x",), dtype=np.int64)
|
|
1205
1244
|
f.create_variable("y", dimensions=("x",), dtype=np.int64)
|
|
1206
1245
|
|
|
1207
|
-
with h5netcdf.File(
|
|
1246
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as f:
|
|
1208
1247
|
assert list(f.dimensions) == ["x", "y"]
|
|
1209
1248
|
assert f.dimensions["x"].size == 0
|
|
1210
1249
|
assert f.dimensions["x"].isunlimited()
|
|
@@ -1213,12 +1252,12 @@ def test_nc4_non_coord(tmp_local_netcdf):
|
|
|
1213
1252
|
assert list(f.variables) == ["test", "y"]
|
|
1214
1253
|
assert list(f._h5group.keys()) == ["x", "y", "test", "_nc4_non_coord_y"]
|
|
1215
1254
|
|
|
1216
|
-
with h5netcdf.File(
|
|
1255
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
1217
1256
|
f.dimensions = {"x": None, "y": 2}
|
|
1218
1257
|
f.create_variable("y", dimensions=("x",), dtype=np.int64)
|
|
1219
1258
|
f.create_variable("test", dimensions=("x",), dtype=np.int64)
|
|
1220
1259
|
|
|
1221
|
-
with h5netcdf.File(
|
|
1260
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as f:
|
|
1222
1261
|
assert list(f.dimensions) == ["x", "y"]
|
|
1223
1262
|
assert f.dimensions["x"].size == 0
|
|
1224
1263
|
assert f.dimensions["x"].isunlimited()
|
|
@@ -1306,42 +1345,42 @@ def test_create_attach_scales_legacyapi(tmp_local_netcdf):
|
|
|
1306
1345
|
create_attach_scales(tmp_local_netcdf, legacyapi)
|
|
1307
1346
|
|
|
1308
1347
|
|
|
1309
|
-
def test_detach_scale(
|
|
1310
|
-
with h5netcdf.File(
|
|
1348
|
+
def test_detach_scale(tmp_local_or_remote_netcdf):
|
|
1349
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1311
1350
|
ds.dimensions["x"] = 2
|
|
1312
1351
|
ds.dimensions["y"] = 2
|
|
1313
1352
|
|
|
1314
|
-
with h5netcdf.File(
|
|
1353
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "a") as ds:
|
|
1315
1354
|
ds.create_variable("test", dimensions=("x",), dtype=np.int64)
|
|
1316
1355
|
|
|
1317
|
-
with h5netcdf.File(
|
|
1356
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1318
1357
|
refs = ds._h5group["x"].attrs.get("REFERENCE_LIST", False)
|
|
1319
1358
|
assert len(refs) == 1
|
|
1320
1359
|
for (ref, dim), name in zip(refs, ["/test"]):
|
|
1321
1360
|
assert dim == 0
|
|
1322
1361
|
assert ds._root._h5file[ref].name == name
|
|
1323
1362
|
|
|
1324
|
-
with h5netcdf.File(
|
|
1363
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "a") as ds:
|
|
1325
1364
|
ds.dimensions["x"]._detach_scale()
|
|
1326
1365
|
|
|
1327
|
-
with h5netcdf.File(
|
|
1366
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1328
1367
|
refs = ds._h5group["x"].attrs.get("REFERENCE_LIST", False)
|
|
1329
1368
|
assert not refs
|
|
1330
1369
|
|
|
1331
1370
|
|
|
1332
|
-
def test_is_scale(
|
|
1333
|
-
with legacyapi.Dataset(
|
|
1371
|
+
def test_is_scale(tmp_local_or_remote_netcdf):
|
|
1372
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1334
1373
|
ds.createDimension("x", 10)
|
|
1335
|
-
with legacyapi.Dataset(
|
|
1374
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1336
1375
|
assert ds.dimensions["x"]._isscale
|
|
1337
1376
|
|
|
1338
1377
|
|
|
1339
|
-
def test_get_dim_scale_refs(
|
|
1340
|
-
with legacyapi.Dataset(
|
|
1378
|
+
def test_get_dim_scale_refs(tmp_local_or_remote_netcdf):
|
|
1379
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1341
1380
|
ds.createDimension("x", 10)
|
|
1342
1381
|
ds.createVariable("test0", "i8", ("x",))
|
|
1343
1382
|
ds.createVariable("test1", "i8", ("x",))
|
|
1344
|
-
with legacyapi.Dataset(
|
|
1383
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1345
1384
|
refs = ds.dimensions["x"]._scale_refs
|
|
1346
1385
|
assert ds._h5file[refs[0][0]] == ds["test0"]._h5ds
|
|
1347
1386
|
assert ds._h5file[refs[1][0]] == ds["test1"]._h5ds
|
|
@@ -1498,14 +1537,14 @@ def test_dimensions(tmp_local_netcdf, read_write_matrix):
|
|
|
1498
1537
|
)
|
|
1499
1538
|
|
|
1500
1539
|
|
|
1501
|
-
def test_no_circular_references(
|
|
1540
|
+
def test_no_circular_references(tmp_local_or_remote_netcdf):
|
|
1502
1541
|
# https://github.com/h5py/h5py/issues/2019
|
|
1503
|
-
with h5netcdf.File(
|
|
1542
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1504
1543
|
ds.dimensions["x"] = 2
|
|
1505
1544
|
ds.dimensions["y"] = 2
|
|
1506
1545
|
|
|
1507
1546
|
gc.collect()
|
|
1508
|
-
with h5netcdf.File(
|
|
1547
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1509
1548
|
refs = gc.get_referrers(ds)
|
|
1510
1549
|
for ref in refs:
|
|
1511
1550
|
print(ref)
|
|
@@ -1713,13 +1752,13 @@ def test_group_names(tmp_local_netcdf):
|
|
|
1713
1752
|
assert ds[name].name == name
|
|
1714
1753
|
|
|
1715
1754
|
|
|
1716
|
-
def test_legacyapi_endianess(
|
|
1755
|
+
def test_legacyapi_endianess(tmp_local_or_remote_netcdf):
|
|
1717
1756
|
# https://github.com/h5netcdf/h5netcdf/issues/15
|
|
1718
1757
|
big = legacyapi._check_return_dtype_endianess("big")
|
|
1719
1758
|
little = legacyapi._check_return_dtype_endianess("little")
|
|
1720
1759
|
native = legacyapi._check_return_dtype_endianess("native")
|
|
1721
1760
|
|
|
1722
|
-
with legacyapi.Dataset(
|
|
1761
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1723
1762
|
ds.createDimension("x", 4)
|
|
1724
1763
|
# test creating variable using endian keyword argument
|
|
1725
1764
|
v = ds.createVariable("big", int, ("x"), endian="big")
|
|
@@ -1729,25 +1768,27 @@ def test_legacyapi_endianess(tmp_local_netcdf):
|
|
|
1729
1768
|
v = ds.createVariable("native", int, ("x"), endian="native")
|
|
1730
1769
|
v[...] = 65535
|
|
1731
1770
|
|
|
1732
|
-
|
|
1771
|
+
h5 = get_hdf5_module(tmp_local_or_remote_netcdf)
|
|
1772
|
+
with h5.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1733
1773
|
assert ds["big"].dtype.byteorder == big
|
|
1734
1774
|
assert ds["little"].dtype.byteorder == little
|
|
1735
1775
|
assert ds["native"].dtype.byteorder == native
|
|
1736
1776
|
|
|
1737
|
-
with h5netcdf.File(
|
|
1777
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1738
1778
|
assert ds["big"].dtype.byteorder == big
|
|
1739
1779
|
assert ds["little"].dtype.byteorder == little
|
|
1740
1780
|
assert ds["native"].dtype.byteorder == native
|
|
1741
1781
|
|
|
1742
|
-
with legacyapi.Dataset(
|
|
1782
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1743
1783
|
assert ds["big"].dtype.byteorder == big
|
|
1744
1784
|
assert ds["little"].dtype.byteorder == little
|
|
1745
1785
|
assert ds["native"].dtype.byteorder == native
|
|
1746
1786
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1787
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
1788
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1789
|
+
assert ds["big"].dtype.byteorder == big
|
|
1790
|
+
assert ds["little"].dtype.byteorder == little
|
|
1791
|
+
assert ds["native"].dtype.byteorder == native
|
|
1751
1792
|
|
|
1752
1793
|
|
|
1753
1794
|
def test_bool_slicing_length_one_dim(tmp_local_netcdf):
|
|
@@ -1781,9 +1822,9 @@ def test_bool_slicing_length_one_dim(tmp_local_netcdf):
|
|
|
1781
1822
|
ds["hello"][bool_slice, :]
|
|
1782
1823
|
|
|
1783
1824
|
|
|
1784
|
-
def test_fancy_indexing(
|
|
1825
|
+
def test_fancy_indexing(tmp_local_or_remote_netcdf):
|
|
1785
1826
|
# regression test for https://github.com/pydata/xarray/issues/7154
|
|
1786
|
-
with h5netcdf.legacyapi.Dataset(
|
|
1827
|
+
with h5netcdf.legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1787
1828
|
ds.createDimension("x", None)
|
|
1788
1829
|
ds.createDimension("y", None)
|
|
1789
1830
|
ds.createVariable("hello", int, ("x", "y"), fill_value=0)
|
|
@@ -1791,7 +1832,7 @@ def test_fancy_indexing(tmp_local_netcdf):
|
|
|
1791
1832
|
ds.createVariable("hello2", int, ("x", "y"))
|
|
1792
1833
|
ds["hello2"][:10, :20] = np.arange(10 * 20, dtype="int").reshape((10, 20))
|
|
1793
1834
|
|
|
1794
|
-
with legacyapi.Dataset(
|
|
1835
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "a") as ds:
|
|
1795
1836
|
np.testing.assert_array_equal(ds["hello"][1, [7, 8, 9]], [17, 18, 19])
|
|
1796
1837
|
np.testing.assert_array_equal(ds["hello"][1, [9, 10, 11]], [19, 0, 0])
|
|
1797
1838
|
np.testing.assert_array_equal(ds["hello"][1, slice(9, 12)], [19, 0, 0])
|
|
@@ -1877,9 +1918,9 @@ def test_h5netcdf_chunking(tmp_local_netcdf):
|
|
|
1877
1918
|
assert chunks_h5netcdf == (5, 5, 5, 10)
|
|
1878
1919
|
|
|
1879
1920
|
|
|
1880
|
-
def test_create_invalid_netcdf_catch_error(
|
|
1921
|
+
def test_create_invalid_netcdf_catch_error(tmp_local_or_remote_netcdf):
|
|
1881
1922
|
# see https://github.com/h5netcdf/h5netcdf/issues/138
|
|
1882
|
-
with h5netcdf.File(
|
|
1923
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as f:
|
|
1883
1924
|
try:
|
|
1884
1925
|
f.create_variable("test", ("x", "y"), data=np.ones((10, 10), dtype="bool"))
|
|
1885
1926
|
except CompatibilityError:
|
|
@@ -2186,3 +2227,506 @@ def test_ros3():
|
|
|
2186
2227
|
f = h5netcdf.File(fname, "r", driver="ros3")
|
|
2187
2228
|
assert "Temperature" in list(f)
|
|
2188
2229
|
f.close()
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
def test_user_type_errors_new_api(tmp_local_or_remote_netcdf):
|
|
2233
|
+
enum_dict1 = dict(one=1, two=2, three=3, missing=254)
|
|
2234
|
+
enum_dict2 = dict(one=0, two=2, three=3, missing=255)
|
|
2235
|
+
with h5netcdf.File("test.nc", "w") as ds0:
|
|
2236
|
+
enum_type_ext = ds0.create_enumtype(np.uint8, "enum_t", enum_dict1)
|
|
2237
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2238
|
+
ds.dimensions = {"enum_dim": 4}
|
|
2239
|
+
g = ds.create_group("subgroup")
|
|
2240
|
+
enum_type = ds.create_enumtype(np.uint8, "enum_t", enum_dict1)
|
|
2241
|
+
|
|
2242
|
+
if tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2243
|
+
testcontext = pytest.raises(RuntimeError, match="Conflict")
|
|
2244
|
+
else:
|
|
2245
|
+
testcontext = pytest.raises(KeyError, match="name already exists")
|
|
2246
|
+
with testcontext:
|
|
2247
|
+
ds.create_enumtype(np.uint8, "enum_t", enum_dict2)
|
|
2248
|
+
|
|
2249
|
+
enum_type2 = g.create_enumtype(np.uint8, "enum_t2", enum_dict2)
|
|
2250
|
+
g.create_enumtype(np.uint8, "enum_t", enum_dict2)
|
|
2251
|
+
with pytest.raises(TypeError, match="Please provide h5netcdf user type"):
|
|
2252
|
+
ds.create_variable(
|
|
2253
|
+
"enum_var1",
|
|
2254
|
+
("enum_dim",),
|
|
2255
|
+
dtype=enum_type._h5ds,
|
|
2256
|
+
fillvalue=enum_dict1["missing"],
|
|
2257
|
+
)
|
|
2258
|
+
with pytest.raises(TypeError, match="is not committed into current file"):
|
|
2259
|
+
ds.create_variable(
|
|
2260
|
+
"enum_var2",
|
|
2261
|
+
("enum_dim",),
|
|
2262
|
+
dtype=enum_type_ext,
|
|
2263
|
+
fillvalue=enum_dict1["missing"],
|
|
2264
|
+
)
|
|
2265
|
+
with pytest.raises(TypeError, match="is not accessible in current group"):
|
|
2266
|
+
ds.create_variable(
|
|
2267
|
+
"enum_var3",
|
|
2268
|
+
("enum_dim",),
|
|
2269
|
+
dtype=enum_type2,
|
|
2270
|
+
fillvalue=enum_dict2["missing"],
|
|
2271
|
+
)
|
|
2272
|
+
with pytest.raises(TypeError, match="Another dtype with same name"):
|
|
2273
|
+
g.create_variable(
|
|
2274
|
+
"enum_var4",
|
|
2275
|
+
("enum_dim",),
|
|
2276
|
+
dtype=enum_type,
|
|
2277
|
+
fillvalue=enum_dict2["missing"],
|
|
2278
|
+
)
|
|
2279
|
+
|
|
2280
|
+
|
|
2281
|
+
def test_user_type_errors_legacyapi(tmp_local_or_remote_netcdf):
|
|
2282
|
+
enum_dict1 = dict(one=1, two=2, three=3, missing=254)
|
|
2283
|
+
enum_dict2 = dict(one=0, two=2, three=3, missing=255)
|
|
2284
|
+
with legacyapi.Dataset("test.nc", "w") as ds0:
|
|
2285
|
+
enum_type_ext = ds0.createEnumType(np.uint8, "enum_t", enum_dict1)
|
|
2286
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2287
|
+
ds.createDimension("enum_dim", 4)
|
|
2288
|
+
g = ds.createGroup("subgroup")
|
|
2289
|
+
enum_type = ds.createEnumType(np.uint8, "enum_t", enum_dict1)
|
|
2290
|
+
if tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2291
|
+
testcontext = pytest.raises(RuntimeError, match="Conflict")
|
|
2292
|
+
else:
|
|
2293
|
+
testcontext = pytest.raises(KeyError, match="name already exists")
|
|
2294
|
+
with testcontext:
|
|
2295
|
+
ds.createEnumType(np.uint8, "enum_t", enum_dict1)
|
|
2296
|
+
|
|
2297
|
+
enum_type2 = g.createEnumType(np.uint8, "enum_t2", enum_dict2)
|
|
2298
|
+
g.create_enumtype(np.uint8, "enum_t", enum_dict2)
|
|
2299
|
+
with pytest.raises(TypeError, match="Please provide h5netcdf user type"):
|
|
2300
|
+
ds.createVariable(
|
|
2301
|
+
"enum_var1",
|
|
2302
|
+
enum_type._h5ds,
|
|
2303
|
+
("enum_dim",),
|
|
2304
|
+
fill_value=enum_dict1["missing"],
|
|
2305
|
+
)
|
|
2306
|
+
with pytest.raises(TypeError, match="is not committed into current file"):
|
|
2307
|
+
ds.createVariable(
|
|
2308
|
+
"enum_var2",
|
|
2309
|
+
enum_type_ext,
|
|
2310
|
+
("enum_dim",),
|
|
2311
|
+
fill_value=enum_dict1["missing"],
|
|
2312
|
+
)
|
|
2313
|
+
with pytest.raises(TypeError, match="is not accessible in current group"):
|
|
2314
|
+
ds.createVariable(
|
|
2315
|
+
"enum_var3",
|
|
2316
|
+
enum_type2,
|
|
2317
|
+
("enum_dim",),
|
|
2318
|
+
fill_value=enum_dict2["missing"],
|
|
2319
|
+
)
|
|
2320
|
+
with pytest.raises(TypeError, match="Another dtype with same name"):
|
|
2321
|
+
g.createVariable(
|
|
2322
|
+
"enum_var4",
|
|
2323
|
+
enum_type,
|
|
2324
|
+
("enum_dim",),
|
|
2325
|
+
fill_value=enum_dict2["missing"],
|
|
2326
|
+
)
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
def test_enum_type_errors_new_api(tmp_local_or_remote_netcdf):
|
|
2330
|
+
enum_dict1 = dict(one=1, two=2, three=3, missing=254)
|
|
2331
|
+
enum_dict2 = dict(one=0, two=2, three=3, missing=255)
|
|
2332
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2333
|
+
ds.dimensions = {"enum_dim": 4}
|
|
2334
|
+
enum_type = ds.create_enumtype(np.uint8, "enum_t", enum_dict1)
|
|
2335
|
+
enum_type2 = ds.create_enumtype(np.uint8, "enum_t2", enum_dict2)
|
|
2336
|
+
|
|
2337
|
+
# 1.
|
|
2338
|
+
with pytest.warns(UserWarning, match="default fill_value 0 which IS defined"):
|
|
2339
|
+
ds.create_variable(
|
|
2340
|
+
"enum_var1",
|
|
2341
|
+
("enum_dim",),
|
|
2342
|
+
dtype=enum_type2,
|
|
2343
|
+
)
|
|
2344
|
+
# 2. is for legacyapi only
|
|
2345
|
+
# 3.
|
|
2346
|
+
with pytest.warns(
|
|
2347
|
+
UserWarning, match="default fill_value 0 which IS NOT defined"
|
|
2348
|
+
):
|
|
2349
|
+
ds.create_variable(
|
|
2350
|
+
"enum_var2",
|
|
2351
|
+
("enum_dim",),
|
|
2352
|
+
dtype=enum_type,
|
|
2353
|
+
)
|
|
2354
|
+
# 4.
|
|
2355
|
+
with pytest.warns(
|
|
2356
|
+
UserWarning, match="with specified fill_value 0 which IS NOT"
|
|
2357
|
+
):
|
|
2358
|
+
ds.create_variable(
|
|
2359
|
+
"enum_var3",
|
|
2360
|
+
("enum_dim",),
|
|
2361
|
+
dtype=enum_type,
|
|
2362
|
+
fillvalue=0,
|
|
2363
|
+
)
|
|
2364
|
+
# 5.
|
|
2365
|
+
with pytest.raises(
|
|
2366
|
+
ValueError, match="with specified fill_value 100 which IS NOT"
|
|
2367
|
+
):
|
|
2368
|
+
ds.create_variable(
|
|
2369
|
+
"enum_var4",
|
|
2370
|
+
("enum_dim",),
|
|
2371
|
+
dtype=enum_type,
|
|
2372
|
+
fillvalue=100,
|
|
2373
|
+
)
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
def test_enum_type_errors_legacyapi(tmp_local_or_remote_netcdf):
|
|
2377
|
+
enum_dict1 = dict(one=1, two=2, three=3, missing=254)
|
|
2378
|
+
enum_dict2 = dict(one=0, two=2, three=3, missing=255)
|
|
2379
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2380
|
+
ds.createDimension("enum_dim", 4)
|
|
2381
|
+
enum_type = ds.createEnumType(np.uint8, "enum_t", enum_dict1)
|
|
2382
|
+
enum_type2 = ds.createEnumType(np.uint8, "enum_t2", enum_dict2)
|
|
2383
|
+
|
|
2384
|
+
# 1.
|
|
2385
|
+
with pytest.warns(UserWarning, match="default fill_value 255 which IS defined"):
|
|
2386
|
+
ds.createVariable(
|
|
2387
|
+
"enum_var1",
|
|
2388
|
+
enum_type2,
|
|
2389
|
+
("enum_dim",),
|
|
2390
|
+
)
|
|
2391
|
+
# 2.
|
|
2392
|
+
with pytest.raises(ValueError, match="default fill_value 255 which IS NOT"):
|
|
2393
|
+
ds.createVariable(
|
|
2394
|
+
"enum_var2",
|
|
2395
|
+
enum_type,
|
|
2396
|
+
("enum_dim",),
|
|
2397
|
+
)
|
|
2398
|
+
# 3. is only for new api
|
|
2399
|
+
# 4.
|
|
2400
|
+
with pytest.warns(
|
|
2401
|
+
UserWarning, match="interpreted as '_UNDEFINED' by netcdf-c."
|
|
2402
|
+
):
|
|
2403
|
+
ds.createVariable(
|
|
2404
|
+
"enum_var3",
|
|
2405
|
+
enum_type,
|
|
2406
|
+
("enum_dim",),
|
|
2407
|
+
fill_value=0,
|
|
2408
|
+
)
|
|
2409
|
+
# 5.
|
|
2410
|
+
with pytest.raises(
|
|
2411
|
+
ValueError, match="with specified fill_value 100 which IS NOT"
|
|
2412
|
+
):
|
|
2413
|
+
ds.createVariable("enum_var4", enum_type, ("enum_dim",), fill_value=100)
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
def test_enum_type(tmp_local_or_remote_netcdf):
|
|
2417
|
+
# test EnumType
|
|
2418
|
+
enum_dict = dict(one=1, two=2, three=3, missing=255)
|
|
2419
|
+
enum_dict2 = dict(one=1, two=2, three=3, missing=254)
|
|
2420
|
+
|
|
2421
|
+
# first with new API
|
|
2422
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2423
|
+
ds.dimensions = {"enum_dim": 4}
|
|
2424
|
+
ds.create_enumtype(np.uint8, "enum_t2", enum_dict2)
|
|
2425
|
+
enum_type = ds.create_enumtype(np.uint8, "enum_t", enum_dict)
|
|
2426
|
+
v = ds.create_variable(
|
|
2427
|
+
"enum_var", ("enum_dim",), dtype=enum_type, fillvalue=enum_dict["missing"]
|
|
2428
|
+
)
|
|
2429
|
+
v[0:3] = [1, 2, 3]
|
|
2430
|
+
with pytest.raises(ValueError) as e:
|
|
2431
|
+
v[3] = 5
|
|
2432
|
+
assert "assign illegal value(s)" in e.value.args[0]
|
|
2433
|
+
|
|
2434
|
+
# check, if new API can read them
|
|
2435
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2436
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2437
|
+
enum_var = ds["enum_var"]
|
|
2438
|
+
assert enum_type.enum_dict == enum_dict
|
|
2439
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2440
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2441
|
+
assert enum_var.datatype == enum_type
|
|
2442
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2443
|
+
|
|
2444
|
+
# check if legacyapi can read them
|
|
2445
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2446
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2447
|
+
enum_var = ds["enum_var"]
|
|
2448
|
+
assert enum_type.enum_dict == enum_dict
|
|
2449
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2450
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2451
|
+
assert enum_var.datatype == enum_type
|
|
2452
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2453
|
+
|
|
2454
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2455
|
+
# check if netCDF4-python can read them
|
|
2456
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2457
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2458
|
+
enum_var = ds["enum_var"]
|
|
2459
|
+
assert enum_type.enum_dict == enum_dict
|
|
2460
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2461
|
+
assert enum_var._FillValue == 255
|
|
2462
|
+
assert repr(enum_var.datatype) == repr(enum_type)
|
|
2463
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2464
|
+
|
|
2465
|
+
# second with legacyapi
|
|
2466
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2467
|
+
ds.createDimension("enum_dim", 4)
|
|
2468
|
+
enum_type = ds.createEnumType(np.uint8, "enum_t", enum_dict)
|
|
2469
|
+
v = ds.createVariable(
|
|
2470
|
+
"enum_var", enum_type, ("enum_dim",), fill_value=enum_dict["missing"]
|
|
2471
|
+
)
|
|
2472
|
+
v[0:3] = [1, 2, 3]
|
|
2473
|
+
with pytest.raises(ValueError) as e:
|
|
2474
|
+
v[3] = 5
|
|
2475
|
+
assert "assign illegal value(s)" in e.value.args[0]
|
|
2476
|
+
|
|
2477
|
+
# check, if new API can read them
|
|
2478
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2479
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2480
|
+
enum_var = ds["enum_var"]
|
|
2481
|
+
assert enum_type.enum_dict == enum_dict
|
|
2482
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2483
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2484
|
+
assert enum_var.datatype == enum_type
|
|
2485
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2486
|
+
|
|
2487
|
+
# check if legacyapi can read them
|
|
2488
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2489
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2490
|
+
enum_var = ds["enum_var"]
|
|
2491
|
+
assert enum_type.enum_dict == enum_dict
|
|
2492
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2493
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2494
|
+
assert enum_var.datatype == enum_type
|
|
2495
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2496
|
+
|
|
2497
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2498
|
+
# check if netCDF4-python can read them
|
|
2499
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2500
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2501
|
+
enum_var = ds["enum_var"]
|
|
2502
|
+
assert enum_type.enum_dict == enum_dict
|
|
2503
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2504
|
+
assert enum_var._FillValue == 255
|
|
2505
|
+
assert repr(enum_var.datatype) == repr(enum_type)
|
|
2506
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2507
|
+
|
|
2508
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2509
|
+
# third with netCDF4 api
|
|
2510
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2511
|
+
ds.createDimension("enum_dim", 4)
|
|
2512
|
+
enum_type = ds.createEnumType(np.uint8, "enum_t", enum_dict)
|
|
2513
|
+
v = ds.createVariable(
|
|
2514
|
+
"enum_var", enum_type, ("enum_dim",), fill_value=enum_dict["missing"]
|
|
2515
|
+
)
|
|
2516
|
+
v[0:3] = [1, 2, 3]
|
|
2517
|
+
with pytest.raises(
|
|
2518
|
+
ValueError, match="assign illegal value to Enum variable"
|
|
2519
|
+
):
|
|
2520
|
+
v[3] = 5
|
|
2521
|
+
|
|
2522
|
+
# check, if new API can read them
|
|
2523
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2524
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2525
|
+
enum_var = ds["enum_var"]
|
|
2526
|
+
assert enum_type.enum_dict == enum_dict
|
|
2527
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2528
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2529
|
+
assert enum_var.datatype == enum_type
|
|
2530
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2531
|
+
|
|
2532
|
+
# check if legacyapi can read them
|
|
2533
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2534
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2535
|
+
enum_var = ds["enum_var"]
|
|
2536
|
+
assert enum_type.enum_dict == enum_dict
|
|
2537
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2538
|
+
assert enum_var.attrs["_FillValue"] == 255
|
|
2539
|
+
assert enum_var.datatype == enum_type
|
|
2540
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2541
|
+
|
|
2542
|
+
# check if netCDF4-python can read them
|
|
2543
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2544
|
+
enum_type = ds.enumtypes["enum_t"]
|
|
2545
|
+
enum_var = ds["enum_var"]
|
|
2546
|
+
assert enum_type.enum_dict == enum_dict
|
|
2547
|
+
assert array_equal(enum_var, np.ma.masked_equal([1, 2, 3, 255], 255))
|
|
2548
|
+
assert enum_var._FillValue == 255
|
|
2549
|
+
assert repr(enum_var.datatype) == repr(enum_type)
|
|
2550
|
+
assert enum_var.datatype.name == "enum_t"
|
|
2551
|
+
|
|
2552
|
+
|
|
2553
|
+
@pytest.mark.parametrize("dtype", ["int", "int8", "uint16", "float32", "int64"])
|
|
2554
|
+
def test_vltype_creation(tmp_local_or_remote_netcdf, netcdf_write_module, dtype):
|
|
2555
|
+
# skip for netCDF4 writer for remote hsds files
|
|
2556
|
+
if netcdf_write_module == netCDF4 and tmp_local_or_remote_netcdf.startswith(
|
|
2557
|
+
remote_h5
|
|
2558
|
+
):
|
|
2559
|
+
pytest.skip()
|
|
2560
|
+
|
|
2561
|
+
with netcdf_write_module.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2562
|
+
ds.createVLType(dtype, "vlen_t")
|
|
2563
|
+
|
|
2564
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2565
|
+
vlen_type = ds.vltypes["vlen_t"]
|
|
2566
|
+
assert isinstance(vlen_type, VLType)
|
|
2567
|
+
assert h5py.check_vlen_dtype(vlen_type.dtype) == np.dtype(dtype)
|
|
2568
|
+
assert vlen_type.name == "vlen_t"
|
|
2569
|
+
|
|
2570
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2571
|
+
vlen_type = ds.vltypes["vlen_t"]
|
|
2572
|
+
assert isinstance(vlen_type, legacyapi.VLType)
|
|
2573
|
+
assert h5py.check_vlen_dtype(vlen_type.dtype) == np.dtype(dtype)
|
|
2574
|
+
assert vlen_type.name == "vlen_t"
|
|
2575
|
+
|
|
2576
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2577
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2578
|
+
vlen_type = ds.vltypes["vlen_t"]
|
|
2579
|
+
assert isinstance(vlen_type, netCDF4.VLType)
|
|
2580
|
+
assert vlen_type.dtype == np.dtype(dtype)
|
|
2581
|
+
assert vlen_type.name == "vlen_t"
|
|
2582
|
+
|
|
2583
|
+
|
|
2584
|
+
def test_compoundtype_creation(tmp_local_or_remote_netcdf, netcdf_write_module):
|
|
2585
|
+
# compound type is created with array of chars
|
|
2586
|
+
compound = np.dtype(
|
|
2587
|
+
[
|
|
2588
|
+
("time", np.int32),
|
|
2589
|
+
("station_name", "S1", 10),
|
|
2590
|
+
("temperature", np.float32),
|
|
2591
|
+
("pressure", np.float32),
|
|
2592
|
+
]
|
|
2593
|
+
)
|
|
2594
|
+
|
|
2595
|
+
# data is filled with fixed strings
|
|
2596
|
+
compound2 = np.dtype(
|
|
2597
|
+
[
|
|
2598
|
+
("time", np.int32),
|
|
2599
|
+
("station_name", "S10"),
|
|
2600
|
+
("temperature", np.float32),
|
|
2601
|
+
("pressure", np.float32),
|
|
2602
|
+
]
|
|
2603
|
+
)
|
|
2604
|
+
cmp_array = np.array(
|
|
2605
|
+
[
|
|
2606
|
+
(0, *["Boulder"], 0.0, 0.0),
|
|
2607
|
+
(1, *["New York"], 2.0, 3.0),
|
|
2608
|
+
(2, *["Denver"], 4.0, 6.0),
|
|
2609
|
+
(3, *["Washington"], 5.0, 7.0),
|
|
2610
|
+
(4, *["Wachtberg"], 6.0, 8.0),
|
|
2611
|
+
],
|
|
2612
|
+
dtype=compound2,
|
|
2613
|
+
)
|
|
2614
|
+
if (
|
|
2615
|
+
netcdf_write_module.__name__ == "netCDF4"
|
|
2616
|
+
and tmp_local_or_remote_netcdf.startswith(remote_h5)
|
|
2617
|
+
):
|
|
2618
|
+
pytest.skip("does not work for netCDF4")
|
|
2619
|
+
with netcdf_write_module.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
2620
|
+
ds.createDimension("x", 5)
|
|
2621
|
+
ds.createGroup("test")
|
|
2622
|
+
compound_t = ds.createCompoundType(compound, "cmp_t")
|
|
2623
|
+
var = ds.createVariable("data", compound_t, ("x",))
|
|
2624
|
+
var[:] = cmp_array
|
|
2625
|
+
|
|
2626
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2627
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2628
|
+
cmptype = ds.cmptypes["cmp_t"]
|
|
2629
|
+
assert isinstance(cmptype, netCDF4.CompoundType)
|
|
2630
|
+
assert cmptype.name == "cmp_t"
|
|
2631
|
+
assert array_equal(ds["data"][:], cmp_array)
|
|
2632
|
+
assert ds["data"].datatype == cmptype.dtype
|
|
2633
|
+
|
|
2634
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2635
|
+
cmptype = ds.cmptypes["cmp_t"]
|
|
2636
|
+
assert isinstance(cmptype, h5netcdf.legacyapi.CompoundType)
|
|
2637
|
+
assert cmptype.name == "cmp_t"
|
|
2638
|
+
assert array_equal(ds["data"][:], cmp_array)
|
|
2639
|
+
assert ds["data"].datatype == cmptype
|
|
2640
|
+
assert ds["data"].dtype == cmptype.dtype
|
|
2641
|
+
|
|
2642
|
+
|
|
2643
|
+
@pytest.mark.skipif(
|
|
2644
|
+
version.parse(netCDF4.__version__) < version.parse("1.7.0"),
|
|
2645
|
+
reason="does not work before netCDF4 v1.7.0",
|
|
2646
|
+
)
|
|
2647
|
+
def test_nc_complex_compatibility(tmp_local_or_remote_netcdf, netcdf_write_module):
|
|
2648
|
+
# native complex
|
|
2649
|
+
complex_array = np.array([0 + 0j, 1 + 0j, 0 + 1j, 1 + 1j, 0.25 + 0.75j])
|
|
2650
|
+
# compound complex
|
|
2651
|
+
complex128 = np.dtype(
|
|
2652
|
+
{
|
|
2653
|
+
"names": ["r", "i"],
|
|
2654
|
+
"formats": ["f8", "f8"],
|
|
2655
|
+
"offsets": [0, 8],
|
|
2656
|
+
"itemsize": 16,
|
|
2657
|
+
"aligned": True,
|
|
2658
|
+
}
|
|
2659
|
+
)
|
|
2660
|
+
cdata = np.array(
|
|
2661
|
+
[(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.25, 0.75)], dtype=complex128
|
|
2662
|
+
)
|
|
2663
|
+
kwargs = {}
|
|
2664
|
+
if (
|
|
2665
|
+
netcdf_write_module.__name__ == "netCDF4"
|
|
2666
|
+
and tmp_local_or_remote_netcdf.startswith(remote_h5)
|
|
2667
|
+
):
|
|
2668
|
+
pytest.skip("does not work for netCDF4")
|
|
2669
|
+
|
|
2670
|
+
if netcdf_write_module.__name__ == "netCDF4":
|
|
2671
|
+
kwargs.update(auto_complex=True)
|
|
2672
|
+
with netcdf_write_module.Dataset(tmp_local_or_remote_netcdf, "w", **kwargs) as ds:
|
|
2673
|
+
ds.createDimension("x", size=len(complex_array))
|
|
2674
|
+
var = ds.createVariable("data", "c16", ("x",))
|
|
2675
|
+
var[:] = complex_array
|
|
2676
|
+
|
|
2677
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "r") as ds:
|
|
2678
|
+
dtype = ds.cmptypes["_PFNC_DOUBLE_COMPLEX_TYPE"]
|
|
2679
|
+
assert isinstance(dtype, h5netcdf.legacyapi.CompoundType)
|
|
2680
|
+
assert dtype.name == "_PFNC_DOUBLE_COMPLEX_TYPE"
|
|
2681
|
+
assert array_equal(ds["data"][:], complex_array)
|
|
2682
|
+
|
|
2683
|
+
if not tmp_local_or_remote_netcdf.startswith(remote_h5):
|
|
2684
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r", auto_complex=True) as ds:
|
|
2685
|
+
dtype = ds.cmptypes["_PFNC_DOUBLE_COMPLEX_TYPE"]
|
|
2686
|
+
assert isinstance(dtype, netCDF4._netCDF4.CompoundType)
|
|
2687
|
+
assert array_equal(ds["data"][:], complex_array)
|
|
2688
|
+
|
|
2689
|
+
with netCDF4.Dataset(tmp_local_or_remote_netcdf, "r", auto_complex=False) as ds:
|
|
2690
|
+
dtype = ds.cmptypes["_PFNC_DOUBLE_COMPLEX_TYPE"]
|
|
2691
|
+
assert isinstance(dtype, netCDF4._netCDF4.CompoundType)
|
|
2692
|
+
assert array_equal(ds["data"][:], cdata)
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
@pytest.mark.skipif(
|
|
2696
|
+
version.parse(netCDF4.__version__) < version.parse("1.7.0"),
|
|
2697
|
+
reason="does not work before netCDF4 v1.7.0",
|
|
2698
|
+
)
|
|
2699
|
+
def test_complex_type_creation_errors(tmp_local_netcdf):
|
|
2700
|
+
complex_array = np.array([0 + 0j, 1 + 0j, 0 + 1j, 1 + 1j, 0.25 + 0.75j])
|
|
2701
|
+
|
|
2702
|
+
with legacyapi.Dataset(tmp_local_netcdf, "w") as ds:
|
|
2703
|
+
ds.createDimension("x", size=len(complex_array))
|
|
2704
|
+
with pytest.raises(TypeError, match="data type 'c4' not understood"):
|
|
2705
|
+
ds.createVariable("data", "c4", ("x",))
|
|
2706
|
+
|
|
2707
|
+
with legacyapi.Dataset(tmp_local_netcdf, "w") as ds:
|
|
2708
|
+
ds.createDimension("x", size=len(complex_array))
|
|
2709
|
+
with pytest.raises(
|
|
2710
|
+
TypeError,
|
|
2711
|
+
match="Currently only 'complex64' and 'complex128' dtypes are allowed.",
|
|
2712
|
+
):
|
|
2713
|
+
ds.createVariable("data", "c32", ("x",))
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
def test_hsds(hsds_up):
|
|
2717
|
+
# test hsds setup/write
|
|
2718
|
+
if without_h5pyd:
|
|
2719
|
+
pytest.skip("h5pyd package not available")
|
|
2720
|
+
elif not hsds_up:
|
|
2721
|
+
pytest.skip("HSDS service not running")
|
|
2722
|
+
rnd = "".join(random.choice(string.ascii_uppercase) for _ in range(5))
|
|
2723
|
+
fname = (
|
|
2724
|
+
"hdf5://" + "home" + "/" + env["HS_USERNAME"] + "/" + "testfile" + rnd + ".nc"
|
|
2725
|
+
)
|
|
2726
|
+
with h5netcdf.File(fname, "w") as ds:
|
|
2727
|
+
g = ds.create_group("test")
|
|
2728
|
+
g.dimensions["x"] = None
|
|
2729
|
+
g.create_variable("var1", ("x",), dtype="i8")
|
|
2730
|
+
|
|
2731
|
+
with h5netcdf.File(fname, "r") as ds:
|
|
2732
|
+
print(ds["test"]["var1"])
|