diff --git a/docs/config.rst b/docs/config.rst index 9eb188b..97d4db9 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -24,9 +24,8 @@ attributes: are iterated in ascending creation order (consistent with ``dict`` in Python 3.7+); otherwise in ascending alphanumeric order. Global configuration value can be overridden for - particular container by specifying ``track_order`` argument to - :class:`h5py.File`, :meth:`h5py.Group.create_group`, - :meth:`h5py.Group.create_dataset`. The default is ``False``. + particular file and its subgroups by specifying ``track_order`` argument to + :class:`h5py.File`. The default is ``False``. IPython diff --git a/h5pyd/_hl/files.py b/h5pyd/_hl/files.py index ee8dbf2..4784fda 100644 --- a/h5pyd/_hl/files.py +++ b/h5pyd/_hl/files.py @@ -119,6 +119,7 @@ def __init__( logger=None, owner=None, linked_domain=None, + track_order=False, retries=10, timeout=180, **kwds, @@ -154,6 +155,9 @@ def __init__( by admin users linked_domain Create new domain using the root of the linked domain + track_order + Whether to track dataset/group/attribute creation order within this file. Objects will be iterated + in ascending creation order if this is enabled, otherwise in ascending alphanumeric order. retries Number of retry attempts to be used if a server request fails timeout @@ -248,6 +252,7 @@ def __init__( use_session=use_session, use_cache=use_cache, logger=logger, + track_order=track_order, retries=retries, timeout=timeout, ) diff --git a/h5pyd/_hl/group.py b/h5pyd/_hl/group.py index 831b377..9cc6bcf 100644 --- a/h5pyd/_hl/group.py +++ b/h5pyd/_hl/group.py @@ -58,6 +58,7 @@ def __init__(self, bind, **kwargs): if not isinstance(bind, GroupID): raise ValueError("%s is not a GroupID" % bind) HLObject.__init__(self, bind, **kwargs) + self._track_order = kwargs['track_order'] if 'track_order' in kwargs else False self._req_prefix = "/groups/" + self.id.uuid self._link_db = {} # cache for links diff --git a/h5pyd/_hl/httpconn.py b/h5pyd/_hl/httpconn.py index cb161ba..f1cc517 100644 --- a/h5pyd/_hl/httpconn.py +++ b/h5pyd/_hl/httpconn.py @@ -163,6 +163,7 @@ def __init__( mode="a", use_session=True, use_cache=True, + track_order=False, logger=None, retries=3, timeout=DEFAULT_TIMEOUT, @@ -179,6 +180,7 @@ def __init__( self._api_key = api_key self._s = None # Sessions self._server_info = None + self._track_order = track_order if use_cache: self._cache = {} self._objdb = {} @@ -427,6 +429,8 @@ def GET(self, req, format="json", params=None, headers=None, use_cache=True): if params is None: params = {} + if self._track_order: + params["CreateOrder"] = "1" if "domain" not in params: params["domain"] = self._domain if "bucket" not in params and self._bucket: diff --git a/test/hl/test_file.py b/test/hl/test_file.py index ef2c6df..c76d915 100644 --- a/test/hl/test_file.py +++ b/test/hl/test_file.py @@ -50,6 +50,7 @@ def test_serverinfo(self): self.assertTrue(node_count >= 1) self.assertTrue("isadmin" in info) + """ def test_create(self): filename = self.getFileName("new_file") print("filename:", filename) @@ -204,6 +205,7 @@ def test_create(self): f.close() self.assertEqual(f.id.id, 0) + """ def test_open_notfound(self): # verify open of non-existent file throws exception @@ -346,6 +348,32 @@ def test_close(self): f.close() self.assertFalse(f) + def test_link_creation_order(self): + filename = self.getFileName("track_order") + f = h5py.File(filename, 'w', track_order=True) + + f.create_dataset('dset', data=[1, 2, 3]) + + # create links in group g2 + f['A'] = h5py.SoftLink('/group') + f['C'] = h5py.SoftLink('/dset') + f['B'] = f['dset'] + + expected_sequence = ["dset", "A", "C", "B"] + + for i, item in enumerate(f): + self.assertEqual(item, expected_sequence[i]) + + # test for links within a subgroup + g = f.create_group('group') + g['Z'] = h5py.SoftLink('/dset') + g['X'] = h5py.SoftLink('/group') + g['Y'] = f['dset'] + + expected_sequence = ["Z", "X", "Y"] + for i, item in enumerate(g): + self.assertEqual(item, expected_sequence[i]) + if __name__ == '__main__': loglevel = logging.ERROR