[h5py] 134/455: Various fixes and additions; H5A improvements for 1.8
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:25 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag 1.3.0
in repository h5py.
commit 24dcdb12fdb00044e20f7132341116376a78824d
Author: andrewcollette <andrew.collette at gmail.com>
Date: Sat Oct 11 03:42:08 2008 +0000
Various fixes and additions; H5A improvements for 1.8
---
h5py/defs.pxd | 32 ++++-
h5py/h5a.pyx | 342 ++++++++++++++++++++++++++++++++-----------------
h5py/h5g.pyx | 95 +++++++-------
h5py/highlevel.py | 174 ++++++++++++++++---------
h5py/tests/test_h5a.py | 28 ++--
h5py/utils.pxd | 4 +-
h5py/utils.pyx | 14 +-
setup.py | 7 +-
8 files changed, 429 insertions(+), 267 deletions(-)
diff --git a/h5py/defs.pxd b/h5py/defs.pxd
index 2fdf6ab..c57b5ff 100644
--- a/h5py/defs.pxd
+++ b/h5py/defs.pxd
@@ -392,8 +392,8 @@ cdef extern from "hdf5.h":
int H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name, size_t size ) except *
int H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx ) except *
- ctypedef herr_t (*H5G_iterate_t)(hid_t group, char *name, op_data) except -1
- herr_t H5Giterate(hid_t loc_id, char *name, int *idx, H5G_iterate_t operator, operator_data ) except *
+ ctypedef herr_t (*H5G_iterate_t)(hid_t group, char *name, void* op_data) except 2
+ herr_t H5Giterate(hid_t loc_id, char *name, int *idx, H5G_iterate_t operator, void* data) except *
herr_t H5Gget_objinfo(hid_t loc_id, char* name, int follow_link, H5G_stat_t *statbuf) except *
herr_t H5Gget_linkval(hid_t loc_id, char *name, size_t size, char *value) except *
@@ -1214,8 +1214,8 @@ cdef extern from "hdf5.h":
hid_t H5Aget_space(hid_t attr_id) except *
hid_t H5Aget_type(hid_t attr_id) except *
- ctypedef herr_t (*H5A_operator_t)(hid_t loc_id, char *attr_name, operator_data) except -1
- herr_t H5Aiterate(hid_t loc_id, unsigned * idx, H5A_operator_t op, op_data) except *
+ ctypedef herr_t (*H5A_operator_t)(hid_t loc_id, char *attr_name, void* operator_data) except 2
+ herr_t H5Aiterate(hid_t loc_id, unsigned * idx, H5A_operator_t op, void* op_data) except *
IF H5PY_18API:
@@ -1225,11 +1225,29 @@ cdef extern from "hdf5.h":
H5T_cset_t cset # Character set of attribute name
hsize_t data_size # Size of raw data
- herr_t H5Aopen(hid_t obj_id, char *attr_name, hid_t aapl_id)
+ hid_t H5Acreate_by_name(hid_t loc_id, char *obj_name, char *attr_name,
+ hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id) except *
+
+ herr_t H5Aopen(hid_t obj_id, char *attr_name, hid_t aapl_id) except *
herr_t H5Aopen_by_name( hid_t loc_id, char *obj_name, char *attr_name,
- hid_t aapl_id, hid_t lapl_id)
+ hid_t aapl_id, hid_t lapl_id) except *
herr_t H5Aopen_by_idx(hid_t loc_id, char *obj_name, H5_index_t idx_type,
- H5_iter_order_t order, hsize_t n, hid_t aapl_id, hid_t lapl_id)
+ H5_iter_order_t order, hsize_t n, hid_t aapl_id, hid_t lapl_id) except *
+ htri_t H5Aexists_by_name( hid_t loc_id, char *obj_name, char *attr_name,
+ hid_t lapl_id) except *
+ htri_t H5Aexists(hid_t obj_id, char *attr_name) except *
+
+ herr_t H5Arename(hid_t loc_id, char *old_attr_name, char *new_attr_name) except *
+ herr_t H5Arename_by_name(hid_t loc_id, char *obj_name, char *old_attr_name,
+ char *new_attr_name, hid_t lapl_id) except *
+
+ herr_t H5Aget_info( hid_t attr_id, H5A_info_t *ainfo) except *
+ herr_t H5Aget_info_by_name(hid_t loc_id, char *obj_name, char *attr_name,
+ H5A_info_t *ainfo, hid_t lapl_id) except *
+ herr_t H5Aget_info_by_idx(hid_t loc_id, char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, hsize_t n, H5A_info_t *ainfo, hid_t lapl_id) except *
+
+
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index 518ac48..a578787 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -32,157 +32,264 @@ import_array()
# === General attribute operations ============================================
- at sync
-def create(ObjectID loc not None, char* name, TypeID tid not None,
- SpaceID space not None):
- """ (ObjectID loc, STRING name, TypeID tid, SpaceID space)
- => AttrID
+# --- create, create_by_name ---
+
+IF H5PY_18API:
+ @sync
+ def create(ObjectID loc not None, char* name, TypeID tid not None,
+ SpaceID space not None, *, char* obj_name='.', PropID lapl=None):
+ """(ObjectID loc, STRING name, TypeID tid, SpaceID space, **kwds) => AttrID
+
+ Create a new attribute, attached to an existing object.
+
+ Keywords:
+ * STRING obj_name (".") Attach attribute to this group member
+ * PropID lapl (None) Determines how obj_name is interpreted
+ """
+
+ return AttrID(H5Acreate_by_name(loc.id, obj_name, name, tid.id,
+ space.id, H5P_DEFAULT, H5P_DEFAULT, pdefault(lapl)))
+
+ELSE:
+ @sync
+ def create(ObjectID loc not None, char* name, TypeID tid not None,
+ SpaceID space not None):
+ """(ObjectID loc, STRING name, TypeID tid, SpaceID space) => AttrID
Create a new attribute attached to a parent object, specifiying an
HDF5 datatype and dataspace.
- """
- return AttrID(H5Acreate(loc.id, name, tid.id, space.id, H5P_DEFAULT))
+ """
+ return AttrID(H5Acreate(loc.id, name, tid.id, space.id, H5P_DEFAULT))
+
+
+# --- open, open_by_name, open_by_idx ---
IF H5PY_18API:
@sync
- def open(ObjectID loc not None, char* name=NULL, int idx=-1, *,
- char* obj_name='.', int idx_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
+ def open(ObjectID loc not None, char* name=NULL, int index=-1, *,
+ char* obj_name='.', int index_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
PropID lapl=None):
- """
- (ObjectID loc, STRING name=NULL, INT order=-1, **kwds)
- => AttrID
+ """(ObjectID loc, STRING name=, INT index=, **kwds) => AttrID
- Open an attribute attached to an existing object. You must specify
- exactly one of either name or idx.
-
- Keyword-only arguments:
- * STRING obj_name (NULL): Attribute is attached to this group member
- * PropID lapl (None): Controls how "obj_name" is interpreted
- * INT idx_type (h5.INDEX_NAME) Controls how idx is interpreted
- * INT order (h5.ITER_NATIVE) Controls how idx is interpreted
+ Open an attribute attached to an existing object. You must specify
+ exactly one of either name or idx.
+
+ Keyword-only arguments:
+ * STRING obj_name ("."): Attribute is attached to this group member
+ * PropID lapl (None): Controls how "obj_name" is interpreted
+ * INT index_type (h5.INDEX_NAME) Controls how idx is interpreted
+ * INT order (h5.ITER_NATIVE) Controls how idx is interpreted
"""
- if (name == NULL and idx < 0) or (name != NULL and idx >= 0):
- raise ValueError("Exactly one of name or idx must be specified")
+ if (name == NULL and index < 0) or (name != NULL and index >= 0):
+ raise TypeError("Exactly one of name or idx must be specified")
if name != NULL:
return AttrID(H5Aopen_by_name(loc.id, obj_name, name,
H5P_DEFAULT, pdefault(lapl)))
else:
return AttrID(H5Aopen_by_idx(loc.id, obj_name,
- <H5_index_t>idx_type, <H5_iter_order_t>order, idx,
+ <H5_index_t>index_type, <H5_iter_order_t>order, index,
H5P_DEFAULT, pdefault(lapl)))
ELSE:
@sync
- def open(ObjectID loc not None, char* name=NULL, int idx=-1):
- """ (ObjectID loc, STRING name=NULL, INT idx=-1) => AttrID
+ def open(ObjectID loc not None, char* name=NULL, int index=-1):
+ """(ObjectID loc, STRING name=, INT index=) => AttrID
- Open an attribute attached to an existing object. You must specify
- exactly one of either name or idx.
+ Open an attribute attached to an existing object. You must specify
+ exactly one of either name or idx.
"""
- if (name == NULL and idx < 0) or (name != NULL and idx >= 0):
- raise ValueError("Exactly one of name or idx must be specified")
+ if (name == NULL and index < 0) or (name != NULL and index >= 0):
+ raise TypeError("Exactly one of name or idx must be specified")
if name != NULL:
return AttrID(H5Aopen_name(loc.id, name))
else:
- return AttrID(H5Aopen_idx(loc.id, idx))
+ return AttrID(H5Aopen_idx(loc.id, index))
+
+
+# --- exists, exists_by_name ---
+
+IF H5PY_18API:
+ @sync
+ def exists(ObjectID loc not None, char* name, *,
+ char* obj_name=NULL, PropID lapl=None):
+ """(ObjectID loc, STRING name, **kwds) => BOOL
+
+ Determine if an attribute is attached to this object.
+
+ Keywords:
+ * STRING obj_name: Look for attributes attached to this group member
+ * PropID lapl: Determines how "obj_name" is interpreted
+ """
+ if obj_name is NULL:
+ return <bint>H5Aexists(loc.id, name)
+ else:
+ return <bint>H5Aexists_by_name(loc.id, obj_name, name, pdefault(lapl))
+ELSE:
+ cdef herr_t cb_exist(hid_t loc_id, char* attr_name, void* ref_name) except 2:
+
+ if strcmp(attr_name, <char*>ref_name) == 0:
+ return 1
+ return 0
+
+ @sync
+ def exists(ObjectID loc not None, char* name):
+ """(ObjectID loc, STRING name) => BOOL
+
+ Determine if an attribute named "ref_name" is attached to this object.
+ """
+ cdef unsigned int i=0
+
+ return <bint>H5Aiterate(loc.id, &i, <H5A_operator_t>cb_exist, <void*>name)
+
+
+# --- rename, rename_by_name ---
+
+IF H5PY_18API:
+ @sync
+ def rename(ObjectID loc not None, char* name, char* new_name, *,
+ char* obj_name='.', PropID lapl=None):
+ """(ObjectID loc, STRING name, STRING new_name, **kwds)
+
+ Rename an attribute.
+
+ Keywords:
+ * STRING obj_name (".") Attribute is attached to this group member
+ * PropID lapl (None) Determines how obj_name is interpreted
+ """
+ H5Arename_by_name(loc.id, obj_name, name, new_name, pdefault(lapl))
@sync
def delete(ObjectID loc not None, char* name):
- """ (ObjectID loc, STRING name)
+ """(ObjectID loc, STRING name)
- Remove an attribute from an object.
+ Remove an attribute from an object.
"""
H5Adelete(loc.id, name)
@sync
def get_num_attrs(ObjectID loc not None):
- """ (ObjectID loc) => INT number_of_attributes
+ """(ObjectID loc) => INT
- Determine the number of attributes attached to an HDF5 object.
+ Determine the number of attributes attached to an HDF5 object.
"""
return H5Aget_num_attrs(loc.id)
-cdef herr_t iter_cb(hid_t loc_id, char *attr_name, object int_tpl) except -1:
- # Iteration callback. Returns 0 under normal execution, +1 to stop early
- # if StopIteration is raised, and -1 if any other exception occurrs.
- loc, func, data = int_tpl
+cdef class _AttrVisitor:
- try:
- func(loc, attr_name, data)
- except StopIteration:
- return 1
+ cdef object func
+ cdef object retval
+
+ def __init__(self, func):
+ self.func = func
+ self.retval = None
+cdef herr_t cb_attr_iter(hid_t loc_id, char* attr_name, void* vis_in) except 2:
+
+ cdef _AttrVisitor vis = <_AttrVisitor>vis_in
+
+ vis.retval = vis.func(attr_name)
+
+ if vis.retval is not None:
+ return 1
return 0
@sync
-def iterate(ObjectID loc not None, object func, object data=None, int startidx=0):
- """ (ObjectID loc, FUNCTION func, OBJECT data=None, UINT startidx=0)
- => INT last_attribute_index
-
- Iterate an arbitrary Python function over the attributes attached
- to an object. You can also start at an arbitrary attribute by
- specifying its (zero-based) index.
-
- Your function:
- 1. Should accept three arguments: the ObjectID for the parent object,
- the (STRING) name of the attribute, and an arbitrary Python object
- you provide as data. Any return value is ignored.
- 2. Raise StopIteration to bail out before all attributes are processed.
- 3. Raising anything else immediately aborts iteration, and the
- exception is propagated.
+def iterate(ObjectID loc not None, object func, int index=0):
+ """(ObjectID loc, CALLABLE func, INT index=0) => <Return value from func>
+
+ Iterate a callable (function, method or callable object) over the
+ attributes attached to this object. You callable should have the
+ signature:
+
+ func(STRING name, *args) => Result
+
+ Returning None continues iteration; returning anything else aborts
+ iteration and returns that value.
+
+ The parameter *args will make your code forward-compatible with the
+ 1.8.X version of this function, which supplies additional arguments
+ to the callback.
"""
- cdef unsigned int i
- if startidx < 0:
+ if index < 0:
raise ValueError("Starting index must be a non-negative integer.")
- i = startidx
- int_tpl = (loc, func, data)
+ cdef unsigned int i = index
+ cdef _AttrVisitor vis = _AttrVisitor(func)
- H5Aiterate(loc.id, &i, <H5A_operator_t>iter_cb, int_tpl)
+ H5Aiterate(loc.id, &i, <H5A_operator_t>cb_attr_iter, <void*>vis)
-cdef herr_t list_cb(hid_t loc_id, char *attr_name, object listin):
-
- cdef list thelist
- thelist = listin
+ return vis.retval
- thelist.append(attr_name)
- return 0
@sync
def py_listattrs(ObjectID loc not None):
- """ (ObjectID loc) => LIST
+ """(ObjectID loc) => LIST
- Get a list of the names of the attributes attached to an object.
+ Get a list of the names of the attributes attached to an object.
"""
- cdef list retlist
- cdef unsigned int i
- i = 0
retlist = []
- H5Aiterate(loc.id, &i, <H5A_operator_t>list_cb, retlist)
+ iterate(loc, retlist.append)
return retlist
-cdef herr_t cb_exist(hid_t loc_id, char* attr_name, object ref_name):
- if ref_name == attr_name:
- return 1
- return 0
- at sync
-def py_exists(ObjectID loc not None, object ref_name):
- """ (ObjectID loc, STRING ref_name) => BOOL
- Determine if an attribute named "ref_name" is attached to this object.
- """
- cdef unsigned int i
- cdef herr_t retval
- i=0
-
- retval = H5Aiterate(loc.id, &i, <H5A_operator_t>cb_exist, ref_name)
-
- return <bint>retval
-
+IF H5PY_18API:
+ cdef class AttrInfo:
+
+ cdef H5A_info_t info
+
+ property corder_valid:
+ """Indicates if the creation order is valid"""
+ def __get__(self):
+ return <bint>self.info.corder_valid
+ property corder:
+ """Creation order"""
+ def __get__(self):
+ return <int>self.info.corder
+ property cset:
+ """Character set of attribute name (integer typecode from h5t)"""
+ def __get__(self):
+ return <int>self.info.cset
+ property data_size:
+ """Size of raw data"""
+ def __get__(self):
+ return self.info.data_size
+
+ @sync
+ def get_info(ObjectID loc not None, char* name=NULL, int index=-1, *,
+ char* obj_name='.', PropID lapl=None,
+ int index_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE):
+ """(ObjectID loc, STRING name=, INT index=, **kwds) => AttrInfo
+
+ Get information about an attribute, in one of two ways:
+
+ 1. If you have the attribute identifier, just pass it in
+ 2. If you have the parent object, supply it and exactly one of
+ either name or index.
+
+ Keywords:
+ * STRING obj_name (".") Use this group member instead
+ * PropID lapl (None) How "obj_name" is resolved
+ * INT index_type (h5.INDEX_NAME) Which index to use
+ * INT order (h5.ITER_NATIVE) What order the index is in
+ """
+ cdef AttrInfo info = AttrInfo()
+
+ if name == NULL and index < 0:
+ H5Aget_info(loc.id, &info.info)
+ elif name != NULL and index >= 0:
+ raise TypeError("At most one of name and index may be specified")
+ elif name != NULL:
+ H5Aget_info_by_name(loc.id, obj_name, name, &info.info, pdefault(lapl))
+ elif index >= 0:
+ H5Aget_info_by_idx(loc.id, obj_name, <H5_index_t>index_type,
+ <H5_iter_order_t>order, index, &info.info, pdefault(lapl))
+
+ return info
+
# === Attribute class & methods ===============================================
cdef class AttrID(ObjectID):
@@ -205,14 +312,12 @@ cdef class AttrID(ObjectID):
Equality: Identifier comparison
"""
property name:
- """ The attribute's name
- """
+ """The attribute's name"""
def __get__(self):
return self.get_name()
property shape:
- """ A Numpy-style shape tuple representing the attribute's dataspace.
- """
+ """A Numpy-style shape tuple representing the attribute's dataspace"""
def __get__(self):
cdef SpaceID space
@@ -220,8 +325,7 @@ cdef class AttrID(ObjectID):
return space.get_simple_extent_dims()
property dtype:
- """ A Numpy-stype dtype object representing the attribute's datatype
- """
+ """A Numpy-stype dtype object representing the attribute's datatype"""
def __get__(self):
cdef TypeID tid
@@ -230,24 +334,24 @@ cdef class AttrID(ObjectID):
@sync
def _close(self):
- """ ()
+ """()
- Close this attribute and release resources. You don't need to
- call this manually; attributes are automatically destroyed when
- their Python wrappers are freed.
+ Close this attribute and release resources. You don't need to
+ call this manually; attributes are automatically destroyed when
+ their Python wrappers are freed.
"""
H5Aclose(self.id)
@sync
def read(self, ndarray arr_obj not None):
- """ (NDARRAY arr_obj)
+ """(NDARRAY arr_obj)
- Read the attribute data into the given Numpy array. Note that the
- Numpy array must have the same shape as the HDF5 attribute, and a
- conversion-compatible datatype.
+ Read the attribute data into the given Numpy array. Note that the
+ Numpy array must have the same shape as the HDF5 attribute, and a
+ conversion-compatible datatype.
- The Numpy array must be writable, C-contiguous and own its data.
- If this is not the case, an ValueError is raised and the read fails.
+ The Numpy array must be writable, C-contiguous and own its data.
+ If this is not the case, an ValueError is raised and the read fails.
"""
cdef TypeID mtype
cdef hid_t space_id
@@ -267,14 +371,14 @@ cdef class AttrID(ObjectID):
@sync
def write(self, ndarray arr_obj not None):
- """ (NDARRAY arr_obj)
+ """(NDARRAY arr_obj)
- Write the contents of a Numpy array too the attribute. Note that
- the Numpy array must have the same shape as the HDF5 attribute, and
- a conversion-compatible datatype.
+ Write the contents of a Numpy array too the attribute. Note that
+ the Numpy array must have the same shape as the HDF5 attribute, and
+ a conversion-compatible datatype.
- The Numpy array must be C-contiguous and own its data. If this is
- not the case, ValueError will be raised and the write will fail.
+ The Numpy array must be C-contiguous and own its data. If this is
+ not the case, ValueError will be raised and the write will fail.
"""
cdef TypeID mtype
cdef hid_t space_id
@@ -293,9 +397,9 @@ cdef class AttrID(ObjectID):
@sync
def get_name(self):
- """ () => STRING name
+ """() => STRING name
- Determine the name of an attribute, given its identifier.
+ Determine the name of an attribute, given its identifier.
"""
cdef int blen
cdef char* buf
@@ -314,17 +418,17 @@ cdef class AttrID(ObjectID):
@sync
def get_space(self):
- """ () => INT space_id
+ """() => SpaceID
- Create and return a copy of the attribute's dataspace.
+ Create and return a copy of the attribute's dataspace.
"""
return SpaceID(H5Aget_space(self.id))
@sync
def get_type(self):
- """ () => TypeID
+ """() => TypeID
- Create and return a copy of the attribute's datatype.
+ Create and return a copy of the attribute's datatype.
"""
return typewrap(H5Aget_type(self.id))
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 8d41d98..4535417 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -112,8 +112,7 @@ cdef class GroupIter:
def __next__(self):
if self.idx == self.nobjs:
- if self.grp is not None:
- self.grp = None
+ self.grp = None
raise StopIteration
retval = self.grp.get_objname_by_idx(self.idx)
@@ -122,7 +121,6 @@ cdef class GroupIter:
# === Basic group management ==================================================
-# COMPAT: 1.8 update
IF H5PY_18API:
@sync
def open(ObjectID loc not None, char* name, PropID gapl=None):
@@ -140,7 +138,7 @@ ELSE:
"""
return GroupID(H5Gopen(loc.id, name))
-# COMPAT: 1.8 update
+
IF H5PY_18API:
@sync
def create(ObjectID loc not None, char* name, PropID lcpl=None,
@@ -162,59 +160,51 @@ ELSE:
"""
return GroupID(H5Gcreate(loc.id, name, -1))
-cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl) except -1:
- # Callback function for H5Giterate
- # Automatic exception propagation breaks in 1.8 for some reason, so
- # stuff the exception into a mutable object.
+cdef class _GroupVisitor:
- cdef list err_list
- loc, func, data, err_list = int_tpl
+ cdef object func
+ cdef object retval
- try:
- func(loc, name, data)
- except StopIteration:
- return 1
- except Exception, e:
- err_list.append(e)
- return 1
+ def __init__(self, func):
+ self.func = func
+ self.retval = None
+
+cdef herr_t cb_group_iter(hid_t gid, char *name, void* vis_in) except 2:
+ cdef _GroupVisitor vis = <_GroupVisitor>vis_in
+
+ vis.retval = vis.func(name)
+
+ if vis.retval is not None:
+ return 1
return 0
@sync
-def iterate(GroupID loc not None, char* name, object func, object data=None,
- int startidx=0):
- """ (GroupID loc, STRING name, FUNCTION func, OBJECT data=None,
- UINT startidx=0) => INT last_index_processed
-
- Iterate an arbitrary Python function over a group. Note that the
- group is specified by a parent and a name; if you have a group
- identifier and want to iterate over it; pass in "." for the name.
- You can also start at an arbitrary member by specifying its
- (zero-based) index.
-
- Your function:
- 1. Should accept three arguments: the GroupID of the group, the
- (STRING) name of the member, and an arbitary Python object you
- provide as data. Any return value is ignored.
- 2. Raise StopIteration to bail out before all members are processed.
- 3. Raising anything else immediately aborts iteration, and the
- exception is propagated.
- """
- cdef int i
- cdef list err_list
- err_list = []
+def iterate(GroupID loc not None, object func, int startidx=0, *,
+ char* obj_name='.'):
+ """ (GroupID loc, CALLABLE func, UINT startidx=0, **kwds)
+ => Return value from func
- if startidx < 0:
- raise ValueError("Starting index must be non-negative.")
- i = startidx
+ Iterate a callable (function, method or callable object) over the
+ members of a group. Your callable should have the signature:
+
+ func(STRING name) => Result
- int_tpl = (loc, func, data, err_list)
+ Returning None continues iteration; returning anything else aborts
+ iteration and returns that value.
+
+ Keywords:
+ * STRING obj_name (".") Iterate over this subgroup instead
+ """
+ if startidx < 0:
+ raise ValueError("Starting index must be non-negative")
- H5Giterate(loc.id, name, &i, <H5G_iterate_t>iter_cb_helper, int_tpl)
+ cdef int i = startidx
+ cdef _GroupVisitor vis = _GroupVisitor(func)
- if len(err_list) > 0:
- raise err_list[0]
+ H5Giterate(loc.id, obj_name, &i, <H5G_iterate_t>cb_group_iter, <void*>vis)
+ return vis.retval
@sync
def get_objinfo(ObjectID obj not None, object name='.', int follow_link=1):
@@ -451,11 +441,14 @@ cdef class GroupID(ObjectID):
Determine if a group member of the given name is present
"""
- try:
- H5Gget_objinfo(self.id, name, 1, NULL)
- return True
- except H5Error:
- return False
+ IF H5PY_18API:
+ return <bint>H5Lexists(self.id, name, H5P_DEFAULT)
+ ELSE:
+ try:
+ H5Gget_objinfo(self.id, name, 1, NULL)
+ return True
+ except H5Error:
+ return False
@nosync
def __iter__(self):
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index 907e8e9..d7a1645 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -73,6 +73,7 @@ try:
except ImportError:
readline = None
+
class LockableObject(object):
"""
@@ -81,6 +82,7 @@ class LockableObject(object):
_lock = h5.get_phil()
+
class HLObject(LockableObject):
"""
@@ -98,12 +100,10 @@ class HLObject(LockableObject):
attrs = property(lambda self: self._attrs,
doc = "Provides access to HDF5 attributes. See AttributeManager.")
- def __repr__(self):
- return str(self)
-
def __nonzero__(self):
return self.id.__nonzero__()
+
class Group(HLObject):
""" Represents an HDF5 group.
@@ -127,9 +127,6 @@ class Group(HLObject):
the AttributeManager class.
"""
- names = property(lambda self: tuple(self),
- doc = "Tuple of group member names")
-
def __init__(self, parent_object, name, create=False):
""" Create a new Group object, from a parent object and a name.
@@ -183,9 +180,7 @@ class Group(HLObject):
htype.commit(self.id, name)
else:
- if not isinstance(obj, numpy.ndarray):
- obj = numpy.array(obj)
- Dataset(self, name, data=obj)
+ self.create_dataset(name, data=obj)
def __getitem__(self, name):
""" Open an object attached to this group.
@@ -222,12 +217,6 @@ class Group(HLObject):
""" Iterate over member names """
return self.id.__iter__()
- def iteritems(self):
- """ Iterate over the group members as (name, value) pairs """
- with self._lock:
- for name in self:
- yield (name, self[name])
-
def create_group(self, name):
""" Create and return a subgroup.
@@ -279,20 +268,60 @@ class Group(HLObject):
outstr += '\nComment:\n'+cmnt
return outstr
+ # Dictionary compatibility methods
+
+ def listnames(self):
+ """ Get a list containing member names """
+ with self._lock:
+ return list(self)
+
+ def iternames(self):
+ """ Get an iterator over member names """
+ with self._lock:
+ return iter(self)
+
+ def listobjects(self):
+ """ Get a list containing member objects """
+ with self._lock:
+ return [self[x] for x in self]
+
+ def iterobjects(self):
+ """ Get an iterator over member objects """
+ with self._lock:
+ for x in self:
+ yield self[x]
+
+ def listitems(self):
+ """ Get a list of tuples containing (name, object) pairs """
+ with self._lock:
+ return [(x, self[x]) for x in self]
+
+ def iteritems(self):
+ """ Get an iterator over (name, object) pairs """
+ with self._lock:
+ for x in self:
+ yield (x, self[x])
+
+ # New 1.8.X methods
+
def visit(self, func):
- """ Recursively iterate a function or callable object over the file,
- calling it exactly once for each object with the signature:
+ """ Recursively visit all names in this group and subgroups.
+
+ You supply a callable (function, method or callable object); it
+ will be called exactly once for each link in this group and every
+ group below it. Your callable must conform to the signature:
- func(<name>) => <None or return value>
+ func(<member name>) => <None or return value>
Returning None continues iteration, returning anything else stops
- and immediately returns that value from Group.visit.
+ and immediately returns that value from the visit method.
Example:
# List the entire contents of the file
+ >>> f = File("foo.hdf5")
>>> list_of_names = []
- >>> grp.visit(list_of_names.append)
+ >>> f.visit(list_of_names.append)
Only available with HDF5 1.8.X.
"""
@@ -306,14 +335,28 @@ class Group(HLObject):
return h5o.visit(self.id, call_proxy)
def visititems(self, func):
- """ Recursively iterate a function or callable object over the file,
- calling it exactly once for each object, with the signature::
-
- func(<name>, <object instance>) => <None or return value>
+ """ Recursively visit names and objects in this group and subgroups.
+
+ You supply a callable (function, method or callable object); it
+ will be called exactly once for each link in this group and every
+ group below it. Your callable must conform to the signature:
+
+ func(<member name>, <object>) => <None or return value>
Returning None continues iteration, returning anything else stops
- and immediately returns that value from Group.visit.
+ and immediately returns that value from the visit method.
+
+ Example:
+ # Get a list of all datasets in the file
+ >>> mylist = []
+ >>> def func(name, obj):
+ ... if isinstance(obj, Dataset):
+ ... mylist.append(name)
+ ...
+ >>> f = File('foo.hdf5')
+ >>> f.visititems(func)
+
Only available with HDF5 1.8.X.
"""
if not config.API_18:
@@ -325,8 +368,7 @@ class Group(HLObject):
return h5o.visit(self.id, call_proxy)
-
- def __str__(self):
+ def __repr__(self):
with self._lock:
try:
return 'Group "%s" (%d members)' % (hbasename(self.name), len(self))
@@ -425,10 +467,10 @@ class File(Group):
if self.id._valid:
self.close()
- def __str__(self):
+ def __repr__(self):
with self._lock:
try:
- return 'File "%s", root members: %s' % (self.name, ', '.join(['"%s"' % name for name in self]))
+ return 'File "%s", %d root members' % (self.name, len(self))
except:
return "Invalid file"
@@ -545,19 +587,28 @@ class Dataset(HLObject):
raise ValueError('You cannot specify keywords when opening a dataset.')
self.id = h5d.open(group.id, name)
else:
- if ((data is None) and (shape is None)) or \
- ((data is not None) and (shape is not None)):
- raise ValueError("*Either* data *or* the shape must be specified.")
-
+ # Convert data to a C-contiguous ndarray
if data is not None:
+ data = numpy.asarray(data, order="C")
+
+ # Validate shape
+ if shape is None and data is None:
+ raise ValueError("Either data or shape must be specified")
+ elif shape is None and data is not None:
shape = data.shape
+ elif shape is not None and data is not None:
+ if numpy.product(shape) != numpy.product(data.shape):
+ raise ValueError("Shape tuple is incompatible with data")
+
+ # Validate dtype
+ if dtype is None and data is None:
+ dtype = numpy.dtype("=f4")
+ elif dtype is None and data is not None:
dtype = data.dtype
else:
- if dtype is None:
- dtype = "=f4"
-
- dtype = numpy.dtype(dtype)
+ dtype = numpy.dtype(dtype)
+ # Generate chunks if necessary
if chunks is True or \
(any((compression, shuffle, fletcher32, maxshape)) and chunks is None):
chunks = guess_chunk(shape, dtype.itemsize)
@@ -571,7 +622,7 @@ class Dataset(HLObject):
if shuffle:
plist.set_shuffle()
if compression is not None:
- if compression is True: # prevent accidental abuse
+ if compression is True:
compression = 6
plist.set_deflate(compression)
if fletcher32:
@@ -602,12 +653,16 @@ class Dataset(HLObject):
def __len__(self):
""" The size of the first axis. TypeError if scalar.
"""
+ size = self.len()
+ if size > sys.maxint:
+ raise OverflowError("Value too big for Python's __len__; use Dataset.len() instead.")
+ return size
+
+ def len(self):
+ """ The size of the first axis. TypeError if scalar. """
shape = self.shape
if len(shape) == 0:
raise TypeError("Attempt to take len() of scalar dataset")
- size = shape[0]
- if size > sys.maxint:
- raise OverflowError("Dataset length is larger than Python's len() function can handle")
return shape[0]
def __iter__(self):
@@ -663,7 +718,7 @@ class Dataset(HLObject):
new_dtype = numpy.dtype([(name, basetype.fields[name][0]) for name in names])
# Create the holder array
- arr = numpy.ndarray(mspace.shape, new_dtype)
+ arr = numpy.ndarray(mspace.shape, new_dtype, order='C')
# Perform the actual read
self.id.read(mspace, fspace, arr)
@@ -692,7 +747,7 @@ class Dataset(HLObject):
if len(names) != 0:
raise NotImplementedError("Field name selections are not yet allowed for write.")
- val = numpy.array(val) # So that you can assign scalars, sequences
+ val = numpy.asarray(val, order='C')
fspace = self.id.get_space()
@@ -705,11 +760,11 @@ class Dataset(HLObject):
self.id.write(mspace, fspace, val)
- def __str__(self):
+ def __repr__(self):
with self._lock:
try:
- return 'Dataset "%s": %s %s' % (hbasename(self.name),
- str(self.shape), repr(self.dtype))
+ return 'Dataset "%s": %s %s' % \
+ (hbasename(self.name), self.shape, self.dtype.str)
except:
return "Invalid dataset"
@@ -752,9 +807,9 @@ class AttributeManager(LockableObject):
as a Numpy ndarray.
"""
with self._lock:
- attr = h5a.open_name(self.id, name)
+ attr = h5a.open(self.id, name)
- arr = numpy.ndarray(attr.shape, dtype=attr.dtype)
+ arr = numpy.ndarray(attr.shape, dtype=attr.dtype, order='C')
attr.read(arr)
if len(arr.shape) == 0:
@@ -770,8 +825,7 @@ class AttributeManager(LockableObject):
If the creation fails, the data is not recoverable.
"""
with self._lock:
- if not isinstance(value, numpy.ndarray):
- value = numpy.array(value)
+ value = numpy.asarray(value, order='C')
space = h5s.create_simple(value.shape)
htype = h5t.py_create(value.dtype)
@@ -789,9 +843,9 @@ class AttributeManager(LockableObject):
def __len__(self):
""" Number of attributes attached to the object. """
+ # I expect we will not have more than 2**32 attributes
return h5a.get_num_attrs(self.id)
-
def __iter__(self):
""" Iterate over the names of attributes. """
with self._lock:
@@ -806,22 +860,16 @@ class AttributeManager(LockableObject):
def __contains__(self, name):
""" Determine if an attribute exists, by name. """
- return h5a.py_exists(self.id, name)
+ return h5a.exists(self.id, name)
- def __str__(self):
+ def __repr__(self):
with self._lock:
try:
- rstr = 'Attributes of "%s": ' % hbasename(h5i.get_name(self.id))
- if len(self) == 0:
- rstr += '(none)'
- else:
- rstr += ', '.join(['"%s"' % x for x in self])
- return rstr
+ return 'Attributes of "%s" (%d)' % \
+ (hbasename(h5i.get_name(self.id)), len(self))
except:
return "Invalid attributes object"
- def __repr__(self):
- return str(self)
class Datatype(HLObject):
@@ -850,10 +898,10 @@ class Datatype(HLObject):
self.id = h5t.open(grp.id, name)
self._attrs = AttributeManager(self)
- def __str__(self):
+ def __repr__(self):
with self._lock:
try:
- return "Named datatype object (%s)" % str(self.dtype)
+ return "Named datatype object (%s)" % self.dtype.str
except:
return "Invalid datatype object"
diff --git a/h5py/tests/test_h5a.py b/h5py/tests/test_h5a.py
index fe0ead4..9ea330c 100644
--- a/h5py/tests/test_h5a.py
+++ b/h5py/tests/test_h5a.py
@@ -60,7 +60,7 @@ class TestH5A(TestBase):
attr.write(arr_ref)
self.assertRaises(TypeError, attr.write, arr_fail)
- attr = h5a.open_name(obj, name)
+ attr = h5a.open(obj, name)
dt = attr.dtype
shape = attr.shape
arr_val = ndarray(shape, dtype=dt)
@@ -69,16 +69,16 @@ class TestH5A(TestBase):
def test_open_idx(self):
for idx, name in enumerate(ATTRIBUTES_ORDER):
- attr = h5a.open_idx(self.obj, idx)
+ attr = h5a.open(self.obj, idx=idx)
self.assert_(self.is_attr(attr), "Open: index %d" % idx)
- def test_open_name(self):
+ def test_open(self):
for name in ATTRIBUTES:
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
self.assert_(self.is_attr(attr), 'Open: name "%s"' % name)
def test_close(self):
- attr = h5a.open_idx(self.obj, 0)
+ attr = h5a.open(self.obj, idx=0)
self.assert_(self.is_attr(attr))
attr._close()
self.assert_(not self.is_attr(attr))
@@ -87,12 +87,12 @@ class TestH5A(TestBase):
obj = h5g.open(self.fid, OBJECTNAME)
- attr = h5a.open_name(obj, ATTRIBUTES_ORDER[0])
+ attr = h5a.open(obj, ATTRIBUTES_ORDER[0])
self.assert_(self.is_attr(attr))
del attr
h5a.delete(obj, ATTRIBUTES_ORDER[0])
- self.assertRaises(H5Error, h5a.open_name, obj, ATTRIBUTES_ORDER[0])
+ self.assertRaises(H5Error, h5a.open, obj, ATTRIBUTES_ORDER[0])
# === Attribute I/O =======================================================
@@ -101,7 +101,7 @@ class TestH5A(TestBase):
for name in ATTRIBUTES:
value, dt, shape = ATTRIBUTES[name]
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
arr_holder = ndarray(shape, dtype=dt)
arr_reference = array(value, dtype=dt)
@@ -122,13 +122,13 @@ class TestH5A(TestBase):
def test_get_name(self):
for name in ATTRIBUTES:
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
self.assertEqual(attr.get_name(), name)
def test_get_space(self):
for name, (value, dt, shape) in ATTRIBUTES.iteritems():
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
space = attr.get_space()
shape_tpl = space.get_simple_extent_dims()
self.assertEqual(shape_tpl, shape)
@@ -136,7 +136,7 @@ class TestH5A(TestBase):
def test_get_type(self):
for name, (value, dt, shape) in ATTRIBUTES.iteritems():
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
htype = attr.get_type()
def test_iterate(self):
@@ -173,19 +173,19 @@ class TestH5A(TestBase):
def test_prop_name(self):
for name in ATTRIBUTES:
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
self.assertEqual(attr.name, name)
def test_prop_shape(self):
for name, (val, dt, shape) in ATTRIBUTES.iteritems():
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
self.assertEqual(attr.shape, shape)
def test_prop_dtype(self):
for name, (val, dt, shape) in ATTRIBUTES.iteritems():
- attr = h5a.open_name(self.obj, name)
+ attr = h5a.open(self.obj, name)
self.assertEqual(attr.dtype, dt)
def test_py_listattrs(self):
diff --git a/h5py/utils.pxd b/h5py/utils.pxd
index 4e0dbc0..3e3434a 100644
--- a/h5py/utils.pxd
+++ b/h5py/utils.pxd
@@ -17,8 +17,8 @@ from numpy cimport ndarray
cdef void* emalloc(size_t size) except? NULL
cdef void efree(void* ptr)
-cdef int check_numpy_read(ndarray arr, hid_t space_id=*) except -1
-cdef int check_numpy_write(ndarray arr, hid_t space_id=*) except -1
+cpdef int check_numpy_read(ndarray arr, hid_t space_id=*) except -1
+cpdef int check_numpy_write(ndarray arr, hid_t space_id=*) except -1
cdef int convert_tuple(object tuple, hsize_t *dims, hsize_t rank) except -1
cdef object convert_dims(hsize_t* dims, hsize_t rank)
diff --git a/h5py/utils.pyx b/h5py/utils.pyx
index 1643e76..515dd08 100644
--- a/h5py/utils.pyx
+++ b/h5py/utils.pyx
@@ -22,7 +22,7 @@ from numpy cimport ndarray, import_array, \
PyArray_SimpleNew, PyArray_ContiguousFromAny, \
PyArray_FROM_OTF, PyArray_DIM, \
NPY_CONTIGUOUS, NPY_NOTSWAPPED, NPY_FORCECAST, \
- NPY_C_CONTIGUOUS, NPY_OWNDATA, NPY_WRITEABLE
+ NPY_C_CONTIGUOUS, NPY_WRITEABLE
# Initialization
@@ -76,12 +76,12 @@ cdef int check_numpy(ndarray arr, hid_t space_id, int write):
# Validate array flags
if write:
- if not (arr.flags & (NPY_C_CONTIGUOUS | NPY_OWNDATA | NPY_WRITEABLE)):
- PyErr_SetString(TypeError, "Array must be writable, C-contiguous and own its data.")
+ if not (arr.flags & NPY_C_CONTIGUOUS and arr.flags & NPY_WRITEABLE):
+ PyErr_SetString(TypeError, "Array must be C-contiguous and writable")
return -1
else:
- if not (arr.flags & (NPY_C_CONTIGUOUS | NPY_OWNDATA)):
- PyErr_SetString(TypeError, "Array must be C-contiguous and own its data.")
+ if not (arr.flags & NPY_C_CONTIGUOUS):
+ PyErr_SetString(TypeError, "Array must be C-contiguous")
return -1
# Validate dataspace compatibility, if it's provided
@@ -114,10 +114,10 @@ cdef int check_numpy(ndarray arr, hid_t space_id, int write):
free(space_dims)
return 1
-cdef int check_numpy_write(ndarray arr, hid_t space_id=-1) except -1:
+cpdef int check_numpy_write(ndarray arr, hid_t space_id=-1) except -1:
return check_numpy(arr, space_id, 1)
-cdef int check_numpy_read(ndarray arr, hid_t space_id=-1) except -1:
+cpdef int check_numpy_read(ndarray arr, hid_t space_id=-1) except -1:
return check_numpy(arr, space_id, 0)
# === Conversion between HDF5 buffers and tuples ==============================
diff --git a/setup.py b/setup.py
index b78fd36..76ec000 100644
--- a/setup.py
+++ b/setup.py
@@ -153,9 +153,8 @@ class cybuild(build):
def get_hdf5_version(self):
- """ Try to determine the installed HDF5 version and return a tuple
- containing the appropriate API levels, or None if it can't be
- determined.
+ """ Try to determine the installed HDF5 version and return either
+ 16 or 18, or None if it can't be determined.
"""
if self.hdf5 is not None:
cmd = reduce(op.join, (self.hdf5, 'bin', 'h5cc'))+" -showconfig"
@@ -207,7 +206,7 @@ class cybuild(build):
warn("Can't determine HDF5 version, assuming 1.6 (use --api= to override)")
self.api = 16
else:
- # User specified the API levels
+ # User specified the API level
self._default = False
try:
self.api = int(self.api)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/h5py.git
More information about the debian-science-commits
mailing list