diff --git a/h5pyd/_hl/attrs.py b/h5pyd/_hl/attrs.py index d4d64a0..35327e0 100644 --- a/h5pyd/_hl/attrs.py +++ b/h5pyd/_hl/attrs.py @@ -352,7 +352,7 @@ def __iter__(self): req = self._req_prefix # backup over the trailing slash in req req = req[:-1] - rsp = self._parent.GET(req) + rsp = self._parent.GET(req, params={"CreateOrder": "1" if self._parent._track_order else "0"}) attributes = rsp['attributes'] attrlist = [] diff --git a/h5pyd/_hl/files.py b/h5pyd/_hl/files.py index 869c16e..d0f3afc 100644 --- a/h5pyd/_hl/files.py +++ b/h5pyd/_hl/files.py @@ -258,7 +258,6 @@ def __init__( use_session=use_session, use_cache=use_cache, logger=logger, - track_order=track_order, retries=retries, timeout=timeout, ) @@ -274,6 +273,8 @@ def __init__( params["include_attrs"] = "T" if bucket: params["bucket"] = bucket + + params["CreateOrder"] = "1" if track_order else "0" # need some special logic for the first request in local mode # to give the sockets time to initialize @@ -398,17 +399,18 @@ def __init__( self._verboseUpdated = None # when the verbose data was fetched self._lastScan = None # when summary stats where last updated by server self._dn_ids = dn_ids + self._track_order = track_order - Group.__init__(self, self._id) + Group.__init__(self, self._id, track_order=track_order) - def _getVerboseInfo(self): + def _getVerboseInfo(self): now = time.time() if ( self._verboseUpdated is None or now - self._verboseUpdated > VERBOSE_REFRESH_TIME ): # resynch the verbose data req = "/?verbose=1" - rsp_json = self.GET(req, use_cache=False) + rsp_json = self.GET(req, use_cache=False, params={"CreateOrder": "1" if self._track_order else "0"}) self.log.debug("get verbose info: {}".format(rsp_json)) props = {} diff --git a/h5pyd/_hl/group.py b/h5pyd/_hl/group.py index 9cc6bcf..d7fdf9c 100644 --- a/h5pyd/_hl/group.py +++ b/h5pyd/_hl/group.py @@ -49,7 +49,7 @@ class Group(HLObject, MutableMappingHDF5): """ Represents an HDF5 group. """ - def __init__(self, bind, **kwargs): + def __init__(self, bind, track_order=False, **kwargs): # print "group init, bind:", bind """ Create a new Group object by binding to a low-level GroupID. @@ -58,7 +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._track_order = track_order self._req_prefix = "/groups/" + self.id.uuid self._link_db = {} # cache for links @@ -150,7 +150,7 @@ def _get_link_json(self, h5path): req = "/groups/" + parent_uuid + "/links/" + name try: - rsp_json = self.GET(req) + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) except IOError: raise KeyError("Unable to open object (Component not found)") @@ -182,7 +182,7 @@ def _get_objdb_links(self): group_json = objdb[self.id.id] return group_json["links"] - def create_group(self, h5path): + def create_group(self, h5path, track_order=False): """ Create and return a new subgroup. Name may be absolute or relative. Fails if the target name already @@ -217,7 +217,7 @@ def create_group(self, h5path): req = "/groups/" + parent_uuid + "/links/" + link try: - rsp_json = self.GET(req) + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) except IOError as ioe: self.log.debug("Got ioe: {}".format(ioe)) create_group = True @@ -238,6 +238,7 @@ def create_group(self, h5path): parent_name = parent_name + '/' + link self.log.debug("create group - parent name: {}".format(parent_name)) sub_group._name = parent_name + sub_group._track_order = track_order parent_uuid = sub_group.id.id else: # sub-group already exsits @@ -259,6 +260,7 @@ def create_group(self, h5path): if sub_group is None: # didn't actually create anything raise ValueError("name already exists") + return sub_group def create_dataset(self, name, shape=None, dtype=None, data=None, **kwds): @@ -583,7 +585,7 @@ def getObjByUuid(self, uuid, collection_type=None): # will need to get JSON from server req = f"/{collection_type}/{uuid}" # make server request - obj_json = self.GET(req) + obj_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) if collection_type == 'groups': tgt = Group(GroupID(self, obj_json)) @@ -778,7 +780,7 @@ def __setitem__(self, name, obj): raise IOError("cannot create subgroup of softlink") parent_uuid = link_json["id"] req = "/groups/" + parent_uuid - group_json = self.GET(req) + group_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) tgt = Group(GroupID(self, group_json)) tgt[basename] = obj @@ -868,7 +870,7 @@ def __len__(self): return len(links_json) req = "/groups/" + self.id.uuid - rsp_json = self.GET(req) + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) return rsp_json['linkCount'] def __iter__(self): @@ -877,7 +879,7 @@ def __iter__(self): if links is None: req = "/groups/" + self.id.uuid + "/links" - rsp_json = self.GET(req) + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) links = rsp_json['links'] # reset the link cache @@ -1093,7 +1095,7 @@ def visititems(self, func): else: # request from server req = "/groups/" + parent.id.uuid + "/links" - rsp_json = self.GET(req) + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) links = rsp_json['links'] for link in links: obj = None @@ -1138,6 +1140,27 @@ def __repr__(self): r = f'' return r + def __reversed__(self): + """ Iterate over member names in reverse order """ + links = self._get_objdb_links() + + if links is None: + req = "/groups/" + self.id.uuid + "/links" + rsp_json = self.GET(req, params={"CreateOrder": "1" if self._track_order else "0"}) + links = rsp_json['links'] + + # reset the link cache + self._link_db = {} + for link in reversed(links): + name = link["title"] + self._link_db[name] = link + + for x in reversed(links): + yield x['title'] + else: + for name in links: + yield name + class HardLink(object): diff --git a/h5pyd/_hl/httpconn.py b/h5pyd/_hl/httpconn.py index 338ab51..a9bbeba 100644 --- a/h5pyd/_hl/httpconn.py +++ b/h5pyd/_hl/httpconn.py @@ -163,7 +163,6 @@ def __init__( mode="a", use_session=True, use_cache=True, - track_order=False, logger=None, retries=3, timeout=DEFAULT_TIMEOUT, @@ -180,7 +179,6 @@ 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 = {} @@ -429,8 +427,6 @@ 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 292b39e..d2b0e05 100644 --- a/test/hl/test_file.py +++ b/test/hl/test_file.py @@ -359,15 +359,15 @@ def populate(self, f): f[str(i)] = [i] def test_track_order(self): - fname = self.mktemp() - f = h5py.File(fname, 'w', track_order=True) # creation order + filename = self.getFileName("track_order_file") + f = h5py.File(filename, 'w', track_order=True) # creation order self.populate(f) self.assertEqual(list(f), [str(i) for i in range(100)]) def test_no_track_order(self): - fname = self.mktemp() - f = h5py.File(fname, 'w', track_order=False) # name alphanumeric + filename = self.getFileName("no_track_order_file") + f = h5py.File(filename, 'w', track_order=False) # name alphanumeric self.populate(f) self.assertEqual(list(f), sorted([str(i) for i in range(100)]))