[h5py] 49/455: More fixes & updates; exception hierarchy finally done

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:16 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 420ae1554427977ae2e3c430b0cae759c09e7b76
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Fri Jun 13 00:13:06 2008 +0000

    More fixes & updates; exception hierarchy finally done
---
 h5py/h5.pyx            |   8 +-
 h5py/h5a.pyx           |   1 +
 h5py/h5d.pyx           |   5 +-
 h5py/h5e.pyx           | 257 +++++++++++++++++++++++++++++++------------------
 h5py/h5f.pyx           |  27 ++++--
 h5py/h5g.pxd           |   2 +-
 h5py/h5g.pyx           |  91 +++++++++--------
 h5py/h5i.pyx           |   4 +-
 h5py/h5p.pxd           |  11 ++-
 h5py/h5p.pyx           |  52 +++++-----
 h5py/h5r.pyx           |  70 ++++++++------
 h5py/h5s.pyx           |  47 ++++-----
 h5py/h5t.pyx           | 213 +++++++++++++++++-----------------------
 h5py/h5z.pyx           |  38 ++++++--
 h5py/std_inline.pyx    |  19 ++++
 h5py/tests/test_h5a.py |  34 +++----
 h5py/tests/test_h5d.py |  24 ++---
 h5py/tests/test_h5f.py |  23 ++---
 h5py/tests/test_h5g.py |  20 ++--
 h5py/tests/test_h5s.py | 232 ++++++++++++++++++++++++++++++++++++++++++++
 h5py/utils.pyx         |  11 ++-
 21 files changed, 766 insertions(+), 423 deletions(-)

diff --git a/h5py/h5.pyx b/h5py/h5.pyx
index e71ef8d..ea1b263 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -12,15 +12,11 @@
 
 
 """
-    Private initialization module for the h5* family of modules.
-
-    Common module for the HDF5 low-level interface library.  This module
-    is imported at the top of every h5* sub-module.  Initializes the
-    library and defines common version info, classes and functions.
+    Common module for the HDF5 low-level interface library.  
 
     Library version and API information lives here:
     - HDF5_VERS, HDF5_VERS_TPL:  Library version
-    - API_VERS, API_VERS_TPL:  API version (1.6 or 1.8) used to compile
+    - API_VERS, API_VERS_TPL:  API version (1.6 or 1.8) used to compile h5py.
 """
 
 from h5e cimport _enable_exceptions
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index 574419a..b2afc0e 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -153,6 +153,7 @@ def get_name(hid_t attr_id):
 
     try:
         blen = H5Aget_name(attr_id, 0, NULL)
+        assert blen >= 0
         buf = <char*>emalloc(sizeof(char)*blen+1)
         blen = H5Aget_name(attr_id, blen+1, buf)
         strout = buf
diff --git a/h5py/h5d.pyx b/h5py/h5d.pyx
index af9e77d..92c55c6 100644
--- a/h5py/h5d.pyx
+++ b/h5py/h5d.pyx
@@ -156,9 +156,8 @@ def extend(hid_t dset_id, object shape):
     """ (INT dset_id, TUPLE shape)
 
         Extend the given dataset so it's at least as big as "shape".  Note that
-        the ability to extend a dataset depends on how its maximum dimensions
-        were set up when it was created. See the docstring for the API function
-        h5s.create_simple for more information.
+        a dataset may only be extended up to the maximum dimensions of its
+        dataspace, which are fixed when the dataset is created.
     """
     cdef hsize_t* dims
     cdef int rank
diff --git a/h5py/h5e.pyx b/h5py/h5e.pyx
index aeee447..6cb4b75 100644
--- a/h5py/h5e.pyx
+++ b/h5py/h5e.pyx
@@ -14,6 +14,11 @@
     Provides a Python exception hierarchy modeled on HDF5 major error numbers,
     and exports a C interface which automatically raises exceptions when
     an error is detected in the HDF5 library.
+
+    Each exception class is associated with an HDF5 major error number.  Since
+    the HDF5 library determines which error number is issued, it also
+    determines which exception class is raised.  The choice is occasionally
+    surprising, and not well documented in the library itself.
 """
 
 from python cimport PyErr_SetObject
@@ -28,78 +33,179 @@ class H5Error(EnvironmentError):
     """
     pass
 
-class ConversionError(StandardError):
-    """ Indicates error on Python side of dtype transformation.
-        Subclass of StandardError, as this is not a library problem.
-    """
-    pass
-
 # --- New classes -------------------------------------------------------------
 
-# H5E_ARGS => ValueError
-
-class FileError(H5Error, IOError):
-    """ H5E_FILE
-
-        Subclass of both H5Error and IOError.
-    """
-    pass
-
-class H5IOError(H5Error, IOError):
-    """ H5E_IO
-
-        Subclass of both H5Error and IOError.
-    """
+           
+#    H5E_ARGS,                   # invalid arguments to routine
+class ArgsError(H5Error):
+    """ H5E_ARGS """
     pass
-
+        
+#    H5E_RESOURCE,               # resource unavailable   
 class ResourceError(H5Error):
-    """ H5E_RESOURCE
-    """
+    """ H5E_RESOURCE """
+    pass
+                    
+#   H5E_INTERNAL,               #  Internal error (too specific to document)
+class InternalError(H5Error):
+    """ H5E_INTERNAL """
     pass
 
+#    H5E_FILE,                   # file Accessability       
+class FileError(H5Error):
+    """ H5E_FILE """
+    pass
+                  
+#    H5E_IO,                     # Low-level I/O                      
+class LowLevelIOError(H5Error):
+    """ H5E_IO """
+    pass
+        
+#    H5E_FUNC,                   # function Entry/Exit     
+class FuncError(H5Error):
+    """ H5E_FUNC """
+    pass
+                   
+#    H5E_ATOM,                   # object Atom         
+class AtomError(H5Error):
+    """ H5E_ATOM """
+    pass
+                       
+#   H5E_CACHE,                  # object Cache        
+class CacheError(H5Error):
+    """ H5E_CACHE """
+    pass
+                       
+#   H5E_BTREE,                  # B-Tree Node           
+class BtreeError(H5Error):
+    """ H5E_BTREE """
+    pass
+                     
+#    H5E_SYM,                    # symbol Table         
+class SymbolError(H5Error):
+    """ H5E_SYM """
+    pass
+                      
+#   H5E_HEAP,                   # Heap  
+class HeapError(H5Error):
+    """ H5E_HEAP """
+    pass
+                                     
+#    H5E_OHDR,                   # object Header     
+class ObjectHeaderError(H5Error):
+    """ H5E_OHDR """
+    pass
+                         
+#    H5E_DATATYPE,               # Datatype    
 class DatatypeError(H5Error):
-    """ H5E_DATATYPE
-    """
+    """ H5E_DATATYPE """
     pass
-
+                               
+#    H5E_DATASPACE,              # Dataspace                      
 class DataspaceError(H5Error):
-    """ H5E_DATASPACE
-    """
+    """ H5E_DATASPACE """
     pass
-
+            
+#    H5E_DATASET,                # Dataset                        
 class DatasetError(H5Error):
-    """ H5E_DATASET
-    """
+    """ H5E_DATASET """
     pass
-
+            
+#    H5E_STORAGE,                # data storage                
+class StorageError(H5Error):
+    """ H5E_STORAGE """
+    pass
+               
+#    H5E_PLIST,                  # Property lists                  
 class PropertyError(H5Error):
-    """ H5E_PLIST
-    """
+    """ H5E_PLIST """
     pass
-
-
-class H5AttributeError(H5Error):
-    """ H5E_ATTR
-    """
+           
+#    H5E_ATTR,                   # Attribute     
+class AttrError(H5Error):
+    """ H5E_ATTR """
     pass
-
+                             
+#    H5E_PLINE,                  # Data filters       
 class FilterError(H5Error):
-    """ H5E_PLINE
-    """
+    """ H5E_PLINE """
+    pass
+                        
+#    H5E_EFL,                    # External file list                         
+class FileListError(H5Error):
+    """ H5E_EFL """
     pass
 
-class H5ReferenceError(H5Error):
-    """ H5E_REFERENCE
-    """
+#    H5E_REFERENCE,              # References          
+class RefError(H5Error):
+    """ H5E_REFERENCE """
+    pass
+                       
+#    H5E_VFL,                    # Virtual File Layer        
+class VirtualFileError(H5Error):
+    """ H5E_VFL """
+    pass
+         
+#    H5E_TBBT,                   # Threaded, Balanced, Binary Trees         
+class TBBTError(H5Error):
+    """ H5E_TBBT """
+    pass
+  
+#    H5E_TST,                    # Ternary Search Trees                       
+class TSTError(H5Error):
+    """ H5E_TST """
     pass
 
+#    H5E_RS,                     # Reference Counted Strings        
+class RSError(H5Error):
+    """ H5E_RS """
+    pass
+          
+#    H5E_ERROR,                  # Error API                    
+class ErrorError(H5Error):
+    """ H5E_ERROR """
+    pass
+              
+#    H5E_SLIST                   # Skip Lists        
+class SkipListError(H5Error):
+    """ H5E_SLIST """
+    pass  
+
+_exceptions = {
+    H5E_ARGS: ArgsError,
+    H5E_RESOURCE: ResourceError,
+    H5E_INTERNAL: InternalError,
+    H5E_FILE: FileError,
+    H5E_IO: LowLevelIOError,
+    H5E_FUNC: FuncError,
+    H5E_ATOM: AtomError,
+    H5E_CACHE: CacheError,
+    H5E_BTREE: BtreeError,
+    H5E_SYM: SymbolError,
+    H5E_HEAP: HeapError,
+    H5E_OHDR: ObjectHeaderError,
+    H5E_DATATYPE: DatatypeError,
+    H5E_DATASPACE: DataspaceError,
+    H5E_DATASET: DatasetError,
+    H5E_STORAGE: StorageError,
+    H5E_PLIST: PropertyError,
+    H5E_ATTR: AttrError,
+    H5E_PLINE: FilterError,
+    H5E_EFL: FileListError,
+    H5E_REFERENCE: RefError,
+    H5E_VFL: VirtualFileError,
+    H5E_TBBT: TBBTError,
+    H5E_TST: TSTError,
+    H5E_RS: RSError,
+    H5E_ERROR: ErrorError,
+    H5E_SLIST: SkipListError}
 
 # === Error stack inspection ==================================================
 
-cdef class H5ErrorStackElement:
+cdef class ErrorStackElement:
     """
         Represents an entry in the HDF5 error stack.
-        Loosely modeled on the H5E_error_t struct.
+        Modeled on the H5E_error_t struct.  All parameters are read-only.
 
         Atributes
         maj_num:    INT major error number
@@ -125,9 +231,9 @@ cdef herr_t walk_cb(int n, H5E_error_t *err_desc, void* stack_in):
     # Callback function to extract elements from the HDF5 error stack
 
     stack = <object>stack_in
-    cdef H5ErrorStackElement element
+    cdef ErrorStackElement element
 
-    element = H5ErrorStackElement()
+    element = ErrorStackElement()
     element.maj_num = err_desc.maj_num
     element.min_num = err_desc.min_num
     element.func_name = err_desc.func_name
@@ -138,7 +244,7 @@ cdef herr_t walk_cb(int n, H5E_error_t *err_desc, void* stack_in):
 
     return 0
 
-def get_error_stack():
+def error_stack():
     """ () => LIST error_stack
 
         Retrieve the HDF5 error stack as a list of ErrorStackElement objects,
@@ -148,7 +254,7 @@ def get_error_stack():
     H5Ewalk(H5E_WALK_DOWNWARD, walk_cb, <void*>stack)
     return stack
 
-def get_error_string():
+def error_string():
     """ () => STRING error_stack
 
         Return a string representation of the current error condition.
@@ -160,17 +266,16 @@ def get_error_string():
             '    n: "<Description>" at <function name>'
     """
     cdef int stacklen
-    cdef H5ErrorStackElement el
+    cdef ErrorStackElement el
 
-    stack = get_error_stack()
+    stack = error_stack()
     stacklen = len(stack)
 
     if stacklen == 0:
         msg = "Unspecified HDF5 error"
     else:
         el = stack[0]
-        msg = "%s (%s: %s)" % (el.desc.capitalize(), el.func_name, 
-                                H5Eget_major(<H5E_major_t>el.maj_num))
+        msg = "%s (%s)" % (el.desc.capitalize(), el.func_name)
         if stacklen > 1:
             msg = msg + "\nHDF5 Error Stack:"
             for i from 0<=i<stacklen:
@@ -250,45 +355,9 @@ cdef herr_t err_callback(void* client_data):
     mj = err_struct.maj_num
     mn = err_struct.min_num
 
-    # File-related errors traditionally raise IOError.
-    # These exceptions are both subclasses of H5Error
-    # and IOError.
-    if mj == H5E_FILE:
-        exc = FileError
-    elif mj == H5E_IO:
-        exc = H5IOError
-
-    # All errors which result from illegal function arguments
-    elif mj == H5E_ARGS:
-        exc = ValueError
-
-    # Major errors which map to new h5e exception classes
-    elif mj == H5E_RESOURCE:
-        exc = ResourceError
-    elif mj == H5E_DATATYPE:
-        exc = DatatypeError
-    elif mj == H5E_DATASPACE:
-        exc = DataspaceError
-    elif mj == H5E_DATASET:
-        exc = DatasetError
-    elif mj == H5E_PLIST:
-        exc = PropertyError
-    elif mj == H5E_ATTR:
-        exc = H5AttributeError
-    elif mj == H5E_PLINE:
-        exc = FilterError
-    elif mj == H5E_REFERENCE:
-        exc = H5ReferenceError
-
-    # Catchall: base H5Error.  
-    else:
-        exc = H5Error
-
-    msg = get_error_string()
-    if issubclass(exc, EnvironmentError):
-        PyErr_SetObject(exc, (1000*mj + mn, msg))
-    else:
-        PyErr_SetObject(exc, msg)
+    exc = _exceptions.get(mj, H5Error)
+    msg = error_string()
+    PyErr_SetObject(exc, (1000*mj + mn, msg))
 
     return 1
 
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index 2d59c17..20e316c 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -67,19 +67,25 @@ def create(char* name, int flags=H5F_ACC_TRUNC, hid_t create_id=H5P_DEFAULT,
             INT access_id=H5P_DEFAULT)
         => INT file_id
 
-        Create a new HDF5 file.  Keyword "flags" may be either ACC_TRUNC, in
-        which case any existing file will be destroyed, or ACC_EXCL, which
-        will force the creation to fail if the file already exists.
-        Keywords create_id and access_id may be dataset creation and access
-        property lists, respectively.
+        Create a new HDF5 file.  Keyword "flags" may be either:
+            ACC_TRUNC:  Truncate an existing file, discarding its data
+            ACC_EXCL:   Fail if a conflicting file exists
+
+        To keep the behavior in line with that of Python's built-in functions,
+        the default is ACC_TRUNC.  Be careful! Keywords create_id and 
+        access_id  may be file creation and access property lists, 
+        respectively.
     """
     return H5Fcreate(name, flags, create_id, access_id)
 
 def flush(hid_t file_id, int scope=H5F_SCOPE_LOCAL):
     """ (INT file_id, INT scope=SCOPE_LOCAL)
 
-        Tell the HDF5 library to flush file buffers to disk.  See the HDF5
-        docs for the meaning of the scope keyword.
+        Tell the HDF5 library to flush file buffers to disk.  file_id may
+        be the file identifier, or the identifier of any object residing in
+        the file.  Keyword "scope" may be:
+            SCOPE_LOCAL:    Flush only the given file
+            SCOPE_GLOBAL:   Flush the entire virtual file
     """
     H5Fflush(file_id, <H5F_scope_t>scope)
 
@@ -116,9 +122,10 @@ def unmount(hid_t loc_id, char* name):
 # === File inspection =========================================================
 
 def get_filesize(hid_t file_id):
-    """ (INT file_id) => LONG size_in_bytes
+    """ (INT file_id) => LONG size
 
-        Determine the total size of the HDF5 file, including the user block.
+        Determine the total size (in bytes) of the HDF5 file, 
+        including any user block.
     """
     cdef hsize_t size
     H5Fget_filesize(file_id, &size)
@@ -156,6 +163,7 @@ def get_name(hid_t obj_id):
     name = NULL
 
     size = H5Fget_name(obj_id, NULL, 0)
+    assert size >= 0
     name = <char*>emalloc(sizeof(char)*(size+1))
     try:    
         H5Fget_name(obj_id, name, size+1)
@@ -203,7 +211,6 @@ def get_obj_ids(hid_t file_id, int types):
         efree(obj_list)
 
 
-
 # === Python extensions =======================================================
 
 PY_SCOPE = DDict({  H5F_SCOPE_LOCAL: 'LOCAL SCOPE', 
diff --git a/h5py/h5g.pxd b/h5py/h5g.pxd
index ecdc146..96d76ff 100644
--- a/h5py/h5g.pxd
+++ b/h5py/h5g.pxd
@@ -56,7 +56,7 @@ 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)
+  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 *
   herr_t H5Gget_objinfo(hid_t loc_id, char* name, int follow_link, H5G_stat_t *statbuf) except *
 
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 0807458..5885cb4 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -20,6 +20,7 @@ from utils cimport emalloc, efree
 # Runtime imports
 import h5
 from h5 import DDict
+from h5e import H5Error
 
 # === Public constants and data structures ====================================
 
@@ -38,21 +39,22 @@ LINK_SOFT  = H5G_LINK_SOFT
 cdef class GroupStat:
     """ Represents the H5G_stat_t structure containing group member info.
 
-        Fields:
-        fileno -> 2-tuple uniquely* identifying the current file
-        objno  -> 2-tuple uniquely* identifying this object
-        nlink  -> Number of hard links to this object
-        mtime  -> Modification time of this object (flaky)
+        Fields (read-only):
+        fileno  ->  2-tuple uniquely* identifying the current file
+        objno   ->  2-tuple uniquely* identifying this object
+        nlink   ->  Number of hard links to this object
+        mtime   ->  Modification time of this object
+        linklen ->  Length of the symbolic link name, or 0 if not a link.
 
         *"Uniquely identifying" means unique among currently open files, 
         not universally unique.
     """
-    cdef public object fileno  # will be a 2-tuple
-    cdef public object objno   # will be a 2-tuple
-    cdef public unsigned int nlink
-    cdef public int type
-    cdef public time_t mtime
-    cdef public size_t linklen
+    cdef readonly object fileno  # will be a 2-tuple
+    cdef readonly object objno   # will be a 2-tuple
+    cdef readonly unsigned int nlink
+    cdef readonly int type
+    cdef readonly time_t mtime
+    cdef readonly size_t linklen
 
 
 # === Basic group management ==================================================
@@ -72,8 +74,9 @@ def close(hid_t group_id):
 def create(hid_t loc_id, char* name, int size_hint=-1):
     """ (INT loc_id, STRING name, INT size_hint=-1)
 
-        Create a new group named "name", under a parent group identified by
-        "loc_id".  See the HDF5 documentation for the meaning of size_hint.
+        Create a new group, under a given parent group.  If given, size_hint
+        is an estimate of the space to reserve (in bytes) for group member
+        names.
     """
     return H5Gcreate(loc_id, name, size_hint)
 
@@ -83,14 +86,13 @@ def link(hid_t loc_id, char* current_name, char* new_name, int link_type=H5G_LIN
     """ ( INT loc_id, STRING current_name, STRING new_name, 
           INT link_type=LINK_HARD, INT remote_id=-1) 
 
-        Create a new hard or soft link.  The link target (object the link will
-        point to) is identified by its parent group "loc_id", and the string
-        current_name.  The name of the new link is new_name.  If you want to
-        create the link in another group, pass its identifier through
-        remote_id.
+        Create a new hard or soft link.  loc_id and current_name identify
+        the link target (object the link will point to).  The new link is
+        identified by new_name and (optionally) another group id "remote_id".
 
-        Hard links are created by default (link_type=LINK_HARD).  To create a
-        symbolic link, pass in link_type=LINK_SOFT.
+        Link types are:
+            LINK_HARD:  Hard link to existing object (default)
+            LINK_SOFT:  Symbolic link; link target need not exist.
     """
     if remote_id < 0:
         remote_id = loc_id
@@ -105,11 +107,11 @@ def unlink(hid_t loc_id, char* name):
     H5Gunlink(loc_id, name)
 
 def move(hid_t loc_id, char* current_name, char* new_name, hid_t remote_id=-1):
-    """ (INT loc_id, STRING current_name, STRING new_name, INT new_group_id=-1)
+    """ (INT loc_id, STRING current_name, STRING new_name, INT remote_id=-1)
 
-        Relink an object, identified by its parent group loc_id and string
-        current_name.  The new name of the link is new_name.  You can create
-        the link in a different group by passing its identifier to remote_id.
+        Relink an object.  loc_id and current_name identify the object.
+        new_name and (optionally) another group id "remote_id" determine
+        where it should be moved.
     """
     if remote_id < 0:
         remote_id = loc_id
@@ -132,8 +134,8 @@ def get_objname_by_idx(hid_t loc_id, hsize_t idx):
 
         Get the name of a group member given its zero-based index.
 
-        Due to a bug in the HDF5 library, the only possible exception
-        raised by this function is ValueError.
+        Due to a limitation of the HDF5 library, the generic exception
+        H5Error (errno 1) is raised if the idx parameter is out-of-range.
     """
     cdef int size
     cdef char* buf
@@ -142,7 +144,7 @@ def get_objname_by_idx(hid_t loc_id, hsize_t idx):
     # This function does not properly raise an exception
     size = H5Gget_objname_by_idx(loc_id, idx, NULL, 0)
     if size < 0:
-        raise ValueError("Invalid argument")
+        raise H5Error((1,"Invalid argument"))
 
     buf = <char*>emalloc(sizeof(char)*(size+1))
     try:
@@ -162,14 +164,14 @@ def get_objtype_by_idx(hid_t loc_id, hsize_t idx):
             - DATASET
             - DATATYPE
 
-        Due to a bug in the HDF5 library, the only possible exception 
-        raised by this function is ValueError.
+        Due to a limitation of the HDF5 library, the generic exception
+        H5Error (errno 1) is raised if the idx parameter is out-of-range.
     """
     # This function does not properly raise an exception
     cdef herr_t retval
     retval = H5Gget_objtype_by_idx(loc_id, idx)
     if retval < 0:
-        raise ValueError("Invalid argument.")
+        raise H5Error((0,"Invalid argument."))
     return retval
 
 def get_objinfo(hid_t loc_id, char* name, int follow_link=1):
@@ -197,19 +199,18 @@ def get_objinfo(hid_t loc_id, char* name, int follow_link=1):
 
     return statobj
 
-cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl):
+cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl) except -1:
+    # Callback function for H5Giterate
 
     func = int_tpl[0]
     data = int_tpl[1]
-    exc_list = int_tpl[2]
 
+    # An unhandled exception (anything except StopIteration) will 
+    # cause Pyrex to immediately return -1, which stops H5Giterate.
     try:
         func(gid, name, data)
     except StopIteration:
         return 1
-    except Exception, e:
-        exc_list.append(e)
-        return -1
 
     return 0
 
@@ -232,18 +233,14 @@ def iterate(hid_t loc_id, char* name, object func, object data=None, int startid
             exception is propagated.
     """
     cdef int i
-    cdef herr_t retval
-
-    i = startidx
 
-    int_tpl = (func, data, [])
+    if startidx < 0:
+        raise ValueError("Starting index must be non-negative.")
 
-    retval = H5Giterate(loc_id, name, &i, <H5G_iterate_t>iter_cb_helper, int_tpl)
+    i = startidx
+    int_tpl = (func, data)
 
-    if retval < 0:
-        if len(int_tpl[2]) != 0:
-            raise int_tpl[2][0]
-        raise GroupError("Error occured during iteration")
+    H5Giterate(loc_id, name, &i, <H5G_iterate_t>iter_cb_helper, int_tpl)
 
 def get_linkval(hid_t loc_id, char* name):
     """ (INT loc_id, STRING name) => STRING link_value
@@ -287,7 +284,7 @@ def get_comment(hid_t loc_id, char* name):
     cmnt = NULL
 
     cmnt_len = H5Gget_comment(loc_id, name, 0, NULL)
-    assert cmnt_len > 0
+    assert cmnt_len >= 0
 
     cmnt = <char*>emalloc(sizeof(char)*(cmnt_len+1))
     try:
@@ -359,11 +356,11 @@ def py_exists(hid_t group_id, char* name, int follow_link=1):
 
         Determine if a named member exists in the given group.  If follow_link
         is True (default), symbolic links will be dereferenced. Note this
-        function will not raise an exception.
+        function will not raise an exception if group_id is invalid.
     """
     try:
         H5Gget_objinfo(group_id, name, follow_link, NULL)
-    except:
+    except H5Error:
         return False
     return True
 
diff --git a/h5py/h5i.pyx b/h5py/h5i.pyx
index 3d8b4a6..296ea4b 100644
--- a/h5py/h5i.pyx
+++ b/h5py/h5i.pyx
@@ -45,8 +45,8 @@ def get_type(hid_t obj_id):
     """ (INT obj_id) => INT type_code
 
         Determine the type of an arbitrary HDF5 object.  The return value is
-        always one of the type constants defined in this module. 
-        If the ID is invalid, BADID is returned.
+        always one of the type constants defined in this module; if the ID is 
+        invalid, BADID is returned.
     """
     return <int>H5Iget_type(obj_id)
 
diff --git a/h5py/h5p.pxd b/h5py/h5p.pxd
index d807e1c..2ff5ea7 100644
--- a/h5py/h5p.pxd
+++ b/h5py/h5p.pxd
@@ -25,11 +25,12 @@ cdef extern from "hdf5.h":
   int H5P_DEFAULT
 
   # Property list classes
-  int H5P_NO_CLASS
-  int H5P_FILE_CREATE 
-  int H5P_FILE_ACCESS 
-  int H5P_DATASET_CREATE 
-  int H5P_DATASET_XFER 
+  hid_t H5P_NO_CLASS
+  hid_t H5P_FILE_CREATE 
+  hid_t H5P_FILE_ACCESS 
+  hid_t H5P_DATASET_CREATE 
+  hid_t H5P_DATASET_XFER 
+  hid_t H5P_MOUNT
 
   # --- Property list operations ----------------------------------------------
   # General operations
diff --git a/h5py/h5p.pyx b/h5py/h5p.pyx
index 7810989..20864bb 100644
--- a/h5py/h5p.pyx
+++ b/h5py/h5p.pyx
@@ -26,7 +26,6 @@ from utils cimport  require_tuple, convert_dims, convert_tuple, \
 import h5
 import h5t
 from h5 import DDict
-from h5e import ConversionError
 
 # === Public constants and data structures ====================================
 
@@ -36,6 +35,7 @@ FILE_CREATE    = H5P_FILE_CREATE
 FILE_ACCESS    = H5P_FILE_ACCESS
 DATASET_CREATE = H5P_DATASET_CREATE
 DATASET_XFER   = H5P_DATASET_XFER
+MOUNT          = H5P_MOUNT
 
 DEFAULT = H5P_DEFAULT
 
@@ -44,8 +44,12 @@ DEFAULT = H5P_DEFAULT
 def create(hid_t cls_id):
     """ (INT cls_id) => INT property_list_id
     
-        Create a new property list as an instance of a class, which should be
-        one of CLASS_*.
+        Create a new property list as an instance of a class; classes are:
+            FILE_CREATE
+            FILE_ACCESS
+            DATASET_CREATE
+            DATASET_XFER
+            MOUNT
     """
     return H5Pcreate(cls_id)
 
@@ -64,14 +68,14 @@ def close(hid_t plist):
 def get_class(hid_t plist):
     """ (INT plist) => INT class_code
 
-        Determine the class of a property list object (one of CLASS_*).
+        Determine the class of a property list object.
     """
     return H5Pget_class(plist)
 
 def equal(hid_t plist1, hid_t plist2):
     """ (INT plist1, INT plist2) => BOOL lists_are_equal
 
-        Compare two existing property lists for equality.
+        Compare two existing property lists or classes for equality.
     """
     return bool(H5Pequal(plist1, plist2))
 
@@ -97,13 +101,13 @@ def get_version(hid_t plist):
 
     return (super_, freelist, stab, shhdr)
 
-def set_userblock(hid_t plist, long size):
-    """ (INT plist, LONG size)    [File creation]
+def set_userblock(hid_t plist, hsize_t size):
+    """ (INT plist, INT/LONG size)    [File creation]
 
-        Set the file user block size, in bytes.  Must be a power of 2, and at
-        least 512.
+        Set the file user block size, in bytes.  
+        Must be a power of 2, and at least 512.
     """
-    H5Pset_userblock(plist, <hsize_t>size)
+    H5Pset_userblock(plist, size)
 
 def get_userblock(hid_t plist):
     """ (INT plist) => LONG size    [File creation]
@@ -117,16 +121,16 @@ def get_userblock(hid_t plist):
 def set_sizes(hid_t plist, size_t addr, size_t size):
     """ (INT plist, INT addr, INT size)    [File creation]
 
-        Set the addressing offsets and lengths for objects in an HDF5 file, in
-        bytes.
+        Set the addressing offsets and lengths for objects 
+        in an HDF5 file, in bytes.
     """
     H5Pset_sizes(plist, addr, size)
 
 def get_sizes(hid_t plist):
     """ (INT plist) => TUPLE sizes    [File creation]
 
-        Determine addressing offsets and lengths for objects in an HDF5 file, in
-        bytes.  Return value is a 2-tuple with values:
+        Determine addressing offsets and lengths for objects in an 
+        HDF5 file, in bytes.  Return value is a 2-tuple with values:
 
         0:  UINT Address offsets
         1:  UINT Lengths
@@ -176,9 +180,9 @@ def set_layout(hid_t plist, int layout_code):
     """ (INT plist, INT layout_code)    [Dataset creation]
 
         Set dataset storage strategy; legal values are:
-        * h5d.LAYOUT_COMPACT
-        * h5d.LAYOUT_CONTIGUOUS
-        * h5d.LAYOUT_CHUNKED
+        * h5d.COMPACT
+        * h5d.CONTIGUOUS
+        * h5d.CHUNKED
     """
     H5Pset_layout(plist, <H5D_layout_t>layout_code)
     
@@ -186,17 +190,17 @@ def get_layout(hid_t plist):
     """ (INT plist) => INT layout_code   [Dataset creation]
 
         Determine the storage strategy of a dataset; legal values are:
-        * h5d.LAYOUT_COMPACT
-        * h5d.LAYOUT_CONTIGUOUS
-        * h5d.LAYOUT_CHUNKED
+        * h5d.COMPACT
+        * h5d.CONTIGUOUS
+        * h5d.CHUNKED
     """
     return <int>H5Pget_layout(plist)
 
 def set_chunk(hid_t plist, object chunksize):
     """ (INT plist_id, TUPLE chunksize)    [Dataset creation]
 
-        Set the dataset chunk size.  It's up to you to provide values which
-        are compatible with your dataset.
+        Set the dataset chunk size.  It's up to you to provide 
+        values which are compatible with your dataset.
     """
     cdef herr_t retval
     cdef int rank
@@ -222,6 +226,7 @@ def get_chunk(hid_t plist):
     cdef hsize_t *dims
 
     rank = H5Pget_chunk(plist, 0, NULL)
+    assert rank >= 0
     dims = <hsize_t*>emalloc(sizeof(hsize_t)*rank)
 
     try:
@@ -236,7 +241,8 @@ def get_chunk(hid_t plist):
 def set_deflate(hid_t plist, unsigned int level=5):
     """ (INT plist_id, UINT level=5)    [Dataset creation]
 
-        Enable DEFLATE (gzip) compression, at the given level (0-9, default 5).
+        Enable DEFLATE (gzip) compression, at the given level.
+        Valid levels are 0-9, default is 5.
     """
     H5Pset_deflate(plist, level)
     
diff --git a/h5py/h5r.pyx b/h5py/h5r.pyx
index a4381a2..ad88eab 100644
--- a/h5py/h5r.pyx
+++ b/h5py/h5r.pyx
@@ -10,6 +10,10 @@
 # 
 #-
 
+"""
+    H5R API for object and region references.
+"""
+
 # Pyrex compile-time imports
 from h5g cimport H5G_obj_t
 
@@ -20,7 +24,7 @@ from h5 import DDict
 # === Public constants and data structures ====================================
 
 OBJECT = H5R_OBJECT
-REGION = H5R_DATASET_REGION
+DATASET_REGION = H5R_DATASET_REGION
 
 PY_TYPE = {H5R_OBJECT: 'OBJECT',  H5R_DATASET_REGION: 'DATASET REGION' }
 PY_TYPE = DDict(PY_TYPE)
@@ -36,15 +40,15 @@ cdef class Reference:
 
         Objects of this class are created exclusively by the library and 
         cannot be modified.  The read-only attribute "typecode" determines 
-        whether the reference is to an object in an HDF5 file (TYPE_OBJECT) 
-        or a dataspace region (TYPE_REGION).
+        whether the reference is to an object in an HDF5 file (OBJECT) 
+        or a dataset region (DATASET_REGION).
     """
 
     cdef ref_u ref
     cdef readonly int typecode
 
     def __str__(self):
-        return "HDF5 reference (type %s)" % TYPE_MAPPER[self.typecode]
+        return "HDF5 reference (type %s)" % PY_TYPE[self.typecode]
 
     def __repr__(self):
         return self.__str__()
@@ -55,7 +59,16 @@ def create(hid_t loc_id, char* name, int ref_type, hid_t space_id=-1):
     """ (INT loc_id, STRING name, INT ref_type, INT space_id=0)
         => ReferenceObject ref
 
-        Create a new reference, either to an object or a dataset region.
+        Create a new reference. The value of ref_type detemines the kind
+        of reference created:
+
+        - OBJECT    Reference to an object in an HDF5 file.  Parameters loc_id
+                    and name identify the object; space_id is unused.
+
+        - DATASET_REGION    
+                    Reference to a dataset region.  Parameters loc_id and
+                    name identify the dataset; the selection on space_id
+                    identifies the region.
     """
     cdef Reference ref
     ref = Reference()
@@ -65,40 +78,43 @@ def create(hid_t loc_id, char* name, int ref_type, hid_t space_id=-1):
 
     return ref
 
-def dereference(hid_t obj_id, Reference ref):
-    """ (INT obj_id, ReferenceObject ref) => INT obj_id
+def dereference(hid_t file_id, Reference ref):
+    """ (INT file_id, ReferenceObject ref) => INT obj_id
 
-        Open the object pointed to by "ref" and return its identifier.  The
-        parameter "obj_id" may be the file ID or the ID of any object which
-        lives in the file.
+        Open the object pointed to by "ref" and return its identifier.
+        The containing file must be provided via file_id, which can be
+        a file identifier or an identifier for any object which lives
+        in the file.
     """
-    return H5Rdereference(obj_id, <H5R_type_t>ref.typecode, &ref.ref)
+    return H5Rdereference(file_id, <H5R_type_t>ref.typecode, &ref.ref)
 
-def get_region(hid_t container_id, Reference ref):
-    """ (INT container_id, Reference ref) => INT dataspace_id
+def get_region(hid_t dataset_id, Reference ref):
+    """ (INT dataset_id, Reference ref) => INT dataspace_id
 
-        Retrieve the dataspace selection pointed to by a reference.  The given
-        reference must be in the dataset indicated by container_id.  Returns
-        an identifier for a copy of the dataspace for the dataset pointed to
-        by "ref", with the appropriate elements selected.
+        Retrieve the dataspace selection pointed to by a reference.
+        Returns a copy of the dataset's dataspace, with the appropriate
+        elements selected.
 
-        The given reference object must be of type TYPE_REGION.
+        The given reference object must be of type DATASET_REGION.
     """
-    return H5Rget_region(container_id, <H5R_type_t>ref.typecode, &ref.ref)
+    return H5Rget_region(dataset_id, <H5R_type_t>ref.typecode, &ref.ref)
 
-def get_obj_type(hid_t container_id, Reference ref):
-    """ (INT container_id, Reference ref) => INT obj_code
+def get_obj_type(hid_t ds_id, Reference ref):
+    """ (INT ds_id, Reference ref) => INT obj_code
 
         Determine what type of object an object reference points to.  The
-        reference may be either TYPE_OBJECT or TYPE_REGION.
+        reference may be either type OBJECT or DATASET_REGION.  For 
+        DATASET_REGION, the parameter ds_id must be either the dataset 
+        identifier, or the identifier for the object within which the
+        dataset is contained.
         
         The return value is one of:
-        h5g.OBJ_LINK        Symbolic link
-        h5g.OBJ_GROUP       Group
-        h5g.OBJ_DATASET     Dataset
-        h5g.OBJ_TYPE        Named datatype
+        h5g.LINK        Symbolic link
+        h5g.GROUP       Group
+        h5g.DATASET     Dataset
+        h5g.TYPE        Named datatype
     """
-    return <int>H5Rget_obj_type(container_id, <H5R_type_t>ref.typecode, &ref.ref)
+    return <int>H5Rget_obj_type(ds_id, <H5R_type_t>ref.typecode, &ref.ref)
 
 
 
diff --git a/h5py/h5s.pyx b/h5py/h5s.pyx
index 4cc6795..999a3cc 100644
--- a/h5py/h5s.pyx
+++ b/h5py/h5s.pyx
@@ -81,11 +81,12 @@ def copy(hid_t space_id):
 def create_simple(object dims_tpl, object max_dims_tpl=None):
     """ (TUPLE dims_tpl, TUPLE max_dims_tpl) => INT new_space_id
 
-        Create a simple (slab) dataspace from a tuple of dimensions.  Every
-        element of dims_tpl must be a positive integer.  You can also specify
-        the maximum dataspace size, via the tuple max_dims.  The special
-        integer SPACE_UNLIMITED, as an element of max_dims, indicates an
-        unlimited dimension.
+        Create a simple (slab) dataspace from a tuple of dimensions.  
+        Every element of dims_tpl must be a positive integer.  
+
+        You can optionally specify the maximum dataspace size. The 
+        special value UNLIMITED, as an element of max_dims, indicates 
+        an unlimited dimension.
     """
     cdef int rank
     cdef hsize_t* dims
@@ -114,8 +115,8 @@ def create_simple(object dims_tpl, object max_dims_tpl=None):
 def is_simple(hid_t space_id):
     """ (INT space_id) => BOOL is_simple
 
-        Determine if an existing dataspace is "simple".  This function is
-        rather silly, as all HDF5 dataspaces are (currently) simple.
+        Determine if an existing dataspace is "simple" (including scalar
+        dataspaces). Currently all HDF5 dataspaces are simple.
     """
     return bool(H5Sis_simple(space_id))
 
@@ -210,11 +211,12 @@ def extent_copy(hid_t dest_id, hid_t source_id):
 def set_extent_simple(hid_t space_id, object dims_tpl, object max_dims_tpl=None):
     """ (INT space_id, TUPLE dims_tpl, TUPLE max_dims_tpl=None)
 
-        Reset the dataspace extent, via a tuple of new dimensions.  Every
-        element of dims_tpl must be a positive integer.  You can also specify
-        the maximum dataspace size, via the tuple max_dims.  The special
-        integer UNLIMITED, as an element of max_dims, indicates an
-        unlimited dimension.
+        Reset the dataspace extent via a tuple of dimensions.  
+        Every element of dims_tpl must be a positive integer.  
+
+        You can optionally specify the maximum dataspace size. The 
+        special value UNLIMITED, as an element of max_dims, indicates 
+        an unlimited dimension.
     """
     cdef int rank
     cdef hsize_t* dims
@@ -243,7 +245,7 @@ def set_extent_simple(hid_t space_id, object dims_tpl, object max_dims_tpl=None)
 def set_extent_none(hid_t space_id):
     """ (INT space_id)
 
-        Remove the dataspace extent; class changes to h5s.CLASS_NO_CLASS.
+        Remove the dataspace extent; class changes to NO_CLASS.
     """
     H5Sset_extent_none(space_id)
 
@@ -263,16 +265,16 @@ def get_select_type(hid_t space_id):
 def get_select_npoints(hid_t space_id):
     """ (INT space_id) => LONG npoints
 
-        Determine the total number of points currently selected.  Works for
-        all selection techniques.
+        Determine the total number of points currently selected.  
+        Works for all selection techniques.
     """
     return H5Sget_select_npoints(space_id)
 
 def get_select_bounds(hid_t space_id):
     """ (INT space_id) => (TUPLE start, TUPLE end)
 
-        Determine the bounding box which exactly contains the current
-        selection.
+        Determine the bounding box which exactly contains 
+        the current selection.
     """
     cdef int rank
     cdef hsize_t *start
@@ -365,11 +367,11 @@ def select_elements(hid_t space_id, object coord_list, int op=H5S_SELECT_SET):
     """ (INT space_id, LIST coord_list, INT op=SELECT_SET)
 
         Select elements using a list of points.  List entries should be
-        <rank>-length tuples containing point coordinates.
-        A zero-length list is apparently not allowed.
+        tuples containing point coordinates. A zero-length list is 
+        apparently not allowed by the HDF5 library.
     """
-    cdef size_t nelements       # Number of point coordinates
-    cdef hsize_t *coords        # Contiguous 2D array nelements x rank x sizeof(hsize_t)
+    cdef size_t nelements   # Number of point coordinates
+    cdef hsize_t *coords    # Contiguous 2D array nelements x rank x sizeof(hsize_t)
 
     cdef int rank
     cdef int i_point
@@ -381,7 +383,8 @@ def select_elements(hid_t space_id, object coord_list, int op=H5S_SELECT_SET):
 
     rank = H5Sget_simple_extent_ndims(space_id)
 
-    # HDF5 expects the coordinates array to be a static, contiguous
+    # The docs say this should be an hsize_t**, but it seems that
+    # HDF5 expects the coordinates to be a static, contiguous
     # array.  We'll simulate that by malloc'ing a contiguous chunk
     # and using pointer arithmetic to initialize it.
     coords = <hsize_t*>emalloc(sizeof(hsize_t)*rank*nelements)
diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 9de293d..adea4d3 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -51,7 +51,6 @@
 
 """
 
-
 # Pyrex compile-time imports
 from defs_c cimport free
 from h5p cimport H5P_DEFAULT
@@ -65,7 +64,7 @@ from utils cimport  emalloc, efree, \
 # Runtime imports
 import h5
 from h5 import DDict
-from h5e import ConversionError
+from h5e import ArgsError
 import sys
 
 # === Custom C API ============================================================
@@ -171,8 +170,8 @@ C_S1 = H5T_C_S1
 def create(int classtype, size_t size):
     """ (INT class, INT size) => INT type_id
         
-        Create a new HDF5 type object.  Legal values are COMPOUND, 
-        OPAQUE, ENUM
+        Create a new HDF5 type object.  Legal values are 
+        COMPOUND, OPAQUE, and ENUM.
     """
     return H5Tcreate(<H5T_class_t>classtype, size)
 
@@ -207,23 +206,23 @@ def copy(hid_t type_id):
 def equal(hid_t typeid_1, hid_t typeid_2):
     """ (INT typeid_1, INT typeid_2) => BOOL types_are_equal
 
-        Test whether two identifiers point to the same datatype object.  Note
-        this does NOT perform any kind of logical comparison.
+        Test whether two identifiers point to the same datatype object.  
+        Note this does NOT perform any kind of logical comparison.
     """
     return bool(H5Tequal(typeid_1, typeid_2))
 
 def lock(hid_t type_id):
     """ (INT type_id)
 
-        Lock a datatype, which makes it immutable and indestructible.  Once
-        locked, it can't be unlocked.
+        Lock a datatype, which makes it immutable and indestructible.
+        Once locked, it can't be unlocked.
     """
     H5Tlock(type_id)
 
 def get_class(hid_t type_id):
     """ (INT type_id) => INT class
 
-        Get <type_id>'s class.
+        Determine the datatype's class.
     """
     return <int>H5Tget_class(type_id)
 
@@ -244,37 +243,41 @@ def get_super(hid_t type_id):
 def get_native_type(hid_t type_id, int direction):
     """ (INT type_id, INT direction) => INT new_type_id
 
-        Determine the native C equivalent for the given datatype.  Legal values
-        for "direction" are:
+        Determine the native C equivalent for the given datatype.
+        Legal values for "direction" are:
           DIR_DEFAULT
           DIR_ASCEND
           DIR_DESCEND
         These determine which direction the list of native datatypes is
         searched; see the HDF5 docs for a definitive list.
+
+        The returned datatype is always a copy one of NATIVE_*, and must
+        eventually be closed.
     """
     return H5Tget_native_type(type_id, <H5T_direction_t>direction)
 
 def detect_class(hid_t type_id, int classtype):
     """ (INT type_id, INT class) => BOOL class_is_present
 
-        Determine if a member of class <class> exists in <type_id>
+        Determine if a member of the given class exists in a compound
+        datatype.  The search is recursive.
     """
     return bool(H5Tdetect_class(type_id, <H5T_class_t>classtype))
 
-def close(hid_t type_id, int force=0):
-    """ (INT type_id, BOOL force=False)
+def close(hid_t type_id, int force=1):
+    """ (INT type_id, BOOL force=True)
 
-        Close this datatype.  If "force" is True, ignore any errors.  Useful
-        when you're not sure if you've got an immutable datatype.
+        Close this datatype.  If "force" is True (default), ignore errors 
+        commonly associated with attempting to close immutable types.
     """
-    if force:
-        PY_H5Tclose(type_id)
-    else:
+    try:
         H5Tclose(type_id)
+    except ArgsError, e:
+        if not (force and e.errno == 1005):  # ArgsError, bad value
+            raise
 
 # === Atomic datatype operations ==============================================
-#     H5Tget_size, H5Tset_size, H5Tget_order, H5Tset_order, H5Tget_precision, \
-#     H5Tset_precision, H5Tget_offset, H5Tset_offset, H5Tget_sign, H5Tset_sign
+
 
 def set_size(hid_t type_id, size_t size):
     """ (INT type_id, INT size)
@@ -332,14 +335,7 @@ def is_variable_str(hid_t type_id):
     return bool(H5Tis_variable_str(type_id))
 
 # === Compound datatype operations ============================================
-# get_nmembers
-# get_member_class
-# get_member_name
-# get_member_index
-# get_member_offset
-# get_member_type
-# insert
-# pack
+
 
 def get_nmembers(hid_t type_id):
     """ (INT type_id) => INT number_of_members
@@ -349,34 +345,37 @@ def get_nmembers(hid_t type_id):
     return H5Tget_nmembers(type_id)
 
 def get_member_class(hid_t type_id, int member):
-    """ (INT type_id, INT member_index) => INT class
+    """ (INT type_id, INT member) => INT class
 
         Determine the datatype class of the member of a compound type,
-        identified by its index (must be 0 <= idx <= nmembers).
+        identified by its index (0 <= member < nmembers).
     """
+    if member < 0:
+        raise ValueError("Member index must be non-negative.")
     return H5Tget_member_class(type_id, member)
 
     
 def get_member_name(hid_t type_id, int member):
-    """ (INT type_id, INT member_index) => STRING name
+    """ (INT type_id, INT member) => STRING name
     
         Determine the name of a member of a compound or enumerated type,
-        identified by its index.
+        identified by its index (0 <= member < nmembers).
     """
-
     cdef char* name
+    name = NULL
+
+    if member < 0:
+        raise ValueError("Member index must be non-negative.")
 
-    name = H5Tget_member_name(type_id, member)
-    if name == NULL:
-        raise RuntimeError("Failed to catch exception in get_member_name()")
     try:
+        name = H5Tget_member_name(type_id, member)
+        assert name != NULL
         pyname = name
     finally:
         free(name)
 
     return pyname
 
-
 def get_member_index(hid_t type_id, char* name):
     """ (INT type_id, STRING name) => INT index
 
@@ -389,9 +388,7 @@ def get_member_offset(hid_t type_id, int member):
     """ (INT type_id, INT member_index) => INT offset
 
         Determine the offset, in bytes, of the beginning of the specified
-        member of a compound datatype.  Due to a limitation of the HDF5
-        library, this function will never raise an exception.  It returns
-        0 on failure; be careful as this is also a legal offset value.
+        member of a compound datatype.
     """
     return H5Tget_member_offset(type_id, member)
 
@@ -402,14 +399,16 @@ def get_member_type(hid_t type_id, int member):
         Create a copy of a member of a compound datatype, identified by its
         index.  You are responsible for closing it when finished.
     """
+    if member < 0:
+        raise ValueError("Member index must be non-negative.")
     return H5Tget_member_type(type_id, member)
 
 def insert(hid_t type_id, char* name, size_t offset, hid_t field_id):
     """ (INT compound_type_id, STRING name, INT offset, INT member_type)
 
-        Add a member <member_type> named <name> to an existing compound 
-        datatype.  <offset> is  the offset in bytes from the beginning of the
-        compound type.
+        Add a named member datatype to a compound datatype.  The parameter
+        offset indicates the offset from the start of the compound datatype,
+        in bytes.
     """
     H5Tinsert(type_id, name, offset, field_id)
 
@@ -422,10 +421,6 @@ def pack(hid_t type_id):
     H5Tpack(type_id)
 
 # === Array datatype operations ===============================================
-# array_create
-# get_array_ndims
-# get_array_dims
-
 
 def array_create(hid_t base, object dims_tpl):
     """ (INT base_type_id, TUPLE dimensions)
@@ -472,15 +467,7 @@ def get_array_dims(hid_t type_id):
     finally:
         efree(dims)
 
-
 # === Enumeration datatypes ===================================================
-#  hid_t     H5Tenum_create(hid_t base_id)
-#  herr_t    H5Tenum_insert(hid_t type, char *name, void *value)
-#  herr_t    H5Tenum_nameof( hid_t type, void *value, char *name, size_t size  )
-#  herr_t    H5Tenum_valueof( hid_t type, char *name, void *value  )
-
-#  char*     H5Tget_member_name(hid_t type_id, unsigned field_idx  )
-#  int       H5Tget_member_index(hid_t type_id, char * field_name  )
 
 def enum_create(hid_t base_id):
     """ (INT base_type_id) => INT new_type_id
@@ -489,91 +476,73 @@ def enum_create(hid_t base_id):
     """
     return H5Tenum_create(base_id)
 
-cdef void _enum_convert(hid_t type_id, long long *buf, int reverse) except *:
+cdef int enum_convert(hid_t type_id, long long *buf, int reverse) except -1:
     # Convert the long long value in "buf" to the native representation
-    # of type_id.  Conversion performed in-place, DatatypeError raised
-    # on failure.
-    # Reverse: zero => llong->type; nonzero => type->llong
+    # of type_id.  Conversion performed in-place.
+    # Reverse: false => llong->type; true => type->llong
+
     cdef hid_t basetype
-    cdef herr_t retval
     cdef H5T_class_t class_code
 
     class_code = H5Tget_class(type_id)
     if class_code != H5T_ENUM:
-        raise DatatypeError("Type %d is not of class ENUM")
+        raise ValueError("Type %d is not of class ENUM" % type_id)
 
     basetype = H5Tget_super(type_id)
-    if basetype < 0:
-        raise DatatypeError("Failed to determine base type of datatype %d" % type_id)
+    assert basetype > 0
 
     try:
         if not reverse:
-            retval = H5Tconvert(H5T_NATIVE_LLONG, basetype, 1, buf, NULL, H5P_DEFAULT)
+            H5Tconvert(H5T_NATIVE_LLONG, basetype, 1, buf, NULL, H5P_DEFAULT)
         else:
-            retval = H5Tconvert(basetype, H5T_NATIVE_LLONG, 1, buf, NULL, H5P_DEFAULT)
-        if retval < 0:
-            raise DatatypeError("Failed to convert enum value")
+            H5Tconvert(basetype, H5T_NATIVE_LLONG, 1, buf, NULL, H5P_DEFAULT)
     finally:
         PY_H5Tclose(basetype)
 
 def enum_insert(hid_t type_id, char* name, long long value):
     """ (INT type_id, STRING name, INT/LONG value)
 
-        Define a new member of an enumerated type.  <value> will be
+        Define a new member of an enumerated type.  The value will be
         automatically converted to the base type defined for this enum.  If
         the conversion results in overflow, the value will be silently clipped.
     """
-    cdef herr_t retval
-    cdef hid_t ptype
     cdef long long buf
-    ptype = 0
 
-    try:
-        buf = value
-        _enum_convert(type_id, &buf, 0)
-        return H5Tenum_insert(type_id, name, &buf)
-    finally:
-        if ptype:
-            PY_H5Tclose(ptype)
+    buf = value
+    enum_convert(type_id, &buf, 0)
+    H5Tenum_insert(type_id, name, &buf)
 
 def enum_nameof(hid_t type_id, long long value):
     """ (INT type_id, LLONG value) => STRING name
 
         Determine the name associated with the given value.  Due to a
         limitation of the HDF5 library, this can only retrieve names up to
-        1023 characters.
+        1023 characters in length.
     """
     cdef herr_t retval
-    cdef char* name
+    cdef char name[1024]
     cdef long long buf
 
-    name = <char*>emalloc(1024)
-
-    try:
-        buf = value
-        _enum_convert(type_id, &buf, 0)
-        retval = H5Tenum_nameof(type_id, &buf, name, 1024)
-        if retval < 0:  # not sure whether H5Tenum_nameof will actually log an error
-            raise RuntimeError("Failed to determine enum name of %d" % value)
-        retstring = name
-        return retstring
-    finally:
-        efree(name)
+    buf = value
+    enum_convert(type_id, &buf, 0)
+    retval = H5Tenum_nameof(type_id, &buf, name, 1024)
+    if retval < 0:  # not sure whether H5Tenum_nameof will actually log an error
+        raise RuntimeError("Failed to determine enum name of %d" % value)
+    retstring = name
+    return retstring
 
 def enum_valueof(hid_t type_id, char* name):
     """ (INT type_id, STRING name) => LONG value)
 
         Get the value associated with an enum name.
     """
-    cdef herr_t retval
     cdef long long buf
 
     H5Tenum_valueof(type_id, name, &buf)
-    _enum_convert(type_id, &buf, 1)
-
+    enum_convert(type_id, &buf, 1)
     return buf
 
-def get_member_value(hid_t type_id, unsigned int idx):
+def get_member_value(hid_t type_id, int idx):
     """ (INT type_id, UINT index) => LONG value
 
         Determine the value for the member at the given zero-based index.
@@ -583,39 +552,38 @@ def get_member_value(hid_t type_id, unsigned int idx):
     cdef long long val
     ptype = 0
 
-    try:
-        ptype = H5Tget_super(type_id)
-        H5Tget_member_value(type_id, idx, &val)
-        H5Tconvert(ptype, H5T_NATIVE_LLONG, 1, &val, NULL, H5P_DEFAULT)
-        return val
-    finally:
-        if ptype:
-            PY_H5Tclose(ptype)
+    if index < 0:
+        raise ValueError("Index must be non-negative.")
+
+    H5Tget_member_value(type_id, idx, &val)
+    enum_convert(type_id, &val, 1)
+    return val
 
 # === Opaque datatypes ========================================================
 
+
 def set_tag(hid_t type_id, char* tag):
     """ (INT type_id, STRING tag)
 
-        Set the a string describing the contents of an opaque datatype
+        Set a string describing the contents of an opaque datatype.
     """
     H5Tset_tag(type_id, tag)
 
 def get_tag(hid_t type_id):
     """ (INT type_id) => STRING tag
 
-        Get the tag associated with an opaque datatype
+        Get the tag associated with an opaque datatype.
     """
     cdef char* buf
     buf = NULL
 
-    buf = H5Tget_tag(type_id)
-    if buf == NULL:
-        raise RuntimeError("Failed to raise exception on H5Tget_tag")
-    tag = buf
-    free(buf)
-
-    return tag
+    try:
+        buf = H5Tget_tag(type_id)
+        assert buf != NULL
+        tag = buf
+        return tag
+    finally:
+        free(buf)
 
 # === Custom Python additions =================================================
 
@@ -744,7 +712,7 @@ def py_h5t_to_dtype(hid_t type_id, object byteorder=None,
 
     elif classtype == H5T_STRING:
         if is_variable_str(type_id):
-            raise ConversionError("Variable-length strings are not supported.")
+            raise ValueError("Variable-length strings are not supported.")
         else:
             size = get_size(type_id)
         typeobj = dtype("|S" + str(size))
@@ -755,7 +723,6 @@ def py_h5t_to_dtype(hid_t type_id, object byteorder=None,
 
     elif classtype == H5T_COMPOUND:
 
-
         nfields = get_nmembers(type_id)
         field_names = []
         field_types = []
@@ -820,14 +787,14 @@ def py_h5t_to_dtype(hid_t type_id, object byteorder=None,
         shape = get_array_dims(type_id)
         typeobj = dtype( (base_dtype, shape) )
     else:
-        raise ConversionError('Unsupported datatype class "%s"' % PY_NAMES[classtype])
+        raise ValueError('Unsupported datatype class "%s"' % PY_NAMES[classtype])
 
     if byteorder is not None:
         return typeobj.newbyteorder(byteorder)
 
     return typeobj
 
-def py_dtype_to_h5t(dtype dtype_in, object complex_names=None):
+def py_dtype_to_h5t(dtype dtype_in not None, object complex_names=None):
     """ ( DTYPE dtype_in, TUPLE complex_names=None) => INT type_id
 
         Given a Numpy dtype object, generate a byte-for-byte memory-compatible
@@ -889,7 +856,7 @@ def py_dtype_to_h5t(dtype dtype_in, object complex_names=None):
         try:
             type_out =  _code_map[dtype_in.str]
         except KeyError:
-            raise ConversionError("Failed to find '%s' in atomic code map" % dtype_in.str)
+            raise ValueError("Failed to find '%s' in atomic code map" % dtype_in.str)
 
     # Complex numbers are stored as HDF5 structs, with names defined at runtime
     elif kind == c'c':
@@ -899,10 +866,10 @@ def py_dtype_to_h5t(dtype dtype_in, object complex_names=None):
         elif length == 16:
             type_out = create_ieee_complex128(byteorder, _complex_names[0], _complex_names[1])
         else:
-            raise ConversionError("Unsupported length %d for complex dtype: %s" % (length, repr(dtype_in)))
+            raise ValueError("Unsupported length %d for complex dtype: %s" % (length, repr(dtype_in)))
 
         if type_out < 0:
-            raise ConversionError("Failed to create complex equivalent for dtype: %s" % repr(dtype_in))
+            raise ValueError("No complex equivalent for dtype: %s" % repr(dtype_in))
 
     # Opaque/array types are differentiated by the presence of a subdtype
     elif kind == c'V':
@@ -922,7 +889,7 @@ def py_dtype_to_h5t(dtype dtype_in, object complex_names=None):
         set_size(type_out, length)
 
     else:
-        raise ConversionError("No conversion path for dtype: %s" % repr(dtype_in))
+        raise ValueError("No conversion path for dtype: %s" % repr(dtype_in))
 
     return type_out
 
@@ -1009,7 +976,7 @@ def py_can_convert_dtype(object dt, object complex_names=None):
     try:
         tid = py_dtype_to_h5t(dt, complex_names)
         can_convert = True
-    except ConversionError:
+    except ValueError:
         pass
 
     if tid:
diff --git a/h5py/h5z.pyx b/h5py/h5z.pyx
index 730ac7a..fb29c01 100644
--- a/h5py/h5z.pyx
+++ b/h5py/h5z.pyx
@@ -14,6 +14,8 @@
 """
     Filter API and constants
 """
+# Pyrex compile-time imports
+include "std_inline.pyx"
 
 # Runtime imports
 import h5
@@ -30,7 +32,6 @@ FILTER_FLETCHER32 = H5Z_FILTER_FLETCHER32
 FILTER_SZIP     = H5Z_FILTER_SZIP
 FILTER_RESERVED = H5Z_FILTER_RESERVED
 FILTER_MAX      = H5Z_FILTER_MAX
-FILTER_NMAX     = H5Z_MAX_NFILTERS
 
 FLAG_DEFMASK    = H5Z_FLAG_DEFMASK
 FLAG_MANDATORY  = H5Z_FLAG_MANDATORY
@@ -39,7 +40,11 @@ FLAG_INVMASK    = H5Z_FLAG_INVMASK
 FLAG_REVERSE    = H5Z_FLAG_REVERSE
 FLAG_SKIP_EDC   = H5Z_FLAG_SKIP_EDC
 
-#skip SZIP options
+SZIP_ALLOW_K13_OPTION_MASK  = H5_SZIP_ALLOW_K13_OPTION_MASK   #1
+SZIP_CHIP_OPTION_MASK       = H5_SZIP_CHIP_OPTION_MASK        #2
+SZIP_EC_OPTION_MASK         = H5_SZIP_EC_OPTION_MASK          #4
+SZIP_NN_OPTION_MASK         = H5_SZIP_NN_OPTION_MASK          #32
+SZIP_MAX_PIXELS_PER_BLOCK   = H5_SZIP_MAX_PIXELS_PER_BLOCK    #32
 
 FILTER_CONFIG_ENCODE_ENABLED = H5Z_FILTER_CONFIG_ENCODE_ENABLED
 FILTER_CONFIG_DECODE_ENABLED = H5Z_FILTER_CONFIG_DECODE_ENABLED
@@ -49,15 +54,36 @@ DISABLE_EDC = H5Z_DISABLE_EDC
 ENABLE_EDC  = H5Z_ENABLE_EDC
 NO_EDC      = H5Z_NO_EDC
 
-
 # === Filter API  =============================================================
 
-def filter_avail(int filter_id):
+def filter_avail(int filter_code):
+    """ (INT filter_code) => BOOL available
+
+        Determine if the given filter is available to the library.
+
+        The filter code should be one of:
+            FILTER_DEFLATE
+            FILTER_SHUFFLE
+            FILTER_FLETCHER32
+            FILTER_SZIP
+    """
+    return pybool(H5Zfilter_avail(<H5Z_filter_t>filter_code))
+
+def get_filter_info(int filter_code):
+    """ (INT filter_code) => INT filter_flags
 
-    return bool(H5Zfilter_avail(<H5Z_filter_t>filter_id))
+        Retrieve a bitfield with information about the given filter.
 
-def get_filter_info(int filter_id):
+        The filter code should be one of:
+            FILTER_DEFLATE
+            FILTER_SHUFFLE
+            FILTER_FLETCHER32
+            FILTER_SZIP
 
+        Valid bitmasks for use with the returned bitfield are:
+          FILTER_CONFIG_ENCODE_ENABLED
+          FILTER_CONFIG_DECODE_ENABLED
+    """
     cdef unsigned int flags
     H5Zget_filter_info(<H5Z_filter_t>filter_id, &flags)
     return flags
diff --git a/h5py/std_inline.pyx b/h5py/std_inline.pyx
new file mode 100644
index 0000000..375288f
--- /dev/null
+++ b/h5py/std_inline.pyx
@@ -0,0 +1,19 @@
+#+
+# 
+# This file is part of h5py, a low-level Python interface to the HDF5 library.
+# 
+# Copyright (C) 2008 Andrew Collette
+# http://h5py.alfven.org
+# License: BSD  (See LICENSE.txt for full license)
+# 
+# $Date$
+# 
+#-
+
+# Simple defs which aren't worth putting in their own module.
+
+cdef object pybool(long val):
+    # It seems Pyrex's bool() actually returns some sort of int.
+    if val:
+        return True
+    return False
diff --git a/h5py/tests/test_h5a.py b/h5py/tests/test_h5a.py
index 98114b9..ba7c1d8 100644
--- a/h5py/tests/test_h5a.py
+++ b/h5py/tests/test_h5a.py
@@ -68,8 +68,8 @@ class TestH5A(unittest.TestCase):
         h5g.close(obj)
         deletecopy(fid, filename)
         
-        self.assertRaises(ValueError, h5a.create, -1, "FOOBAR", -1, -1)
-        self.assertRaises(ValueError, h5a.write, -1, arr_ref)
+        self.assertRaises(H5Error, h5a.create, -1, "FOOBAR", -1, -1)
+        self.assertRaises(H5Error, h5a.write, -1, arr_ref)
 
     def test_open_idx(self):
         for idx, name in enumerate(ATTRIBUTES_ORDER):
@@ -77,7 +77,7 @@ class TestH5A(unittest.TestCase):
             self.assert_(self.is_attr(aid), "Open: index %d" % idx)
             h5a.close(aid)
     
-        self.assertRaises(ValueError, h5a.open_idx, -1, 0)
+        self.assertRaises(H5Error, h5a.open_idx, -1, 0)
 
     def test_open_name(self):
         for name in ATTRIBUTES:
@@ -85,7 +85,7 @@ class TestH5A(unittest.TestCase):
             self.assert_(self.is_attr(aid), 'Open: name "%s"' % name)
             h5a.close(aid)
 
-        self.assertRaises(ValueError, h5a.open_name, -1, "foo")
+        self.assertRaises(H5Error, h5a.open_name, -1, "foo")
 
     def test_close(self):
         aid = h5a.open_idx(self.obj, 0)
@@ -93,7 +93,7 @@ class TestH5A(unittest.TestCase):
         h5a.close(aid)
         self.assert_(not self.is_attr(aid))
     
-        self.assertRaises(ValueError, h5a.close, -1)
+        self.assertRaises(H5Error, h5a.close, -1)
 
     def test_delete(self):
         fid, filename = getcopy(HDFNAME)
@@ -103,7 +103,7 @@ class TestH5A(unittest.TestCase):
         self.assert_(not h5a.py_exists(obj, ATTRIBUTES_ORDER[0]))
         deletecopy(fid, filename)
 
-        self.assertRaises(ValueError, h5a.delete, -1, "foo")
+        self.assertRaises(H5Error, h5a.delete, -1, "foo")
 
     # === Attribute I/O =======================================================
 
@@ -125,7 +125,7 @@ class TestH5A(unittest.TestCase):
 
             h5a.close(aid)
         
-        self.assertRaises(ValueError, h5a.read, -1, arr_holder)
+        self.assertRaises(H5Error, h5a.read, -1, arr_holder)
 
     # h5a.write is done by test_create_write
 
@@ -134,7 +134,7 @@ class TestH5A(unittest.TestCase):
     def test_get_num_attrs(self):
         n = h5a.get_num_attrs(self.obj)
         self.assertEqual(n, len(ATTRIBUTES))
-        self.assertRaises(ValueError, h5a.get_num_attrs, -1)
+        self.assertRaises(H5Error, h5a.get_num_attrs, -1)
 
     def test_get_name(self):
     
@@ -144,7 +144,7 @@ class TestH5A(unittest.TestCase):
             self.assertEqual(supposed_name, name)
             h5a.close(aid)
 
-        self.assertRaises(ValueError, h5a.get_name, -1)
+        self.assertRaises(H5Error, h5a.get_name, -1)
 
     def test_get_space(self):
 
@@ -156,7 +156,7 @@ class TestH5A(unittest.TestCase):
             h5s.close(sid)
             h5a.close(aid)
 
-        self.assertRaises(ValueError, h5a.get_space, -1)
+        self.assertRaises(H5Error, h5a.get_space, -1)
 
     def test_get_type(self):
 
@@ -168,7 +168,7 @@ class TestH5A(unittest.TestCase):
             h5t.close(tid)
             h5a.close(aid)
 
-        self.assertRaises(ValueError, h5a.get_type, -1)
+        self.assertRaises(H5Error, h5a.get_type, -1)
 
     def test_iterate(self):
 
@@ -201,14 +201,14 @@ class TestH5A(unittest.TestCase):
         h5a.iterate(self.obj, iterate_two, namelist, 1)
         self.assertEqual(namelist, ATTRIBUTES_ORDER[1:3])
 
-        self.assertRaises(ValueError, h5a.iterate, -1, iterate_two, namelist)
+        self.assertRaises(H5Error, h5a.iterate, -1, iterate_two, namelist)
 
 
     # === Python extensions ===================================================
 
     def test_py_listattrs(self):
         self.assertEqual(h5a.py_listattrs(self.obj), ATTRIBUTES_ORDER)
-        self.assertRaises(ValueError, h5a.py_listattrs, -1)
+        self.assertRaises(H5Error, h5a.py_listattrs, -1)
 
     def test_py_shape(self):
         
@@ -217,7 +217,7 @@ class TestH5A(unittest.TestCase):
             retshape = h5a.py_shape(aid)
             self.assertEqual(retshape, shape) 
             h5a.close(aid)
-        self.assertRaises(ValueError, h5a.py_shape, -1)
+        self.assertRaises(H5Error, h5a.py_shape, -1)
 
     def test_py_dtype(self):
 
@@ -225,7 +225,7 @@ class TestH5A(unittest.TestCase):
             aid = h5a.open_name(self.obj, name)
             self.assertEqual(h5a.py_dtype(aid),dt)
             h5a.close(aid)
-        self.assertRaises(ValueError, h5a.py_dtype, -1)
+        self.assertRaises(H5Error, h5a.py_dtype, -1)
 
     def test_py_get(self):
 
@@ -234,7 +234,7 @@ class TestH5A(unittest.TestCase):
             arr_returned = h5a.py_get(self.obj, name)
             self.assert_(all(arr_returned == arr_reference), 
                 errstr(arr_reference, arr_returned))
-        self.assertRaises(ValueError, h5a.py_get, -1, "foo")
+        self.assertRaises(H5Error, h5a.py_get, -1, "foo")
 
     def test_py_set(self):
 
@@ -249,7 +249,7 @@ class TestH5A(unittest.TestCase):
         h5g.close(obj)
         deletecopy(fid, filename)
 
-        self.assertRaises(ValueError, h5a.py_set, -1, "foo", arr_reference)
+        self.assertRaises(H5Error, h5a.py_set, -1, "foo", arr_reference)
 
 
     def test_py_exists(self):
diff --git a/h5py/tests/test_h5d.py b/h5py/tests/test_h5d.py
index d20da42..9921bf8 100644
--- a/h5py/tests/test_h5d.py
+++ b/h5py/tests/test_h5d.py
@@ -16,7 +16,7 @@ import numpy
 
 import h5py
 from h5py import h5f, h5d, h5i, h5s, h5t, h5p
-from h5py.h5e import DatasetError
+from h5py.h5e import H5Error
 
 HDFNAME = os.path.join(os.path.dirname(h5py.__file__), 'tests/data/smpl_compound_chunked.hdf5')
 DTYPE = numpy.dtype([('a_name','>i4'),
@@ -52,8 +52,8 @@ class TestH5D(unittest.TestCase):
         self.did = h5d.open(self.fid, "CompoundChunked")
         self.assertEqual(h5i.get_type(self.did), h5i.DATASET)
 
-        self.assertRaises(DatasetError, h5d.open, self.fid, "Something else")
-        self.assertRaises(ValueError, h5d.close, -1)
+        self.assertRaises(H5Error, h5d.open, self.fid, "Something else")
+        self.assertRaises(H5Error, h5d.close, -1)
 
     def test_read(self):
         array = numpy.ndarray(SHAPE, dtype=DTYPE)
@@ -62,7 +62,7 @@ class TestH5D(unittest.TestCase):
         for name in DTYPE.fields:
             self.assert_(numpy.all(array[name] == basearray[name]), "%s::\n%s\n!=\n%s" % (name, array[name], basearray[name]))
 
-        self.assertRaises(ValueError, h5d.read, -1, h5s.ALL, h5s.ALL, array)
+        self.assertRaises(H5Error, h5d.read, -1, h5s.ALL, h5s.ALL, array)
 
     def test_get_space(self):
         sid = h5d.get_space(self.did)
@@ -71,16 +71,16 @@ class TestH5D(unittest.TestCase):
             self.assertEqual(shape, SHAPE)
         finally:
             h5s.close(sid)
-        self.assertRaises(ValueError, h5d.get_space, -1)
+        self.assertRaises(H5Error, h5d.get_space, -1)
 
     def test_get_space_status(self):
         status = h5d.get_space_status(self.did)
         self.assert_(status in h5d.PY_SPACE_STATUS)
-        self.assertRaises(ValueError, h5d.get_space_status, -1)
+        self.assertRaises(H5Error, h5d.get_space_status, -1)
 
     def test_get_offset(self):
         # Chunked datasets have no offset.  New test dset needed.
-        self.assertRaises(ValueError, h5d.get_offset, -1)
+        self.assertRaises(H5Error, h5d.get_offset, -1)
 
     def test_get_storage_size(self):
         # This function can't intentionally raise an exception.
@@ -93,7 +93,7 @@ class TestH5D(unittest.TestCase):
             self.assertEqual(h5i.get_type(tid), h5i.DATATYPE)
         finally:
             h5t.close(tid)
-        self.assertRaises(ValueError, h5d.get_type, -1)
+        self.assertRaises(H5Error, h5d.get_type, -1)
 
     def test_get_create_plist(self):
         pid = h5d.get_create_plist(self.did)
@@ -102,19 +102,19 @@ class TestH5D(unittest.TestCase):
         finally:
             h5p.close(pid)
 
-        self.assertRaises(ValueError, h5d.get_create_plist, -1)
+        self.assertRaises(H5Error, h5d.get_create_plist, -1)
 
     def test_py_shape(self):
         self.assertEqual(h5d.py_shape(self.did), SHAPE)
-        self.assertRaises(ValueError, h5d.py_shape, -1)
+        self.assertRaises(H5Error, h5d.py_shape, -1)
 
     def test_py_rank(self):
         self.assertEqual(h5d.py_rank(self.did), 1)
-        self.assertRaises(ValueError, h5d.py_rank, -1)
+        self.assertRaises(H5Error, h5d.py_rank, -1)
 
     def test_py_dtype(self):
         self.assertEqual(type(h5d.py_dtype(self.did)), numpy.dtype)
-        self.assertRaises(ValueError, h5d.py_dtype, -1)
+        self.assertRaises(H5Error, h5d.py_dtype, -1)
         
         
 
diff --git a/h5py/tests/test_h5f.py b/h5py/tests/test_h5f.py
index 2e49b59..89bfef3 100644
--- a/h5py/tests/test_h5f.py
+++ b/h5py/tests/test_h5f.py
@@ -17,6 +17,7 @@ import os
 import h5py
 from h5py import h5f, h5i, h5p
 from common import getcopy, deletecopy, errstr
+from h5py.h5e import H5Error
 
 HDFNAME = os.path.join(os.path.dirname(h5py.__file__), 'tests/data/attributes.hdf5')
 
@@ -34,21 +35,21 @@ class TestH5F(unittest.TestCase):
         h5f.close(fid)
         self.assertEqual(h5i.get_type(fid), h5i.BADID)
 
-        self.assertRaises(IOError, h5f.open, 'SOME OTHER NAME')
-        self.assertRaises(ValueError, h5f.close, -1)
+        self.assertRaises(H5Error, h5f.open, 'SOME OTHER NAME')
+        self.assertRaises(H5Error, h5f.close, -1)
 
     def test_create(self):
         name = tempfile.mktemp('.hdf5')
         fid = h5f.create(name)
         self.assertEqual(h5i.get_type(fid), h5i.FILE)
         h5f.close(fid)
-        self.assertRaises(IOError, h5f.create, name, h5f.ACC_EXCL)
+        self.assertRaises(H5Error, h5f.create, name, h5f.ACC_EXCL)
         os.unlink(name)
 
     def test_flush(self):
         fid, fname = getcopy(HDFNAME)
         h5f.flush(fid)
-        self.assertRaises(ValueError, h5f.flush, -1)
+        self.assertRaises(H5Error, h5f.flush, -1)
         deletecopy(fid, fname)
 
     def test_is_hdf5(self):
@@ -64,36 +65,36 @@ class TestH5F(unittest.TestCase):
     def test_get_filesize(self):
 
         self.assertEqual(h5f.get_filesize(self.fid), os.stat(HDFNAME).st_size)
-        self.assertRaises(ValueError, h5f.get_filesize, -1)
+        self.assertRaises(H5Error, h5f.get_filesize, -1)
 
     def test_get_create_plist(self):
         cplist = h5f.get_create_plist(self.fid)
         self.assert_(h5p.equal(h5p.get_class(cplist), h5p.FILE_CREATE))
         h5p.close(cplist)
-        self.assertRaises(ValueError, h5f.get_create_plist, -1)
+        self.assertRaises(H5Error, h5f.get_create_plist, -1)
 
     def test_get_access_plist(self):
         aplist = h5f.get_access_plist(self.fid)
         self.assert_(h5p.equal(h5p.get_class(aplist), h5p.FILE_ACCESS))
         h5p.close(aplist)
-        self.assertRaises(ValueError, h5f.get_access_plist, -1)
+        self.assertRaises(H5Error, h5f.get_access_plist, -1)
 
     def test_get_freespace(self):
         self.assert_(h5f.get_freespace(self.fid) >= 0)
-        self.assertRaises(ValueError, h5f.get_freespace, -1)
+        self.assertRaises(H5Error, h5f.get_freespace, -1)
 
     def test_get_name(self):
         self.assertEqual(h5f.get_name(self.fid), HDFNAME)
-        self.assertRaises(ValueError, h5f.get_name, -1)
+        self.assertRaises(H5Error, h5f.get_name, -1)
 
     def test_get_obj_count(self):
         self.assert_(h5f.get_obj_count(self.fid, h5f.OBJ_ALL) >= 0)
-        self.assertRaises(ValueError, h5f.get_obj_count, -1, h5f.OBJ_ALL)
+        self.assertRaises(H5Error, h5f.get_obj_count, -1, h5f.OBJ_ALL)
     
     def test_get_obj_ids(self):
         idlist = h5f.get_obj_ids(self.fid, h5f.OBJ_ALL)
         self.assert_(isinstance(idlist, list))
-        self.assertRaises(ValueError, h5f.get_obj_ids, -1, h5f.OBJ_ALL)
+        self.assertRaises(H5Error, h5f.get_obj_ids, -1, h5f.OBJ_ALL)
 
 
 
diff --git a/h5py/tests/test_h5g.py b/h5py/tests/test_h5g.py
index 08a1d80..8a6e0dc 100644
--- a/h5py/tests/test_h5g.py
+++ b/h5py/tests/test_h5g.py
@@ -46,7 +46,7 @@ class TestH5G(unittest.TestCase):
             self.assert_(not self.is_grp(gid))
         
         self.assertRaises(H5Error, h5g.open, self.obj, 'Some other group')
-        self.assertRaises(ValueError, h5g.close, -1)
+        self.assertRaises(H5Error, h5g.close, -1)
 
     def test_create(self):
         fid, filename = getcopy(HDFNAME)
@@ -98,7 +98,7 @@ class TestH5G(unittest.TestCase):
         self.assertRaises(H5Error, h5g.move, obj, 'Ghost group', 'blah')
         self.assertRaises(H5Error, h5g.unlink, obj, 'Some other name')
         self.assertRaises(H5Error, h5g.link, obj, 'Ghost group', 'blah') 
-        self.assertRaises(ValueError, h5g.get_linkval, -1, "foobar")
+        self.assertRaises(H5Error, h5g.get_linkval, -1, "foobar")
 
         h5g.close(obj)
 
@@ -107,7 +107,7 @@ class TestH5G(unittest.TestCase):
     def test_get_num_objs(self):
 
         self.assertEqual(h5g.get_num_objs(self.obj), 3)
-        self.assertRaises(ValueError, h5g.get_num_objs, -1)
+        self.assertRaises(H5Error, h5g.get_num_objs, -1)
 
     def test_objname_objtype(self):
 
@@ -115,8 +115,8 @@ class TestH5G(unittest.TestCase):
             self.assertEqual(h5g.get_objname_by_idx(self.obj, idx), name)
             self.assertEqual(h5g.get_objtype_by_idx(self.obj, idx), h5g.GROUP)
 
-        self.assertRaises(ValueError, h5g.get_objname_by_idx, self.obj, -1)
-        self.assertRaises(ValueError, h5g.get_objtype_by_idx, self.obj, -1)
+        self.assertRaises(H5Error, h5g.get_objname_by_idx, self.obj, -1)
+        self.assertRaises(H5Error, h5g.get_objtype_by_idx, self.obj, -1)
 
     def test_get_objinfo(self):
 
@@ -128,7 +128,7 @@ class TestH5G(unittest.TestCase):
         retval.mtime
         retval.linklen
 
-        self.assertRaises(ValueError, h5g.get_objinfo, self.obj, 'Something else')
+        self.assertRaises(H5Error, h5g.get_objinfo, self.obj, 'Something else')
 
 
     def test_iterate(self):
@@ -170,15 +170,15 @@ class TestH5G(unittest.TestCase):
         h5g.set_comment(obj, TEST_GROUPS[0], "This is a comment.")
         self.assertEqual(h5g.get_comment(obj, TEST_GROUPS[0]), "This is a comment.")
 
-        self.assertRaises(ValueError, h5g.set_comment, -1, "foo", "bar")
-        self.assertRaises(ValueError, h5g.get_comment, -1, "foo")
+        self.assertRaises(H5Error, h5g.set_comment, -1, "foo", "bar")
+        self.assertRaises(H5Error, h5g.get_comment, -1, "foo")
 
         deletecopy(fid, filename)
 
     def test_py_listnames(self):
 
         self.assertEqual(h5g.py_listnames(self.obj), TEST_GROUPS)
-        self.assertRaises(ValueError, h5g.py_listnames, -1)
+        self.assertRaises(H5Error, h5g.py_listnames, -1)
 
     def test_py_iternames(self):
 
@@ -186,7 +186,7 @@ class TestH5G(unittest.TestCase):
         self.assertEqual(list(iterator), TEST_GROUPS)
         #self.assertRaises(StopIteration, iterator.next()) bug in unittest
         
-        self.assertRaises(ValueError, h5g.py_iternames, -1)
+        self.assertRaises(H5Error, h5g.py_iternames, -1)
 
     def test_py_exists(self):
 
diff --git a/h5py/tests/test_h5s.py b/h5py/tests/test_h5s.py
new file mode 100644
index 0000000..4aebbd7
--- /dev/null
+++ b/h5py/tests/test_h5s.py
@@ -0,0 +1,232 @@
+#+
+# 
+# This file is part of h5py, a low-level Python interface to the HDF5 library.
+# 
+# Copyright (C) 2008 Andrew Collette
+# http://h5py.alfven.org
+# License: BSD  (See LICENSE.txt for full license)
+# 
+# $Date$
+# 
+#-
+
+import unittest
+
+import h5py
+from h5py import h5s, h5i
+from h5py.h5e import H5Error
+
+spaces = [(10,10), (1,1), (1,), ()]
+max_spaces = [(10,10), (3,4), (h5s.UNLIMITED,), ()]
+
+class TestH5S(unittest.TestCase):
+
+
+    def test_create_close(self):
+        sid = h5s.create(h5s.SCALAR)
+        self.assertEqual(h5i.get_type(sid), h5i.DATASPACE)
+        h5s.close(sid)
+        self.assertEqual(h5i.get_type(sid), h5i.BADID)
+
+        self.assertRaises(H5Error, h5s.create, -1)
+        self.assertRaises(H5Error, h5s.close, -1)
+
+    def test_copy(self):
+        sid = h5s.create(h5s.SCALAR)
+        sid2 = h5s.copy(sid)
+        self.assertEqual(h5i.get_type(sid2), h5i.DATASPACE)
+        h5s.close(sid2)
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.copy, -1)
+
+    def test_simple(self):
+        # Tests create_simple, get_simple_extent_dims, get_simple_extent_ndims
+
+        for space, max_space in zip(spaces, max_spaces):
+            sid = h5s.create_simple(space,max_space)
+            self.assertEqual(h5s.get_simple_extent_dims(sid), space)
+            self.assertEqual(h5s.get_simple_extent_dims(sid, True), max_space)
+            self.assertEqual(h5s.get_simple_extent_ndims(sid), len(space))
+            h5s.close(sid)
+
+        # Bad input
+        self.assertRaises(ValueError, h5s.create_simple, None)
+        self.assertRaises(H5Error, h5s.get_simple_extent_dims, -1)
+        self.assertRaises(H5Error, h5s.get_simple_extent_ndims, -1)
+
+        # Illegal input
+        self.assertRaises(H5Error, h5s.create_simple, (10,10), (10,9))
+        self.assertRaises(ValueError, h5s.create_simple, (10,10), (10,))
+
+    def test_is_simple(self):
+        # According to HDF5 docs, all dataspaces are "simple," even scalar ones.
+        sid = h5s.create(h5s.SCALAR)
+        self.assert_(h5s.is_simple(sid))
+        h5s.close(sid)
+        sid = h5s.create(h5s.SIMPLE)    
+        self.assert_(h5s.is_simple(sid))
+        h5s.close(sid)
+
+        # I think this should be H5Error but the library disagrees.
+        self.assertRaises(H5Error, h5s.is_simple, -1)
+
+    def test_offset_simple(self):
+        
+        sid = h5s.create_simple((100,100))
+        h5s.select_hyperslab(sid, (0,0), (10,10))
+        self.assertEqual(h5s.get_select_bounds(sid), ((0,0),(9,9)))
+        h5s.offset_simple(sid,(2,2))
+        self.assertEqual(h5s.get_select_bounds(sid), ((2,2),(11,11)))
+        h5s.offset_simple(sid, None)
+        self.assertEqual(h5s.get_select_bounds(sid), ((0,0),(9,9)))
+
+        self.assertRaises(H5Error, h5s.offset_simple, -1, (10,10))
+        self.assertRaises(ValueError, h5s.offset_simple, sid, (10,))
+
+        h5s.close(sid)
+
+    def test_get_simple_extent_npoints(self):
+        
+        sid = h5s.create_simple((100,100))
+        self.assertEqual(h5s.get_simple_extent_npoints(sid), 100*100)
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.get_simple_extent_npoints, -1)
+
+    def test_get_simple_extent_type(self):
+
+        sid = h5s.create(h5s.SIMPLE)
+        sid2 = h5s.create(h5s.SCALAR)
+        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.SIMPLE)
+        self.assertEqual(h5s.get_simple_extent_type(sid2), h5s.SCALAR)
+        h5s.close(sid)
+        h5s.close(sid2)
+
+        self.assertRaises(H5Error, h5s.get_simple_extent_type, -1)
+
+    def test_extent_copy(self):
+
+        sid = h5s.create(h5s.SIMPLE)
+        sid2 = h5s.create_simple((35,42))
+        h5s.extent_copy(sid, sid2)
+        self.assertEqual(h5s.get_simple_extent_dims(sid2), (35,42))
+        h5s.close(sid)
+        h5s.close(sid2)
+
+        self.assertRaises(H5Error, h5s.extent_copy, -1, -1)
+
+    def test_set_extent_simple(self):
+
+        for space, max_space in zip(spaces, max_spaces):
+            sid = h5s.create_simple((10,10))
+            h5s.set_extent_simple(sid, space, max_space)
+            self.assertEqual(h5s.get_simple_extent_dims(sid), space)
+            self.assertEqual(h5s.get_simple_extent_dims(sid, True), max_space)
+            h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.set_extent_simple, -1, (10,10))
+
+    def test_set_extent_none(self):
+
+        sid = h5s.create_simple((10,10))
+        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.SIMPLE)
+        h5s.set_extent_none(sid)
+        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.NO_CLASS)
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.set_extent_none, -1)
+
+
+    def test_get_select_type_npoints(self):
+
+        sid = h5s.create_simple((10,10))
+        h5s.select_hyperslab(sid, (0,0), (5,5))
+        self.assertEqual(h5s.get_select_type(sid), h5s.SEL_HYPERSLABS)
+        self.assertEqual(h5s.get_select_npoints(sid), 25)
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.get_select_type, -1)
+        self.assertRaises(H5Error, h5s.get_select_npoints, -1)
+
+    def test_get_select_bounds(self):
+
+        sid = h5s.create_simple((100,100))
+        h5s.select_all(sid)
+        self.assertEqual(h5s.get_select_bounds(sid), ((0,0), (99,99)))
+        h5s.select_hyperslab(sid, (10,10), (13,17))
+        self.assertEqual(h5s.get_select_bounds(sid), ((10,10), (22,26)))
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.get_select_bounds, -1)
+
+    def test_select(self):
+
+        sid = h5s.create_simple((100,100))
+        h5s.select_none(sid)
+        self.assertEqual(h5s.get_select_npoints(sid), 0)
+        h5s.select_all(sid)
+        self.assertEqual(h5s.get_select_npoints(sid), 100*100)
+        h5s.select_none(sid)
+        self.assertEqual(h5s.get_select_npoints(sid), 0)
+
+        h5s.select_hyperslab(sid, (0,0), (10,10))
+        self.assert_(h5s.select_valid(sid))
+        h5s.select_hyperslab(sid, (0,0), (200,200))
+        self.assert_(not h5s.select_valid(sid))
+        
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.select_none, -1)
+        self.assertRaises(H5Error, h5s.select_all, -1)
+        self.assertRaises(H5Error, h5s.select_valid, -1)
+
+    def test_elements(self):
+
+        pointlist= [(0,0), (15,98), (4,17), (67,32)] 
+        sid = h5s.create_simple((100,100))
+
+        h5s.select_elements(sid, pointlist)
+        self.assertEqual(h5s.get_select_elem_npoints(sid), len(pointlist))
+        self.assertEqual(h5s.get_select_elem_pointlist(sid), pointlist)
+
+        self.assertRaises(H5Error, h5s.select_elements, -1, [])
+        self.assertRaises(H5Error, h5s.get_select_elem_npoints, -1)
+        self.assertRaises(H5Error, h5s.get_select_elem_pointlist, -1)
+
+    def test_get_blocks(self):
+
+        start = [ (0,0), (50,60) ]
+        count = [ (5,5), (13,17) ]
+
+        sid = h5s.create_simple((100,100))
+        h5s.select_hyperslab(sid, start[0], count[0], op=h5s.SELECT_SET)
+        h5s.select_hyperslab(sid, start[1], count[1], op=h5s.SELECT_OR)
+
+        self.assertEqual(h5s.get_select_hyper_nblocks(sid), 2)
+        blocklist = h5s.get_select_hyper_blocklist(sid)
+        self.assertEqual(blocklist, [( (0,0), (4,4) ), ( (50,60), (62,76) )])
+
+        h5s.close(sid)
+
+        self.assertRaises(H5Error, h5s.get_select_hyper_nblocks, -1)
+        self.assertRaises(H5Error, h5s.get_select_hyper_blocklist, -1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5py/utils.pyx b/h5py/utils.pyx
index 8eaf565..38c2da7 100644
--- a/h5py/utils.pyx
+++ b/h5py/utils.pyx
@@ -10,7 +10,7 @@
 # 
 #-
 
-from python cimport PyTuple_Check, PyList_Check
+from python cimport PyTuple_Check, PyList_Check, PyErr_SetString
 
 cdef int require_tuple(object tpl, int none_allowed, int size, char* name) except -1:
     # Ensure that tpl is in fact a tuple, or None if none_allowed is nonzero.
@@ -28,7 +28,9 @@ cdef int require_tuple(object tpl, int none_allowed, int size, char* name) excep
     if none_allowed:
         nmsg = " or None"
 
-    raise ValueError("%s must be a tuple%s%s." % (name, smsg, nmsg))
+    msg = "%s must be a tuple%s%s." % (name, smsg, nmsg)
+    PyErr_SetString(ValueError, msg)
+    return -1
 
 cdef int require_list(object lst, int none_allowed, int size, char* name) except -1:
     # Counterpart of require_tuple, for lists
@@ -44,8 +46,9 @@ cdef int require_list(object lst, int none_allowed, int size, char* name) except
     if none_allowed:
         nmsg = " or None"
 
-    raise ValueError("%s must be a list%s%s." % (name, smsg, nmsg))
-
+    msg = "%s must be a list%s%s." % (name, smsg, nmsg)
+    PyErr_SetString(ValueError, msg)
+    return -1
 
 
 

-- 
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