h5netcdf 1.6.0__tar.gz → 1.6.2__tar.gz
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-1.6.0 → h5netcdf-1.6.2}/CHANGELOG.rst +20 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/PKG-INFO +4 -3
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/README.rst +1 -1
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/conf.py +1 -1
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/devguide.rst +4 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/index.rst +1 -1
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/_version.py +2 -2
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/core.py +32 -8
- h5netcdf-1.6.2/h5netcdf/tests/conftest.py +83 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/tests/test_h5netcdf.py +108 -20
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf.egg-info/PKG-INFO +4 -3
- h5netcdf-1.6.0/h5netcdf/tests/conftest.py +0 -65
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/.pre-commit-config.yaml +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/AUTHORS.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/LICENSE +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/Makefile +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/api.rst +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/changelog.rst +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/feature.rst +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/doc/legacyapi.rst +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/__init__.py +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/attrs.py +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/dimensions.py +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/legacyapi.py +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/tests/pytest.ini +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf/utils.py +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf.egg-info/SOURCES.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf.egg-info/dependency_links.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf.egg-info/requires.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/h5netcdf.egg-info/top_level.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/licenses/H5PY_LICENSE.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/licenses/PSF_LICENSE.txt +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/pyproject.toml +0 -0
- {h5netcdf-1.6.0 → h5netcdf-1.6.2}/setup.cfg +0 -0
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
Change Log
|
|
2
2
|
----------
|
|
3
3
|
|
|
4
|
+
Version 1.6.2 (June 26th, 2025):
|
|
5
|
+
|
|
6
|
+
- Codespell fixes ({pull}`261`).
|
|
7
|
+
By `Kurt Schwehr <https://github.com/schwehr>`_
|
|
8
|
+
- Fix hsds/h5pyd test fixture spinup issues ({pull}`265`).
|
|
9
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
10
|
+
- Fix and add circular referrer tests for Python 3.14 and update CI matrix ({pull}`264`).
|
|
11
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
12
|
+
- Avoid opening h5pyd file to check if there is a preexisting file,
|
|
13
|
+
instead remap mode "a" -> "r+", resort to "w" if file doesn't exist ({issue}`262`, {pull}`266`).
|
|
14
|
+
By `Jonas Grönberg <https://github.com/JonasGronberg>`_ and `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
15
|
+
- Reduce CI time by installing available scientific-python-nightly-wheels and using pip cache ({pull}`267`).
|
|
16
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
17
|
+
|
|
18
|
+
Version 1.6.1 (March 7th, 2025):
|
|
19
|
+
|
|
20
|
+
- Let Variable.chunks return None for scalar variables, independent of what the underlying
|
|
21
|
+
h5ds object returns ({pull}`259`).
|
|
22
|
+
By `Rickard Holmberg <https://github.com/rho-novatron>`_
|
|
23
|
+
|
|
4
24
|
Version 1.6.0 (March 7th, 2025):
|
|
5
25
|
|
|
6
26
|
- Allow specifying `h5netcdf.File(driver="h5pyd")` to force the use of h5pyd ({issue}`255`, {pull}`256`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: h5netcdf
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: netCDF4 via h5py
|
|
5
5
|
Author-email: Stephan Hoyer <shoyer@gmail.com>, Kai Mühlbauer <kmuehlbauer@wradlib.org>
|
|
6
6
|
Maintainer-email: h5netcdf developers <devteam@h5netcdf.org>
|
|
@@ -56,6 +56,7 @@ Requires-Dist: packaging
|
|
|
56
56
|
Provides-Extra: test
|
|
57
57
|
Requires-Dist: netCDF4; extra == "test"
|
|
58
58
|
Requires-Dist: pytest; extra == "test"
|
|
59
|
+
Dynamic: license-file
|
|
59
60
|
|
|
60
61
|
h5netcdf
|
|
61
62
|
========
|
|
@@ -318,7 +319,7 @@ The following describes the behavior of h5netcdf with respect to order tracking
|
|
|
318
319
|
for a few key versions:
|
|
319
320
|
|
|
320
321
|
- Version 0.12.0 and earlier, the ``track_order`` parameter`order was missing
|
|
321
|
-
and thus order tracking was
|
|
322
|
+
and thus order tracking was implicitly set to ``False``.
|
|
322
323
|
- Version 0.13.0 enabled order tracking by setting the parameter
|
|
323
324
|
``track_order`` to ``True`` by default without deprecation.
|
|
324
325
|
- Versions 0.13.1 to 1.0.2 set ``track_order`` to ``False`` due to a bug in a
|
|
@@ -259,7 +259,7 @@ The following describes the behavior of h5netcdf with respect to order tracking
|
|
|
259
259
|
for a few key versions:
|
|
260
260
|
|
|
261
261
|
- Version 0.12.0 and earlier, the ``track_order`` parameter`order was missing
|
|
262
|
-
and thus order tracking was
|
|
262
|
+
and thus order tracking was implicitly set to ``False``.
|
|
263
263
|
- Version 0.13.0 enabled order tracking by setting the parameter
|
|
264
264
|
``track_order`` to ``True`` by default without deprecation.
|
|
265
265
|
- Versions 0.13.1 to 1.0.2 set ``track_order`` to ``False`` due to a bug in a
|
|
@@ -18,10 +18,14 @@ Contributors
|
|
|
18
18
|
- `Ezequiel Cimadevilla Alvarez <https://github.com/zequihg50>`_
|
|
19
19
|
- `Frédéric Laliberté <https://github.com/laliberte>`_
|
|
20
20
|
- `Ghislain Vaillant <https://github.com/ghisvail>`_
|
|
21
|
+
- `John Readey <https://github.com/jreadey>`_
|
|
22
|
+
- `Jonas Grönberg <https://github.com/JonasGronberg>`_
|
|
23
|
+
- `Kurt Schwehr <https://github.com/schwehr>`_
|
|
21
24
|
- `Lion Krischer <https://github.com/krischer>`_
|
|
22
25
|
- `Mark Harfouche <https://github.com/hmaarrfk>`_
|
|
23
26
|
- `Martin Raspaud <https://github.com/mraspaud>`_
|
|
24
27
|
- `Pierre Augier <https://github.com/paugier>`_
|
|
28
|
+
- `Rickard Holmberg <https://github.com/rho-novatron>`_
|
|
25
29
|
- `Ryan Grout <https://github.com/groutr>`_
|
|
26
30
|
- `Scott Henderson <https://github.com/scottyhq>`_
|
|
27
31
|
- `Thomas Kluyver <https://github.com/takluyver>`_
|
|
@@ -50,7 +50,7 @@ by Stephan Hoyer. The first `official` ``h5netcdf`` announcement was made by Ste
|
|
|
50
50
|
`xarray issue tracker`_ only one day later.
|
|
51
51
|
|
|
52
52
|
The library evolved constantly over the years (fixing bugs and adding enhancements)
|
|
53
|
-
and gained contributions from
|
|
53
|
+
and gained contributions from 21 other :ref:`contributors` so far. The library is widely used,
|
|
54
54
|
especially as backend within `xarray`_.
|
|
55
55
|
|
|
56
56
|
Early 2020 Kai Mühlbauer started to add contributions and after some time he volunteered
|
|
@@ -608,6 +608,11 @@ class BaseVariable(BaseObject):
|
|
|
608
608
|
class Variable(BaseVariable):
|
|
609
609
|
@property
|
|
610
610
|
def chunks(self):
|
|
611
|
+
if self.shape == ():
|
|
612
|
+
# In HSDS, the layout can be chunked even for scalar datasets, but with only a single chunk.
|
|
613
|
+
# Return None for scalar datasets since they shall be handled as non-chunked.
|
|
614
|
+
assert self._h5ds.chunks in (None, (), (1,))
|
|
615
|
+
return None
|
|
611
616
|
return self._h5ds.chunks
|
|
612
617
|
|
|
613
618
|
@property
|
|
@@ -1514,16 +1519,35 @@ class File(Group):
|
|
|
1514
1519
|
"No module named 'h5pyd'. h5pyd is required for "
|
|
1515
1520
|
f"opening urls: {path}"
|
|
1516
1521
|
)
|
|
1522
|
+
self._preexisting_file = mode in {"r", "r+", "a"}
|
|
1523
|
+
# remap "a" -> "r+" to check file existence
|
|
1524
|
+
# fallback to "w" if not
|
|
1525
|
+
_mode = mode
|
|
1526
|
+
if mode == "a":
|
|
1527
|
+
mode = "r+"
|
|
1528
|
+
self._h5py = h5pyd
|
|
1517
1529
|
try:
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1530
|
+
self._h5file = self._h5py.File(
|
|
1531
|
+
path, mode, track_order=track_order, **kwargs
|
|
1532
|
+
)
|
|
1533
|
+
self._preexisting_file = mode != "w"
|
|
1521
1534
|
except OSError:
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1535
|
+
# if file does not exist, create it
|
|
1536
|
+
if _mode == "a":
|
|
1537
|
+
mode = "w"
|
|
1538
|
+
self._h5file = self._h5py.File(
|
|
1539
|
+
path, mode, track_order=track_order, **kwargs
|
|
1540
|
+
)
|
|
1541
|
+
self._preexisting_file = False
|
|
1542
|
+
msg = (
|
|
1543
|
+
"Append mode for h5pyd now probes with 'r+' first and "
|
|
1544
|
+
"only falls back to 'w' if the file is missing.\n"
|
|
1545
|
+
"To silence this warning use 'r+' (open-existing) or 'w' "
|
|
1546
|
+
"(create-new) directly."
|
|
1547
|
+
)
|
|
1548
|
+
warnings.warn(msg, UserWarning, stacklevel=2)
|
|
1549
|
+
else:
|
|
1550
|
+
raise
|
|
1527
1551
|
else:
|
|
1528
1552
|
self._preexisting_file = os.path.exists(path) and mode != "w"
|
|
1529
1553
|
self._h5py = h5py
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
import time
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from shutil import rmtree
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from h5pyd import Folder
|
|
11
|
+
from hsds.hsds_app import HsdsApp
|
|
12
|
+
|
|
13
|
+
with_reqd_pkgs = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
with_reqd_pkgs = False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(scope="session")
|
|
19
|
+
def hsds_up():
|
|
20
|
+
"""Provide HDF Highly Scalable Data Service (HSDS) for h5pyd testing."""
|
|
21
|
+
if not with_reqd_pkgs:
|
|
22
|
+
pytest.skip("Required packages h5pyd and hsds not available")
|
|
23
|
+
|
|
24
|
+
root_dir = Path(tempfile.mkdtemp(prefix="tmp-hsds-root-"))
|
|
25
|
+
bucket_name = "pytest"
|
|
26
|
+
os.environ["BUCKET_NAME"] = bucket_name
|
|
27
|
+
# need to create a directory for our bucket
|
|
28
|
+
(root_dir / bucket_name).mkdir()
|
|
29
|
+
|
|
30
|
+
kwargs = {
|
|
31
|
+
"username": "h5netcdf-pytest",
|
|
32
|
+
"password": "TestEarlyTestEverything",
|
|
33
|
+
"root_dir": str(root_dir),
|
|
34
|
+
"logfile": str(root_dir / "hsds.log"),
|
|
35
|
+
"log_level": "DEBUG",
|
|
36
|
+
"host": "localhost",
|
|
37
|
+
"sn_port": 5101,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
os.environ.update(
|
|
41
|
+
{
|
|
42
|
+
"BUCKET_NAME": bucket_name,
|
|
43
|
+
"HS_USERNAME": kwargs["username"],
|
|
44
|
+
"HS_PASSWORD": kwargs["password"],
|
|
45
|
+
"HS_USE_HTTPS": "False",
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
hsds = HsdsApp(**kwargs)
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
hsds.run()
|
|
53
|
+
timeout = time.time() + 60
|
|
54
|
+
while not hsds.ready:
|
|
55
|
+
if time.time() > timeout:
|
|
56
|
+
raise TimeoutError("HSDS server did not become ready in time")
|
|
57
|
+
time.sleep(1)
|
|
58
|
+
|
|
59
|
+
os.environ["HS_ENDPOINT"] = hsds.endpoint
|
|
60
|
+
# make folders expected by pytest
|
|
61
|
+
Folder("/home/", mode="w")
|
|
62
|
+
Folder("/home/h5netcdf-pytest/", mode="w")
|
|
63
|
+
|
|
64
|
+
yield True
|
|
65
|
+
|
|
66
|
+
except Exception as err:
|
|
67
|
+
log_path = kwargs["logfile"]
|
|
68
|
+
if os.path.exists(log_path):
|
|
69
|
+
with open(log_path) as f:
|
|
70
|
+
print("\n=== HSDS Log ===")
|
|
71
|
+
print(f.read())
|
|
72
|
+
else:
|
|
73
|
+
print(f"HSDS log not found at: {log_path}")
|
|
74
|
+
raise err
|
|
75
|
+
|
|
76
|
+
finally:
|
|
77
|
+
try:
|
|
78
|
+
hsds.check_processes()
|
|
79
|
+
hsds.stop()
|
|
80
|
+
except Exception:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
rmtree(root_dir, ignore_errors=True)
|
|
@@ -3,7 +3,9 @@ import io
|
|
|
3
3
|
import random
|
|
4
4
|
import re
|
|
5
5
|
import string
|
|
6
|
+
import sys
|
|
6
7
|
import tempfile
|
|
8
|
+
import weakref
|
|
7
9
|
from os import environ as env
|
|
8
10
|
|
|
9
11
|
import h5py
|
|
@@ -30,6 +32,7 @@ except ImportError:
|
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
remote_h5 = ("http:", "hdf5:")
|
|
35
|
+
python_version = version.parse(".".join(map(str, sys.version_info[:3])))
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
@pytest.fixture
|
|
@@ -37,26 +40,30 @@ def tmp_local_netcdf(tmpdir):
|
|
|
37
40
|
return str(tmpdir.join("testfile.nc"))
|
|
38
41
|
|
|
39
42
|
|
|
43
|
+
@pytest.fixture()
|
|
44
|
+
def setup_h5pyd_config(hsds_up):
|
|
45
|
+
env["HS_ENDPOINT"] = "http://127.0.0.1:5101"
|
|
46
|
+
env["HS_USERNAME"] = "h5netcdf-pytest"
|
|
47
|
+
env["HS_PASSWORD"] = "TestEarlyTestEverything"
|
|
48
|
+
env["HS_USE_HTTPS"] = "False"
|
|
49
|
+
|
|
50
|
+
|
|
40
51
|
@pytest.fixture(params=["testfile.nc", "hdf5://testfile"])
|
|
41
|
-
def tmp_local_or_remote_netcdf(request, tmpdir
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
+ "testfile"
|
|
55
|
-
+ rnd
|
|
56
|
-
+ ".nc"
|
|
57
|
-
)
|
|
52
|
+
def tmp_local_or_remote_netcdf(request, tmpdir):
|
|
53
|
+
param = request.param
|
|
54
|
+
if param.startswith(remote_h5):
|
|
55
|
+
try:
|
|
56
|
+
hsds_up = request.getfixturevalue("hsds_up")
|
|
57
|
+
except pytest.skip.Exception:
|
|
58
|
+
pytest.skip("HSDS not available")
|
|
59
|
+
|
|
60
|
+
if not hsds_up:
|
|
61
|
+
pytest.skip("HSDS fixture returned False (not running)")
|
|
62
|
+
|
|
63
|
+
rnd = "".join(random.choices(string.ascii_uppercase, k=5))
|
|
64
|
+
return f"hdf5://home/{env['HS_USERNAME']}/testfile{rnd}.nc"
|
|
58
65
|
else:
|
|
59
|
-
return str(tmpdir.join(
|
|
66
|
+
return str(tmpdir.join(param))
|
|
60
67
|
|
|
61
68
|
|
|
62
69
|
@pytest.fixture(params=[True, False])
|
|
@@ -1300,6 +1307,24 @@ def test_overwrite_existing_file(tmp_local_netcdf):
|
|
|
1300
1307
|
assert ds.attrs._h5attrs.get("_NCProperties", False)
|
|
1301
1308
|
|
|
1302
1309
|
|
|
1310
|
+
def test_overwrite_existing_remote_file(tmp_local_or_remote_netcdf):
|
|
1311
|
+
# create file with legacyapi
|
|
1312
|
+
with legacyapi.Dataset(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1313
|
+
ds.createDimension("x", 10)
|
|
1314
|
+
|
|
1315
|
+
# check attribute
|
|
1316
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1317
|
+
assert ds.attrs._h5attrs.get("_NCProperties", False)
|
|
1318
|
+
|
|
1319
|
+
# overwrite file with new api
|
|
1320
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1321
|
+
ds.dimensions["x"] = 10
|
|
1322
|
+
|
|
1323
|
+
# check attribute
|
|
1324
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1325
|
+
assert ds.attrs._h5attrs.get("_NCProperties", False)
|
|
1326
|
+
|
|
1327
|
+
|
|
1303
1328
|
def test_scales_on_append(tmp_local_netcdf):
|
|
1304
1329
|
# create file with _NCProperties attribute
|
|
1305
1330
|
with netCDF4.Dataset(tmp_local_netcdf, "w") as ds:
|
|
@@ -1555,7 +1580,38 @@ def test_no_circular_references(tmp_local_or_remote_netcdf):
|
|
|
1555
1580
|
refs = gc.get_referrers(ds)
|
|
1556
1581
|
for ref in refs:
|
|
1557
1582
|
print(ref)
|
|
1558
|
-
|
|
1583
|
+
if python_version >= version.parse("3.14"):
|
|
1584
|
+
assert len(refs) == 0
|
|
1585
|
+
else:
|
|
1586
|
+
assert len(refs) == 1
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
def test_no_circular_references_py314(tmp_local_or_remote_netcdf):
|
|
1590
|
+
# https://github.com/h5py/h5py/issues/2019
|
|
1591
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "w") as ds:
|
|
1592
|
+
ds.dimensions["x"] = 2
|
|
1593
|
+
ds.dimensions["y"] = 2
|
|
1594
|
+
|
|
1595
|
+
# clean up everything
|
|
1596
|
+
gc.collect()
|
|
1597
|
+
gc.garbage.clear()
|
|
1598
|
+
|
|
1599
|
+
# use weakref to hold on object
|
|
1600
|
+
file_ref = None
|
|
1601
|
+
with h5netcdf.File(tmp_local_or_remote_netcdf, "r") as ds:
|
|
1602
|
+
file_ref = weakref.ref(ds)
|
|
1603
|
+
|
|
1604
|
+
# clean up
|
|
1605
|
+
gc.collect()
|
|
1606
|
+
|
|
1607
|
+
# check garbage list
|
|
1608
|
+
if file_ref() is not None:
|
|
1609
|
+
print("Uncollectable object:", file_ref())
|
|
1610
|
+
print("Potential GC garbage:")
|
|
1611
|
+
for obj in gc.garbage:
|
|
1612
|
+
print(repr(obj))
|
|
1613
|
+
|
|
1614
|
+
assert file_ref() is None or "<Closed h5netcdf.File>"
|
|
1559
1615
|
|
|
1560
1616
|
|
|
1561
1617
|
def test_expanded_variables_netcdf4(tmp_local_netcdf, netcdf_write_module):
|
|
@@ -1693,7 +1749,7 @@ def test_track_order_specification(tmp_local_netcdf):
|
|
|
1693
1749
|
# While netcdf4-c has historically only allowed track_order to be True
|
|
1694
1750
|
# There doesn't seem to be a good reason for this
|
|
1695
1751
|
# https://github.com/Unidata/netcdf-c/issues/2054 historically, h5netcdf
|
|
1696
|
-
# has not specified this parameter (leaving it
|
|
1752
|
+
# has not specified this parameter (leaving it implicitly as False)
|
|
1697
1753
|
# We want to make sure we allow both here
|
|
1698
1754
|
with h5netcdf.File(tmp_local_netcdf, "w", track_order=False):
|
|
1699
1755
|
pass
|
|
@@ -2757,3 +2813,35 @@ def test_h5pyd_driver(hsds_up):
|
|
|
2757
2813
|
with h5netcdf.File(fname, "w", driver="h5pyd") as ds:
|
|
2758
2814
|
assert ds._h5py == h5pyd
|
|
2759
2815
|
assert isinstance(ds._h5file, h5pyd.File)
|
|
2816
|
+
|
|
2817
|
+
|
|
2818
|
+
def test_h5pyd_nonchunked_scalars(hsds_up):
|
|
2819
|
+
if without_h5pyd:
|
|
2820
|
+
pytest.skip("h5pyd package not available")
|
|
2821
|
+
elif not hsds_up:
|
|
2822
|
+
pytest.skip("HSDS service not running")
|
|
2823
|
+
rnd = "".join(random.choice(string.ascii_uppercase) for _ in range(5))
|
|
2824
|
+
fname = f"hdf5://testfile{rnd}.nc"
|
|
2825
|
+
with h5pyd.File(fname, "w") as ds:
|
|
2826
|
+
ds.create_dataset("foo", data=b"1234")
|
|
2827
|
+
with h5netcdf.File(fname, "r", driver="h5pyd") as ds:
|
|
2828
|
+
# HSDS stores this as a chunked dataset, but only with a single chunk
|
|
2829
|
+
assert ds["foo"]._h5ds.chunks == (1,)
|
|
2830
|
+
# However, since it is a scalar dataset, we should not expose the chunking
|
|
2831
|
+
assert ds["foo"].chunks is None
|
|
2832
|
+
|
|
2833
|
+
|
|
2834
|
+
def test_h5pyd_append(hsds_up):
|
|
2835
|
+
if without_h5pyd:
|
|
2836
|
+
pytest.skip("h5pyd package not available")
|
|
2837
|
+
elif not hsds_up:
|
|
2838
|
+
pytest.skip("HSDS service not running")
|
|
2839
|
+
rnd = "".join(random.choice(string.ascii_uppercase) for _ in range(5))
|
|
2840
|
+
fname = f"hdf5://testfile{rnd}.nc"
|
|
2841
|
+
|
|
2842
|
+
with pytest.warns(UserWarning, match="Append mode for h5pyd"):
|
|
2843
|
+
with h5netcdf.File(fname, "a", driver="h5pyd") as ds:
|
|
2844
|
+
assert not ds._preexisting_file
|
|
2845
|
+
|
|
2846
|
+
with h5netcdf.File(fname, "a", driver="h5pyd") as ds:
|
|
2847
|
+
assert ds._preexisting_file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: h5netcdf
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: netCDF4 via h5py
|
|
5
5
|
Author-email: Stephan Hoyer <shoyer@gmail.com>, Kai Mühlbauer <kmuehlbauer@wradlib.org>
|
|
6
6
|
Maintainer-email: h5netcdf developers <devteam@h5netcdf.org>
|
|
@@ -56,6 +56,7 @@ Requires-Dist: packaging
|
|
|
56
56
|
Provides-Extra: test
|
|
57
57
|
Requires-Dist: netCDF4; extra == "test"
|
|
58
58
|
Requires-Dist: pytest; extra == "test"
|
|
59
|
+
Dynamic: license-file
|
|
59
60
|
|
|
60
61
|
h5netcdf
|
|
61
62
|
========
|
|
@@ -318,7 +319,7 @@ The following describes the behavior of h5netcdf with respect to order tracking
|
|
|
318
319
|
for a few key versions:
|
|
319
320
|
|
|
320
321
|
- Version 0.12.0 and earlier, the ``track_order`` parameter`order was missing
|
|
321
|
-
and thus order tracking was
|
|
322
|
+
and thus order tracking was implicitly set to ``False``.
|
|
322
323
|
- Version 0.13.0 enabled order tracking by setting the parameter
|
|
323
324
|
``track_order`` to ``True`` by default without deprecation.
|
|
324
325
|
- Versions 0.13.1 to 1.0.2 set ``track_order`` to ``False`` due to a bug in a
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import tempfile
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from shutil import rmtree
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
try:
|
|
9
|
-
from h5pyd import Folder
|
|
10
|
-
from hsds.hsds_app import HsdsApp
|
|
11
|
-
|
|
12
|
-
with_reqd_pkgs = True
|
|
13
|
-
except ImportError:
|
|
14
|
-
with_reqd_pkgs = False
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@pytest.fixture(scope="session")
|
|
18
|
-
def hsds_up():
|
|
19
|
-
"""Provide HDF Highly Scalabale Data Service (HSDS) for h5pyd testing."""
|
|
20
|
-
if with_reqd_pkgs:
|
|
21
|
-
root_dir = Path(tempfile.mkdtemp(prefix="tmp-hsds-root-"))
|
|
22
|
-
bucket_name = "pytest"
|
|
23
|
-
os.environ["BUCKET_NAME"] = bucket_name
|
|
24
|
-
os.mkdir(
|
|
25
|
-
f"{root_dir}/{bucket_name}"
|
|
26
|
-
) # need to create a directory for our bucket
|
|
27
|
-
|
|
28
|
-
hs_username = "h5netcdf-pytest"
|
|
29
|
-
hs_password = "TestEarlyTestEverything"
|
|
30
|
-
|
|
31
|
-
kwargs = {}
|
|
32
|
-
kwargs["username"] = hs_username
|
|
33
|
-
kwargs["password"] = hs_password
|
|
34
|
-
kwargs["root_dir"] = str(root_dir)
|
|
35
|
-
kwargs["logfile"] = f"{root_dir}/hsds.log"
|
|
36
|
-
kwargs["log_level"] = "DEBUG"
|
|
37
|
-
kwargs["host"] = "localhost"
|
|
38
|
-
kwargs["sn_port"] = 5101
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
hsds = HsdsApp(**kwargs)
|
|
42
|
-
|
|
43
|
-
hsds.run()
|
|
44
|
-
is_up = hsds.ready
|
|
45
|
-
|
|
46
|
-
if is_up:
|
|
47
|
-
os.environ["HS_ENDPOINT"] = hsds.endpoint
|
|
48
|
-
os.environ["HS_USERNAME"] = hs_username
|
|
49
|
-
os.environ["HS_PASSWORD"] = hs_password
|
|
50
|
-
# make folders expected by pytest
|
|
51
|
-
# pytest/home/h5netcdf-pytest
|
|
52
|
-
# Folder("/pytest/", mode='w')
|
|
53
|
-
Folder("/home/", mode="w")
|
|
54
|
-
Folder("/home/h5netcdf-pytest/", mode="w")
|
|
55
|
-
except Exception:
|
|
56
|
-
is_up = False
|
|
57
|
-
|
|
58
|
-
yield is_up
|
|
59
|
-
hsds.check_processes() # this will capture hsds log output
|
|
60
|
-
hsds.stop()
|
|
61
|
-
|
|
62
|
-
rmtree(root_dir, ignore_errors=True)
|
|
63
|
-
|
|
64
|
-
else:
|
|
65
|
-
yield False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|