[h5py] 73/455: Minor fixes
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:19 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 79874575ac733928d9ab8e79580b0a7ac1a76519
Author: andrewcollette <andrew.collette at gmail.com>
Date: Wed Jul 9 22:58:16 2008 +0000
Minor fixes
---
MANIFEST.in | 2 +-
README.txt | 4 +++
h5py/h5a.pyx | 21 ++++++++++++-
h5py/h5t.pyx | 5 +++
h5py/highlevel.py | 82 +++++++++++++++++++++++++++++++++++++-------------
h5py/tests/test_h5a.py | 4 +++
setup.py | 52 ++++++++++++++++----------------
7 files changed, 121 insertions(+), 49 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 13a5cf4..859cf56 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,7 +3,7 @@ include LICENSE.txt
include README.txt
include VERSION.txt
include docs.cfg
-recursive-include h5py *.py *.pyx *.pxd *.h *.c *.hdf5
+recursive-include h5py *.py *.pyx *.pxd *.pxi *.h *.c *.hdf5
recursive-include licenses *
recursive-include docs *
diff --git a/README.txt b/README.txt
index 623a3ca..65ff137 100644
--- a/README.txt
+++ b/README.txt
@@ -7,6 +7,10 @@ Copyright (c) 2008 Andrew Collette
Version 0.2.0
+* `Introduction`_
+* `Features`_
+* `Installation`_
+
Introduction
============
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index 2d03d75..58d1e47 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -21,7 +21,7 @@ from h5s cimport SpaceID, H5Sclose
from numpy cimport import_array, ndarray, PyArray_DATA
from utils cimport check_numpy_read, check_numpy_write, \
- emalloc, efree
+ emalloc, efree, pybool
# Runtime imports
import h5
@@ -132,6 +132,25 @@ def py_listattrs(ObjectID loc not None):
H5Aiterate(loc.id, &i, <H5A_operator_t>list_cb, retlist)
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
+
+def py_exists(ObjectID loc not None, object ref_name):
+ """ (ObjectID loc, STRING ref_name)
+
+ 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 pybool(retval)
+
# === Attribute class & methods ===============================================
cdef class AttrID(ObjectID):
diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 6bfcde3..c79b1fb 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -48,6 +48,11 @@
calls, which are presented as methods of class TypeEnumID.
Additionally, the py_create function allows you to create HDF5
enumerated types by passing in a dictionary along with a Numpy dtype.
+
+ 4. Variable-length types
+
+ VLEN types, including VLEN strings, are not currently supported.
+ This may eventually change.
"""
include "conditions.pxi"
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index f4e9da8..b44fa49 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -90,13 +90,13 @@ class Group(HLObject):
The len() of a group is the number of members, and iterating over a
group yields the names of its members, in arbitary library-defined
- order.
+ order. They also support the __contains__ syntax ("if name in group").
Subgroups and datasets can be created via the convenience functions
create_group and create_dataset, as well as by calling the appropriate
class constructor.
- Group attributes are accessed via Group.attrs; see the docstring for
+ Group attributes are accessed via group.attrs; see the docstring for
the AttributeManager class.
"""
@@ -133,6 +133,15 @@ class Group(HLObject):
Attempt to convert it to an ndarray and store it. Scalar
values are stored as scalar datasets. Raise ValueError if we
can't understand the resulting array dtype.
+
+ If a group member of the same name already exists, the assignment
+ will fail. You can check by using the Python __contains__ syntax:
+
+ if "name" in grp:
+ del grp["name"]
+ grp["name"] = <whatever>
+
+ This limitation is intentional, and may be lifted in the future.
"""
if isinstance(obj, Group) or isinstance(obj, Dataset) or isinstance(obj, Datatype):
self.id.link(name, h5i.get_name(obj.id), link_type=h5g.LINK_HARD)
@@ -170,17 +179,19 @@ class Group(HLObject):
self.id.unlink(name)
def __len__(self):
+ """ Number of members attached to this group """
return self.id.get_num_objs()
+ def __contains__(self, name):
+ """ Test if a member name exists """
+ return self.id.py_exists(name)
+
def __iter__(self):
+ """ Iterate over member names """
return self.id.py_iter()
- def __str__(self):
- if self.id._valid:
- return 'Group "%s" (%d members)' % (hbasename(self.name), len(self))
- return "Closed group"
-
def iteritems(self):
+ """ Iterate over the group members as (name, value) pairs """
for name in self:
yield (name, self[name])
@@ -224,6 +235,12 @@ class Group(HLObject):
outstr += '\nComment:\n'+cmnt
return outstr
+ def __str__(self):
+ if self.id._valid:
+ return 'Group "%s" (%d members)' % (hbasename(self.name), len(self))
+ return "Closed group"
+
+
class File(Group):
""" Represents an HDF5 file on disk.
@@ -373,7 +390,7 @@ class Dataset(HLObject):
def __init__(self, group, name,
data=None, dtype=None, shape=None,
chunks=None, compression=None, shuffle=False, fletcher32=False):
- """ Create a Dataset object. You might find it easier to use the
+ """ Construct a Dataset object. You might find it easier to use the
Group methods: Group["name"] or Group.create_dataset().
There are two modes of operation for this constructor:
@@ -383,7 +400,7 @@ class Dataset(HLObject):
the object will attempt to open an existing HDF5 dataset.
2. Create a dataset
- You can supply either:
+ You supply "group", "name" and either:
- Keyword "data"; a Numpy array from which the shape, dtype and
initial contents will be determined.
- Both "dtype" (Numpy dtype object) and "shape" (tuple of
@@ -433,12 +450,12 @@ class Dataset(HLObject):
self._attrs = AttributeManager(self)
def __getitem__(self, args):
- """ Read a slice from the underlying HDF5 array. Takes slices and
+ """ Read a slice from the HDF5 dataset. Takes slices and
recarray-style field names (more than one is allowed!) in any
order.
For a compound dataset ds, with shape (10,10,5) and fields "a", "b"
- and "c", the following are all legal subscripts:
+ and "c", the following are all legal syntax:
ds[1,2,3]
ds[1,2,:]
@@ -446,7 +463,7 @@ class Dataset(HLObject):
ds[1]
ds[:]
ds[1,2,3,"a"]
- ds[0:5:2, 0:6:3, 0:2, "a", "b"]
+ ds[0:5:2, ..., 0:2, "a", "b"]
"""
start, count, stride, names = slicer(self.shape, args)
@@ -496,10 +513,9 @@ class Dataset(HLObject):
return arr
def __setitem__(self, args):
- """ Write to the underlying array from an existing Numpy array. The
- shape of the Numpy array must match the shape of the selection,
- and the Numpy array's datatype must be convertible to the HDF5
- array's datatype.
+ """ Write to the HDF5 dataset from an Numpy array. The shape of the
+ Numpy array must match the shape of the selection, and the Numpy
+ array's datatype must be convertible to the HDF5 datatype.
"""
val = args[-1]
args = args[0:-1]
@@ -539,7 +555,13 @@ class AttributeManager(object):
array. Non-scalar data is always returned as an ndarray.
The len() of this object is the number of attributes; iterating over
- it yields the attribute names.
+ it yields the attribute names. They also support the __contains__
+ syntax ("if name in obj.attrs...").
+
+ Unlike groups, writing to an attribute will overwrite an existing
+ attribute of the same name. This is not a transacted operation; you
+ can lose data if you try to assign an object which h5py doesn't
+ understand.
"""
def __init__(self, parent):
@@ -548,6 +570,10 @@ class AttributeManager(object):
self.id = parent.id
def __getitem__(self, name):
+ """ Read the value of an attribute. If the attribute is scalar, it
+ will be returned as a Numpy scalar. Otherwise, it will be returned
+ as a Numpy ndarray.
+ """
attr = h5a.open_name(self.id, name)
arr = numpy.ndarray(attr.shape, dtype=attr.dtype)
@@ -558,34 +584,48 @@ class AttributeManager(object):
return arr
def __setitem__(self, name, value):
+ """ Set the value of an attribute, overwriting any previous value.
+ The value you provide must be convertible to a Numpy array or
+ scalar. If it's not, the action is aborted with no data loss.
+
+ Any existing value is destroyed just before the call to h5a.create.
+ If the creation fails, the data is not recoverable.
+ """
if not isinstance(value, numpy.ndarray):
value = numpy.array(value)
space = h5s.create_simple(value.shape)
htype = h5t.py_create(value.dtype)
- # TODO: some kind of transaction safeguard here
- try:
+ # TODO: some kind of transactions safeguard
+ if name in self:
h5a.delete(self.id, name)
- except H5Error:
- pass
+
attr = h5a.create(self.id, name, htype, space)
attr.write(value)
def __delitem__(self, name):
+ """ Delete an attribute (which must already exist). """
h5a.delete(self.id, name)
def __len__(self):
+ """ Number of attributes attached to the object. """
return h5a.get_num_attrs(self.id)
def __iter__(self):
+ """ Iterate over the names of attributes. """
for name in h5a.py_listattrs(self.id):
yield name
def iteritems(self):
+ """ Iterate over (name, value) tuples. """
for name in self:
yield (name, self[name])
+ def __contains__(self, name):
+ """ Determine if an attribute exists, by name. """
+ return h5a.py_exists(self.id, name)
+
def __str__(self):
if self.id._valid:
rstr = 'Attributes of "%s": ' % hbasename(h5i.get_name(self.id))
diff --git a/h5py/tests/test_h5a.py b/h5py/tests/test_h5a.py
index 28dd6c0..94df76e 100644
--- a/h5py/tests/test_h5a.py
+++ b/h5py/tests/test_h5a.py
@@ -197,6 +197,10 @@ class TestH5A(unittest.TestCase):
self.assertEqual(attrlist, ATTRIBUTES_ORDER)
+ def test_py_exists(self):
+
+ self.assert_(h5a.py_exists(self.obj, ATTRIBUTES_ORDER[0]))
+ self.assert_(not h5a.py_exists(self.obj, "Something else"))
diff --git a/setup.py b/setup.py
index 8ec510c..52bd43c 100644
--- a/setup.py
+++ b/setup.py
@@ -82,10 +82,10 @@ def warn(instring):
# === Parse command line arguments ============================================
-ENABLE_PYREX = False
-PYREX_ONLY = False
-PYREX_FORCE = False
-PYREX_FORCE_OFF = False
+ENABLE_PYREX = False # Flag: Pyrex must be run
+PYREX_ONLY = False # Flag: Run Pyrex, but don't perform build
+PYREX_FORCE = False # Flag: Disable Pyrex timestamp checking
+PYREX_FORCE_OFF = False # Flag: Don't run Pyrex, no matter what
API_VERS = (1,6)
DEBUG_LEVEL = 0
@@ -106,6 +106,7 @@ for arg in sys.argv[:]:
PYREX_FORCE_OFF = True
sys.argv.remove(arg)
elif arg.find('--api=') == 0:
+ ENABLE_PYREX=True
api = arg[6:]
if api == '16':
API_VERS = (1,6)
@@ -113,6 +114,7 @@ for arg in sys.argv[:]:
fatal('Unrecognized API version "%s" (only "16" currently allowed)' % api)
sys.argv.remove(arg)
elif arg.find('--debug=') == 0:
+ ENABLE_PYREX=True
DEBUG_LEVEL = int(arg[8:])
sys.argv.remove(arg)
@@ -177,40 +179,38 @@ extra_compile_args = pyx_extra_args
# Pyrex source files (without extension)
pyrex_sources = [os.path.join(pyx_src_path, x) for x in pyx_modules]
-# Check if the conditions.pxi file is up-to-date
-cond_path = os.path.join(pyx_src_path, 'conditions.pxi')
-cond = \
-"""
-%s
-
-DEF H5PY_API_MAJ = %d
-DEF H5PY_API_MIN = %d
-DEF H5PY_DEBUG = %d
-DEF H5PY_API = "%d.%d"
-""" % (AUTO_HDR, API_VERS[0], API_VERS[1], DEBUG_LEVEL,API_VERS[0], API_VERS[1])
-
-try:
- cond_file = open(cond_path,'r')
- cond_present = cond_file.read()
- cond_file.close()
- if cond_present != cond:
- ENABLE_PYREX = True
-except IOError:
- ENABLE_PYREX = True
- cond_present = ""
-
# If for some reason the .c files are missing, Pyrex is required.
if not all([os.path.exists(x+'.c') for x in pyrex_sources]):
ENABLE_PYREX = True
if ENABLE_PYREX and not PYREX_FORCE_OFF:
print "Running Pyrex..."
+
try:
from Pyrex.Compiler.Main import Version
if Version.version >= MIN_PYREX:
from Pyrex.Compiler.Main import compile_multiple, CompilationOptions
+ # Check if the conditions.pxi file is up-to-date
+ cond_path = os.path.join(pyx_src_path, 'conditions.pxi')
+ cond = \
+"""
+%s
+
+DEF H5PY_API_MAJ = %d
+DEF H5PY_API_MIN = %d
+DEF H5PY_DEBUG = %d
+DEF H5PY_API = "%d.%d"
+""" % (AUTO_HDR, API_VERS[0], API_VERS[1], DEBUG_LEVEL,API_VERS[0], API_VERS[1])
+
+ try:
+ cond_file = open(cond_path,'r')
+ cond_present = cond_file.read()
+ cond_file.close()
+ except IOError:
+ cond_present = ""
+
# If we regenerate the file every time, Pyrex's timestamp checking
# is useless. So only replace it if it's out of date.
if cond_present != cond:
--
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