[h5py] 126/455: More cleanup & consolidation

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:24 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 249dcbb7de271708a438ebd295c76e273d3a761d
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Wed Sep 24 06:21:42 2008 +0000

    More cleanup & consolidation
---
 h5py/defs.pxd  | 219 +++++++++++++++++++++++++++++++--------------------------
 h5py/h5.pxd    |   6 +-
 h5py/h5.pyx    | 156 +++++++++++++++++++++-------------------
 h5py/h5a.pyx   |  20 +++---
 h5py/h5d.pyx   |  13 ++--
 h5py/h5f.pyx   |   3 +
 h5py/h5g.pyx   |   4 +-
 h5py/h5l.pyx   |  11 ++-
 h5py/h5o.pyx   |   5 +-
 h5py/h5p.pyx   | 109 ++++++++++++++++++++++------
 h5py/h5r.pyx   |   5 ++
 h5py/h5s.pyx   |  35 ++++++++-
 h5py/h5t.pxd   |   8 +++
 h5py/h5t.pyx   | 204 +++++++++++++++++++++++++++++++++--------------------
 h5py/h5z.pyx   |   3 +
 h5py/sync.pxi  |  18 +++--
 h5py/utils.pyx |   7 +-
 17 files changed, 519 insertions(+), 307 deletions(-)

diff --git a/h5py/defs.pxd b/h5py/defs.pxd
index f9e76bd..278733b 100644
--- a/h5py/defs.pxd
+++ b/h5py/defs.pxd
@@ -12,8 +12,16 @@
 
 # This file provides all external libraries for h5py.
 
+# Originally each HDF5 subsection was attached to its own .pxd file, but this
+# proved much too complicated as the definitions are interdependent.
+
+# This file contains code or comments from the HDF5 library, as well as some
+# PyTables definitions.  Licenses for both these packages are located in 
+# the "licenses" folder in the distribution root directory.
+
 include "config.pxi"  # Needed for H5PY_*API defines
 
+
 # === Standard C library types and functions ==================================
 
 cdef extern from "stdlib.h":
@@ -45,6 +53,7 @@ cdef extern from "stdint.h":
   ctypedef signed long long int int64_t
   ctypedef signed long long int uint64_t 
 
+
 # === H5 - Common definitions and library functions ===========================
 
 cdef extern from "hdf5.h":
@@ -71,6 +80,22 @@ cdef extern from "hdf5.h":
   herr_t H5get_libversion(unsigned *majnum, unsigned *minnum,
                           unsigned *relnum ) except *
 
+  # New in 1.8.X
+  IF H5PY_18API:
+
+    ctypedef enum H5_iter_order_t:
+      H5_ITER_UNKNOWN = -1,       # Unknown order
+      H5_ITER_INC,                # Increasing order
+      H5_ITER_DEC,                # Decreasing order
+      H5_ITER_NATIVE,             # No particular order, whatever is fastest
+      H5_ITER_N                   # Number of iteration orders
+
+    ctypedef enum H5_index_t:
+      H5_INDEX_UNKNOWN = -1,      # Unknown index type     
+      H5_INDEX_NAME,              # Index on names      
+      H5_INDEX_CRT_ORDER,         # Index on creation order    
+      H5_INDEX_N                  # Number of indices defined    
+
 
 # === H5E - Error handling API ================================================
 
@@ -135,58 +160,35 @@ cdef extern from "hdf5.h":
   herr_t    H5Ewalk(H5E_direction_t direction, H5E_walk_t func, void* client_data)
 
 
-# === H5A - Attributes API ====================================================
-
-cdef extern from "hdf5.h":
-
-  hid_t     H5Acreate(hid_t loc_id, char *name, hid_t type_id, hid_t space_id, hid_t create_plist) except *
-  hid_t     H5Aopen_idx(hid_t loc_id, unsigned int idx) except *
-  hid_t     H5Aopen_name(hid_t loc_id, char *name) except *
-  herr_t    H5Aclose(hid_t attr_id) except *
-  herr_t    H5Adelete(hid_t loc_id, char *name) except *
-
-  herr_t    H5Aread(hid_t attr_id, hid_t mem_type_id, void *buf) except *
-  herr_t    H5Awrite(hid_t attr_id, hid_t mem_type_id, void *buf  ) except *
-
-  int       H5Aget_num_attrs(hid_t loc_id) except *
-  ssize_t   H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) except *
-  hid_t     H5Aget_space(hid_t attr_id) except *
-  hid_t     H5Aget_type(hid_t attr_id) except *
-
-  ctypedef herr_t (*H5A_operator_t)(hid_t loc_id, char *attr_name, operator_data) except -1
-  herr_t    H5Aiterate(hid_t loc_id, unsigned * idx, H5A_operator_t op, op_data) except *
-
-
 # === H5D - Dataset API =======================================================
 
 cdef extern from "hdf5.h":
 
-  # HDF5 layouts
   ctypedef enum H5D_layout_t:
     H5D_LAYOUT_ERROR    = -1,
-    H5D_COMPACT         = 0,    # raw data is very small
-    H5D_CONTIGUOUS      = 1,    # the default
-    H5D_CHUNKED         = 2,    # slow and fancy
-    H5D_NLAYOUTS        = 3     # this one must be last!
+    H5D_COMPACT         = 0,
+    H5D_CONTIGUOUS      = 1,
+    H5D_CHUNKED         = 2,
+    H5D_NLAYOUTS        = 3
 
   ctypedef enum H5D_alloc_time_t:
-    H5D_ALLOC_TIME_ERROR	=-1,
+    H5D_ALLOC_TIME_ERROR    =-1,
     H5D_ALLOC_TIME_DEFAULT  =0,
-    H5D_ALLOC_TIME_EARLY	=1,
-    H5D_ALLOC_TIME_LATE	    =2,
-    H5D_ALLOC_TIME_INCR	    =3
+    H5D_ALLOC_TIME_EARLY    =1,
+    H5D_ALLOC_TIME_LATE        =2,
+    H5D_ALLOC_TIME_INCR        =3
 
   ctypedef enum H5D_space_status_t:
-    H5D_SPACE_STATUS_ERROR	        =-1,
-    H5D_SPACE_STATUS_NOT_ALLOCATED	=0,
-    H5D_SPACE_STATUS_PART_ALLOCATED	=1,
-    H5D_SPACE_STATUS_ALLOCATED		=2
+    H5D_SPACE_STATUS_ERROR            =-1,
+    H5D_SPACE_STATUS_NOT_ALLOCATED    =0,
+    H5D_SPACE_STATUS_PART_ALLOCATED    =1,
+    H5D_SPACE_STATUS_ALLOCATED        =2
 
   ctypedef enum H5D_fill_time_t:
-    H5D_FILL_TIME_ERROR	=-1,
+    H5D_FILL_TIME_ERROR    =-1,
     H5D_FILL_TIME_ALLOC =0,
-    H5D_FILL_TIME_NEVER	=1,
-    H5D_FILL_TIME_IFSET	=2
+    H5D_FILL_TIME_NEVER    =1,
+    H5D_FILL_TIME_IFSET    =2
 
   ctypedef enum H5D_fill_value_t:
     H5D_FILL_VALUE_ERROR        =-1,
@@ -224,8 +226,9 @@ cdef extern from "hdf5.h":
                                     hid_t space_id, hsize_t *size) except *
   herr_t    H5Dvlen_reclaim(hid_t type_id, hid_t space_id, 
                             hid_t plist, void *buf) except *
+
   ctypedef  herr_t (*H5D_operator_t)(void *elem, hid_t type_id, unsigned ndim,
-				    hsize_t *point, void *operator_data)
+                    hsize_t *point, void *operator_data)
   herr_t    H5Diterate(void *buf, hid_t type_id, hid_t space_id, 
                         H5D_operator_t operator, void* operator_data) except *
 
@@ -287,8 +290,8 @@ cdef extern from "hdf5.h":
 cdef extern from "hdf5.h":
 
   ctypedef enum H5FD_mem_t:
-    H5FD_MEM_NOLIST	= -1,
-    H5FD_MEM_DEFAULT	= 0,
+    H5FD_MEM_NOLIST    = -1,
+    H5FD_MEM_DEFAULT    = 0,
     H5FD_MEM_SUPER      = 1,
     H5FD_MEM_BTREE      = 2,
     H5FD_MEM_DRAW       = 3,
@@ -298,7 +301,7 @@ cdef extern from "hdf5.h":
     H5FD_MEM_NTYPES
 
   # HDF5 uses a clever scheme wherein these are actually init() calls
-  # Hopefully Pyrex won't have a problem with this.
+  # Hopefully Cython won't have a problem with this.
   # Thankfully they are defined but -1 if unavailable
   hid_t H5FD_CORE
   hid_t H5FD_FAMILY
@@ -389,6 +392,7 @@ cdef extern from "hdf5.h":
 
   # New extensions in 1.8.X
   IF H5PY_18API:
+
     ctypedef enum H5G_storage_type_t:
         H5G_STORAGE_TYPE_UNKNOWN = -1,
         H5G_STORAGE_TYPE_SYMBOL_TABLE,
@@ -396,15 +400,16 @@ cdef extern from "hdf5.h":
         H5G_STORAGE_TYPE_DENSE 
    
     ctypedef struct H5G_info_t:
-        H5G_storage_type_t 	storage_type
-        hsize_t 	 nlinks
-        long int     max_corder  # FIXME: not really long int
+        H5G_storage_type_t     storage_type
+        hsize_t     nlinks
+        int64_t     max_corder
 
-    hid_t H5Gcreate_anon( hid_t loc_id, hid_t gcpl_id, hid_t gapl_id  ) except *
-    hid_t H5Gcreate2(hid_t loc_id, char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id) except *
-    hid_t H5Gopen2( hid_t loc_id, char * name, hid_t gapl_id  ) except *
-    herr_t H5Gget_info( hid_t group_id, H5G_info_t *group_info  ) except *
-    herr_t H5Gget_info_by_name( hid_t loc_id, char *group_name, H5G_info_t *group_info, hid_t lapl_id  ) except *
+    hid_t   H5Gcreate_anon( hid_t loc_id, hid_t gcpl_id, hid_t gapl_id) except *
+    hid_t   H5Gcreate2(hid_t loc_id, char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id) except *
+    hid_t   H5Gopen2( hid_t loc_id, char * name, hid_t gapl_id) except *
+    herr_t  H5Gget_info( hid_t group_id, H5G_info_t *group_info) except *
+    herr_t  H5Gget_info_by_name( hid_t loc_id, char *group_name, H5G_info_t *group_info, hid_t lapl_id) except *
+    hid_t   H5Gget_create_plist(hid_t group_id) except *
 
 
 # === H5I - Identifier and reflection interface ===============================
@@ -478,16 +483,7 @@ IF H5PY_18API:
       ctypedef herr_t (*H5L_iterate_t) (hid_t group, char *name, H5L_info_t *info,
                         void *op_data)
 
-      ctypedef enum H5_index_t:
-        H5_INDEX_NAME,
-        H5_INDEX_CRT_ORDER
-
-      ctypedef enum H5_iter_order_t:
-         H5_ITER_INC,      # Increasing order
-         H5_ITER_DEC,     # Decreasing order
-         H5_ITER_NATIVE  # Fastest available order
-
-     # API
+      # Links API
 
       herr_t H5Lmove(hid_t src_loc, char *src_name, hid_t dst_loc,
         char *dst_name, hid_t lcpl_id, hid_t lapl_id) except *
@@ -543,13 +539,16 @@ IF H5PY_18API:
 # === H5O - General object operations (1.8.X only) ============================
 
 IF H5PY_18API:
+
     cdef extern from "hdf5.h":
 
+      ctypedef uint32_t H5O_msg_crt_idx_t
+
       ctypedef enum H5O_type_t:
-        H5O_TYPE_UNKNOWN = -1,      #	Unknown object type		
-        H5O_TYPE_GROUP,	            #   Object is a group		
-        H5O_TYPE_DATASET,		    #   Object is a dataset		
-        H5O_TYPE_NAMED_DATATYPE,    #   Object is a named data type	
+        H5O_TYPE_UNKNOWN = -1,      #    Unknown object type        
+        H5O_TYPE_GROUP,                #   Object is a group        
+        H5O_TYPE_DATASET,            #   Object is a dataset        
+        H5O_TYPE_NAMED_DATATYPE,    #   Object is a named data type    
         H5O_TYPE_NTYPES             #   Number of different object types (must be last!) 
 
       # --- Components for the H5O_info_t struct ----------------------------------
@@ -573,12 +572,12 @@ IF H5PY_18API:
         mesg mesg
 
       ctypedef struct H5_ih_info_t:
-        hsize_t     index_size,  # /* btree and/or list */
+        hsize_t     index_size,  # btree and/or list
         hsize_t     heap_size
 
       cdef struct meta_size:
-        H5_ih_info_t   obj,    #        /* v1/v2 B-tree & local/fractal heap for groups, B-tree for chunked datasets */
-        H5_ih_info_t   attr    #        /* v2 B-tree & heap for attributes */
+        H5_ih_info_t   obj,    #        v1/v2 B-tree & local/fractal heap for groups, B-tree for chunked datasets
+        H5_ih_info_t   attr    #        v2 B-tree & heap for attributes
 
       ctypedef struct H5O_info_t:
         unsigned long   fileno         #  File number that object is located in 
@@ -593,15 +592,6 @@ IF H5PY_18API:
         hdr           hdr
         meta_size     meta_size
 
-      ctypedef enum H5_index_t:
-        H5_INDEX_NAME,
-        H5_INDEX_CRT_ORDER
-
-      ctypedef enum H5_iter_order_t:
-         H5_ITER_INC,      # Increasing order
-         H5_ITER_DEC,     # Decreasing order
-         H5_ITER_NATIVE  # Fastest available order
-
       ctypedef herr_t (*H5O_iterate_t)(hid_t obj, char *name, H5O_info_t *info,
                         void *op_data)
 
@@ -610,6 +600,7 @@ IF H5PY_18API:
 
       herr_t H5Oget_info(hid_t loc_id, H5O_info_t *oinfo) except *
 
+
 # === H5P - Property list API =================================================
 
 cdef extern from "hdf5.h":
@@ -627,23 +618,23 @@ cdef extern from "hdf5.h":
     H5D_NLAYOUTS        = 3     # this one must be last!
 
   ctypedef enum H5D_alloc_time_t:
-    H5D_ALLOC_TIME_ERROR	=-1,
+    H5D_ALLOC_TIME_ERROR    =-1,
     H5D_ALLOC_TIME_DEFAULT  =0,
-    H5D_ALLOC_TIME_EARLY	=1,
-    H5D_ALLOC_TIME_LATE	    =2,
-    H5D_ALLOC_TIME_INCR	    =3
+    H5D_ALLOC_TIME_EARLY    =1,
+    H5D_ALLOC_TIME_LATE        =2,
+    H5D_ALLOC_TIME_INCR        =3
 
   ctypedef enum H5D_space_status_t:
-    H5D_SPACE_STATUS_ERROR	        =-1,
-    H5D_SPACE_STATUS_NOT_ALLOCATED	=0,
-    H5D_SPACE_STATUS_PART_ALLOCATED	=1,
-    H5D_SPACE_STATUS_ALLOCATED		=2
+    H5D_SPACE_STATUS_ERROR            =-1,
+    H5D_SPACE_STATUS_NOT_ALLOCATED    =0,
+    H5D_SPACE_STATUS_PART_ALLOCATED    =1,
+    H5D_SPACE_STATUS_ALLOCATED        =2
 
   ctypedef enum H5D_fill_time_t:
-    H5D_FILL_TIME_ERROR	=-1,
+    H5D_FILL_TIME_ERROR    =-1,
     H5D_FILL_TIME_ALLOC =0,
-    H5D_FILL_TIME_NEVER	=1,
-    H5D_FILL_TIME_IFSET	=2
+    H5D_FILL_TIME_NEVER    =1,
+    H5D_FILL_TIME_IFSET    =2
 
   ctypedef enum H5D_fill_value_t:
     H5D_FILL_VALUE_ERROR        =-1,
@@ -664,8 +655,8 @@ cdef extern from "hdf5.h":
     H5F_CLOSE_DEFAULT = 3
 
   ctypedef enum H5FD_mem_t:
-    H5FD_MEM_NOLIST	= -1,
-    H5FD_MEM_DEFAULT	= 0,
+    H5FD_MEM_NOLIST    = -1,
+    H5FD_MEM_DEFAULT    = 0,
     H5FD_MEM_SUPER      = 1,
     H5FD_MEM_BTREE      = 2,
     H5FD_MEM_DRAW       = 3,
@@ -807,19 +798,19 @@ cdef extern from "hdf5.h":
     H5S_SELECT_INVALID    # Must be the last one
 
   ctypedef enum H5S_class_t:
-    H5S_NO_CLASS         = -1,  #/*error                                      */
-    H5S_SCALAR           = 0,   #/*scalar variable                            */
-    H5S_SIMPLE           = 1,   #/*simple data space                          */
+    H5S_NO_CLASS         = -1,  #/*error                                     
+    H5S_SCALAR           = 0,   #/*scalar variable                           
+    H5S_SIMPLE           = 1,   #/*simple data space                         
     # no longer defined in 1.8
-    #H5S_COMPLEX          = 2    #/*complex data space                         */
+    #H5S_COMPLEX          = 2    #/*complex data space                        
 
   ctypedef enum H5S_sel_type:
-    H5S_SEL_ERROR	= -1, 	    #/* Error			*/
-    H5S_SEL_NONE	= 0,        #/* Nothing selected 		*/
-    H5S_SEL_POINTS	= 1,        #/* Sequence of points selected	*/
-    H5S_SEL_HYPERSLABS  = 2,    #/* "New-style" hyperslab selection defined	*/
-    H5S_SEL_ALL		= 3,        #/* Entire extent selected	*/
-    H5S_SEL_N		= 4	        #/*THIS MUST BE LAST		*/
+    H5S_SEL_ERROR    = -1,         #Error           
+    H5S_SEL_NONE    = 0,        #Nothing selected        
+    H5S_SEL_POINTS    = 1,        #Sequence of points selected   
+    H5S_SEL_HYPERSLABS  = 2,    #"New-style" hyperslab selection defined   
+    H5S_SEL_ALL        = 3,        #Entire extent selected   
+    H5S_SEL_N        = 4            #/*THIS MUST BE LAST       
 
 
   # Basic operations
@@ -1145,10 +1136,38 @@ cdef extern from "hdf5.h":
         H5Z_ENABLE_EDC      = 1,
         H5Z_NO_EDC          = 2 
 
-    # --- Filter API ----------------------------------------------------------
     htri_t H5Zfilter_avail(H5Z_filter_t id_) except *
     herr_t H5Zget_filter_info(H5Z_filter_t filter_, unsigned int *filter_config_flags) except *
 
 
+# === H5A - Attributes API ====================================================
+
+cdef extern from "hdf5.h":
+
+  hid_t     H5Acreate(hid_t loc_id, char *name, hid_t type_id, hid_t space_id, hid_t create_plist) except *
+  hid_t     H5Aopen_idx(hid_t loc_id, unsigned int idx) except *
+  hid_t     H5Aopen_name(hid_t loc_id, char *name) except *
+  herr_t    H5Aclose(hid_t attr_id) except *
+  herr_t    H5Adelete(hid_t loc_id, char *name) except *
+
+  herr_t    H5Aread(hid_t attr_id, hid_t mem_type_id, void *buf) except *
+  herr_t    H5Awrite(hid_t attr_id, hid_t mem_type_id, void *buf  ) except *
+
+  int       H5Aget_num_attrs(hid_t loc_id) except *
+  ssize_t   H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) except *
+  hid_t     H5Aget_space(hid_t attr_id) except *
+  hid_t     H5Aget_type(hid_t attr_id) except *
+
+  ctypedef herr_t (*H5A_operator_t)(hid_t loc_id, char *attr_name, operator_data) except -1
+  herr_t    H5Aiterate(hid_t loc_id, unsigned * idx, H5A_operator_t op, op_data) except *
+
+  IF H5PY_18API:
+
+    ctypedef struct H5A_info_t:
+      hbool_t corder_valid          # Indicate if creation order is valid
+      H5O_msg_crt_idx_t corder      # Creation order
+      H5T_cset_t        cset        # Character set of attribute name
+      hsize_t           data_size   # Size of raw data
+
 
 
diff --git a/h5py/h5.pxd b/h5py/h5.pxd
index c88d587..8b8b350 100644
--- a/h5py/h5.pxd
+++ b/h5py/h5.pxd
@@ -25,7 +25,8 @@ cpdef PHIL get_phil()
 
 cdef class H5PYConfig:
 
-    cdef object _complex_names
+    cdef object _r_name
+    cdef object _i_name
     cdef readonly object API_16
     cdef readonly object API_18
     cdef readonly object DEBUG
@@ -38,8 +39,7 @@ cdef class ObjectID:
     cdef readonly int _locked
     cdef object _hash
 
-cdef object standard_richcmp(object self, object other, int how)
-cdef object obj_hash(ObjectID obj)
+# Library init.  Safe to call more than once.
 cdef int init_hdf5() except -1
 
 
diff --git a/h5py/h5.pyx b/h5py/h5.pyx
index 5bcf12b..ea8b2fa 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -33,7 +33,7 @@
 
 include "config.pxi"
 
-from python cimport PyErr_SetObject
+from python_exc cimport PyErr_SetString
 
 import atexit
 import threading
@@ -49,6 +49,41 @@ cdef class H5PYConfig:
         self.API_18 = H5PY_18API
         self.DEBUG = H5PY_DEBUG
         self.THREADS = H5PY_THREADS
+        self._r_name = 'r'
+        self._i_name = 'i'
+
+    property complex_names:
+        """ Settable 2-tuple controlling how complex numbers are saved.
+        """
+
+        def __get__(self):
+            return (self._r_name, self._i_name)
+
+        def __set__(self, val):
+            try:
+                r = val[0]
+                i = val[1]
+                if not (isinstance(r, str) and isinstance(i, str)):
+                    raise TypeError
+            except Exception:
+                raise TypeError("complex_names must be a 2-tuple (real, img)")
+            self._r_name = r
+            self._i_name = i
+
+    def __repr__(self):
+        rstr =  \
+"""\
+Summary of h5py config
+======================
+1.6 API: %s
+1.8 API: %s
+Thread-aware: %s
+Diagnostic mode: %s
+Complex names: %s"""
+
+        rstr %= (bool(self.API_16), bool(self.API_18), bool(self.THREADS),
+                 bool(self.DEBUG), self.complex_names)
+        return rstr
 
 # === Bootstrap diagnostics and threading, before decorator is defined ===
 
@@ -118,6 +153,7 @@ cdef class PHIL:
             return 0      
 
 cdef PHIL phil = PHIL()
+
 cpdef PHIL get_phil():
     """ Obtain a reference to the PHIL. """
     return phil
@@ -128,50 +164,6 @@ include "sync.pxi"
 
 # === Public C API for object identifiers =====================================
 
-cdef object standard_richcmp(object self, object other, int how):
-    # HDF5 object identity is determined by comparing hash values.  In the
-    # absence of a logical comparision method (for example, TypeId.equal()),
-    # this hash-based identity is used for comparison.
-    
-    # Subject to:
-    # 1. Both must be of the same type
-    # 2. Both must be hashable
-    # 3. Only == and != comparisons are supported
-    #
-    # Otherwise NotImplemented is returned, for Python's fallback mechanics.
-
-    if how != 2 and how != 3:
-        return NotImplemented
-
-    if not type(self) == type(other) and isinstance(self, ObjectID):
-        return NotImplemented   # Can't compare across types
-
-    try:
-        eq = (hash(self) == hash(other))
-    except TypeError:
-        return NotImplemented   # Can't compare unhashable instances
-
-    if how == 2:
-        return eq
-    return not eq
-
-cdef object obj_hash(ObjectID obj):
-    # Try to compute the hash of the given file-resident object, raising
-    # TypeError if it can't be done.
-    
-    # This is a counterpart to standard_richcmp.
-
-    cdef H5G_stat_t stat
-
-    phil.acquire()
-    try:
-        H5Gget_objinfo(obj.id, '.', 0, &stat)
-        return hash((stat.fileno[0], stat.fileno[1], stat.objno[0], stat.objno[1]))
-    except:
-        raise TypeError("Objects of class %s cannot be hashed" % obj.__class__.__name__)
-    finally:
-        phil.release()
-
 cdef class ObjectID:
 
     """
@@ -247,18 +239,46 @@ cdef class ObjectID:
             phil.release()
 
     def __richcmp__(self, object other, int how):
-        """ Supports only == and != """
-        return standard_richcmp(self, other, how)
+        """ Basic comparison for HDF5 objects.  Implements only equality:
+
+            1. Mismatched types always NOT EQUAL
+            2. Try to compare object hashes
+            3. If unhashable, compare identifiers
+        """
+        cdef bint truthval = 0
+
+        if how != 2 and how != 3:
+            return NotImplemented
+
+        if isinstance(other, ObjectID) and type(self) == type(other):
+            try:
+                truthval = hash(self) == hash(other)
+            except TypeError:
+                truthval = self.id == other.id
+
+        if how == 2:
+            return truthval
+        return not truthval
 
     def __hash__(self):
-        """ By default HDF5 objects are hashed based on their file and object
-            numbers.  Objects which are not file-resident cannot be hashed.
+        """ Default hash is computed from the object header, which requires
+            a file-resident object.  TypeError if this can't be done.
         """
+        cdef H5G_stat_t stat
+
         if self._hash is None:
-            self._hash = obj_hash(self)
+            phil.acquire()
+            try:
+                H5Gget_objinfo(self.id, '.', 0, &stat)
+                self._hash = hash((stat.fileno[0], stat.fileno[1], stat.objno[0], stat.objno[1]))
+            except Exception:
+                raise TypeError("Objects of class %s cannot be hashed" % self.__class__.__name__)
+            finally:
+                phil.release()
+
         return self._hash
 
-    def __str__(self):
+    def __repr__(self):
         phil.acquire()
         try:
             ref = str(H5Iget_ref(self.id)) if self._valid else "X"
@@ -267,8 +287,6 @@ cdef class ObjectID:
         finally:
             phil.release()
 
-    def __repr__(self):
-        return self.__str__()
 
 # === HDF5 "H5" API ===========================================================
 
@@ -521,8 +539,7 @@ def error_stack():
     H5Ewalk(H5E_WALK_DOWNWARD, walk_cb, <void*>stack)
     return stack
 
- at nosync
-def error_string():
+cpdef object error_string():
     """ () => STRING error_stack
 
         Return a string representation of the current error condition.
@@ -587,24 +604,16 @@ cdef herr_t err_callback(void* client_data) with gil:
     H5Ewalk(H5E_WALK_UPWARD, extract_cb, &err_struct)
     mj = err_struct.maj_num
 
-    exc = _exceptions.get(mj, H5Error)
+    try:
+        exc = _exceptions[mj]
+    except:
+        exc = H5Error
 
     msg = error_string()
-    PyErr_SetObject(exc, msg)
+    PyErr_SetString(exc, msg)
 
     return 1
 
-cdef int _enable_exceptions() except -1:
-    # Enable automatic exception handling, by registering the above callback
-    if H5Eset_auto(err_callback, NULL) < 0:
-        raise RuntimeError("Failed to register HDF5 exception callback.")
-    return 0
-
-cdef int _disable_exceptions() except -1:
-    # Disable automatic exception handling
-    if H5Eset_auto(NULL, NULL) < 0:
-        raise RuntimeError("Failed to unregister HDF5 exception callback.")
-    return 0
 
 # === Library init ============================================================
 
@@ -632,20 +641,23 @@ def _exithack():
         finally:
             free(objs)
 
-cdef int _hdf5_inited = 0
+cdef int hdf5_inited = 0
 
 cdef int init_hdf5() except -1:
     # Initialize the library and set register Python callbacks for exception
     # handling.  Safe to call more than once.
+    global hdf5_inited
 
-    if not _hdf5_inited:
+    if not hdf5_inited:
         IF H5PY_DEBUG:
             log_lib.info("* Initializing h5py library")
         if H5open() < 0:
             raise RuntimeError("Failed to initialize the HDF5 library.")
-        _enable_exceptions()
+        if H5Eset_auto(err_callback, NULL) < 0:
+            raise RuntimeError("Failed to register HDF5 exception callback.")
         atexit.register(_exithack)
-        _hdf5_inited = 1
+        hdf5_inited = 1
+
     return 0
 
 init_hdf5()
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index 885eda8..319e259 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -19,18 +19,15 @@ include "sync.pxi"
 
 # Compile-time imports
 from h5 cimport init_hdf5
-from h5t cimport TypeID, typewrap
+from h5t cimport TypeID, typewrap, py_create
 from h5s cimport SpaceID
 from numpy cimport import_array, ndarray, PyArray_DATA
-from utils cimport  check_numpy_read, check_numpy_write, \
-                    emalloc, efree
+from utils cimport check_numpy_read, check_numpy_write, emalloc, efree
 
 # Initialization
 init_hdf5()
 import_array()
 
-# Runtime imports
-import h5t
 
 # === General attribute operations ============================================
 
@@ -38,7 +35,7 @@ import h5t
 def create(ObjectID loc not None, char* name, TypeID tid not None, 
             SpaceID space not None):
     """ (ObjectID loc, STRING name, TypeID tid, SpaceID space) 
-        => INT attr_id
+        => AttrID
 
         Create a new attribute attached to a parent object, specifiying an 
         HDF5 datatype and dataspace.
@@ -47,7 +44,7 @@ def create(ObjectID loc not None, char* name, TypeID tid not None,
 
 @sync
 def open_idx(ObjectID loc not None, int idx):
-    """ (ObjectID loc_id, UINT idx) => INT attr_id
+    """ (ObjectID loc_id, UINT idx) => AttrID
 
         Open an exisiting attribute on an object, by zero-based index.
     """
@@ -60,7 +57,7 @@ def open_idx(ObjectID loc not None, int idx):
 
 @sync
 def open_name(ObjectID loc not None, char* name):
-    """ (ObjectID loc, STRING name) => INT attr_id
+    """ (ObjectID loc, STRING name) => AttrID
 
         Open an existing attribute on an object, by name.
     """
@@ -178,6 +175,9 @@ cdef class AttrID(ObjectID):
         name:   The attribute's name
         dtype:  A Numpy dtype representing this attribute's type
         shape:  A Numpy-style shape tuple representing the dataspace
+
+        Hashable: No
+        Equality: Python default
     """
     property name:
         """ The attribute's name
@@ -232,7 +232,7 @@ cdef class AttrID(ObjectID):
             space_id = H5Aget_space(self.id)
             check_numpy_write(arr_obj, space_id)
 
-            mtype = h5t.py_create(arr_obj.dtype)
+            mtype = py_create(arr_obj.dtype)
 
             H5Aread(self.id, mtype.id, PyArray_DATA(arr_obj))
 
@@ -258,7 +258,7 @@ cdef class AttrID(ObjectID):
         try:
             space_id = H5Aget_space(self.id)
             check_numpy_read(arr_obj, space_id)
-            mtype = h5t.py_create(arr_obj.dtype)
+            mtype = py_create(arr_obj.dtype)
 
             H5Awrite(self.id, mtype.id, PyArray_DATA(arr_obj))
 
diff --git a/h5py/h5d.pyx b/h5py/h5d.pyx
index 0129130..6c8c8e4 100644
--- a/h5py/h5d.pyx
+++ b/h5py/h5d.pyx
@@ -22,7 +22,7 @@ from h5 cimport init_hdf5
 from numpy cimport ndarray, import_array, PyArray_DATA, NPY_WRITEABLE
 from utils cimport  check_numpy_read, check_numpy_write, \
                     require_tuple, convert_tuple, emalloc, efree
-from h5t cimport TypeID, typewrap
+from h5t cimport TypeID, typewrap, py_create
 from h5s cimport SpaceID
 from h5p cimport PropID, propwrap, pdefault
 
@@ -30,9 +30,6 @@ from h5p cimport PropID, propwrap, pdefault
 init_hdf5()
 import_array()
 
-# Runtime imports
-import h5t
-
 # === Public constants and data structures ====================================
 
 COMPACT     = H5D_COMPACT
@@ -56,6 +53,7 @@ FILL_VALUE_UNDEFINED    = H5D_FILL_VALUE_UNDEFINED
 FILL_VALUE_DEFAULT      = H5D_FILL_VALUE_DEFAULT
 FILL_VALUE_USER_DEFINED = H5D_FILL_VALUE_USER_DEFINED
 
+
 # === Basic dataset operations ================================================
 
 @sync
@@ -119,6 +117,9 @@ cdef class DatasetID(ObjectID):
         dtype:  Numpy dtype representing the dataset type
         shape:  Numpy-style shape tuple representing the dataspace
         rank:   Integer giving dataset rank
+
+        Hashable: Yes, if not anonymous
+        Equality: HDF5 identity if not anonymous, otherwise Python default
     """
 
     property dtype:
@@ -186,7 +187,7 @@ cdef class DatasetID(ObjectID):
         cdef void* data
         cdef int oldflags
 
-        mtype = h5t.py_create(arr_obj.dtype)
+        mtype = py_create(arr_obj.dtype)
         check_numpy_write(arr_obj, -1)
 
         self_id = self.id
@@ -226,7 +227,7 @@ cdef class DatasetID(ObjectID):
         cdef void* data
         cdef int oldflags
 
-        mtype = h5t.py_create(arr_obj.dtype)
+        mtype = py_create(arr_obj.dtype)
         check_numpy_read(arr_obj, -1)
 
         self_id = self.id
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index bff07c2..c4dfb10 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -243,6 +243,9 @@ cdef class FileID(ObjectID):
 
         Properties:
         name:   File name on disk
+
+        Hashable: Yes, always
+        Equality: HDF5 object identity
     """
 
     property name:
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 7a0205d..d8ec0d3 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -18,7 +18,7 @@ include "config.pxi"
 include "sync.pxi"
 
 # Compile-time imports
-from h5 cimport init_hdf5, standard_richcmp
+from h5 cimport init_hdf5
 from utils cimport emalloc, efree
 from h5p cimport PropID, pdefault
 IF H5PY_18API:
@@ -260,6 +260,8 @@ cdef class GroupID(ObjectID):
         providing access to the H5L family of routines.  See the docs
         for h5py.h5l.LinkProxy for more information.
 
+        Hashable: Yes, unless anonymous
+        Equality: HDF5 object identity if not anonymous, or NotImplemented
     """
 
     IF H5PY_18API:
diff --git a/h5py/h5l.pyx b/h5py/h5l.pyx
index 0d39abd..8932364 100644
--- a/h5py/h5l.pyx
+++ b/h5py/h5l.pyx
@@ -9,7 +9,6 @@
 # $Date$
 # 
 #-
-from utils cimport pybool
 
 """
     API for the "H5L" family of link-related operations
@@ -36,6 +35,8 @@ cdef class LinkProxy(ObjectID):
         >>> g.links.exists("FooBar")
         False
 
+        Hashable: No
+        Equality: Undefined
     """
 
     def __cinit__(self, hid_t id_):
@@ -46,13 +47,19 @@ cdef class LinkProxy(ObjectID):
         # shared by both this object and the parent.
         H5Iinc_ref(self.id)
 
+    def __richcmp__(self, object other, int how):
+        return NotImplemented
+
+    def __hash__(self):
+        raise TypeError("Link proxies are unhashable; use the parent group instead.")
+
     @sync
     def exists(self, char* name):
         """ (STRING name) => BOOL
 
             Check if a link of the specified name exists in this group.
         """
-        return pybool(H5Lexists(self.id, name, H5P_DEFAULT))
+        return <bint>(H5Lexists(self.id, name, H5P_DEFAULT))
 
 
 
diff --git a/h5py/h5o.pyx b/h5py/h5o.pyx
index 8a03b1e..c97c894 100644
--- a/h5py/h5o.pyx
+++ b/h5py/h5o.pyx
@@ -17,7 +17,7 @@ include "sync.pxi"
 # built with API compatibility level below 1.8.
 
 # Pyrex compile-time imports
-from h5 cimport init_hdf5
+from h5 cimport init_hdf5, ObjectID
 from h5f cimport wrap_identifier
 
 # Initialization
@@ -47,6 +47,7 @@ cdef class ObjInfo:
         newcopy.infostruct = self.infostruct
         return newcopy
 
+ at sync
 def get_info(ObjectID obj not None):
     """ (ObjectID obj) => ObjInfo
     """
@@ -91,7 +92,7 @@ cdef herr_t visit_cb(hid_t obj, char* name, H5O_info_t *info, void* data):
 
     return 0
  
-
+ at sync
 def visit(ObjectID obj not None, object func, int idx_type=H5_INDEX_NAME,
           int order=H5_ITER_NATIVE):
     """ (ObjectID obj, CALLABLE func, INT idx_type=, INT order=)
diff --git a/h5py/h5p.pyx b/h5py/h5p.pyx
index 1bb31c4..41b22bf 100644
--- a/h5py/h5p.pyx
+++ b/h5py/h5p.pyx
@@ -19,33 +19,20 @@ include "config.pxi"
 include "sync.pxi"
 
 # Compile-time imports
-from h5 cimport init_hdf5, standard_richcmp
+from h5 cimport init_hdf5
 from utils cimport  require_tuple, convert_dims, convert_tuple, \
                     emalloc, efree, require_list, \
                     check_numpy_write, check_numpy_read
 from numpy cimport ndarray, import_array
-from h5t cimport TypeID
+from h5t cimport TypeID, py_create
 
 # Initialization
 init_hdf5()
 import_array()
 
-# Runtime imports
-import h5t
 
 # === C API ===================================================================
 
-cdef class PropClassID(PropID):
-
-    def __richcmp__(self, object other, int how):
-        return standard_richcmp(self, other, how)
-
-    def __hash__(self):
-        """ Since classes are library-created and immutable, they are uniquely
-            identified by their HDF5 identifiers.
-        """
-        return hash(self.id)
-
 cdef hid_t pdefault(PropID pid):
 
     if pid is None:
@@ -97,6 +84,7 @@ DEFAULT = None   # In the HDF5 header files this is actually 0, which is an
 
 # === Property list functional API ============================================
 
+ at sync
 def create(PropClassID cls not None):
     """ (PropClassID cls) => PropID
     
@@ -118,6 +106,7 @@ cdef class PropID(ObjectID):
         Base class for all property lists and classes
     """
 
+    @sync
     def equal(self, PropID plist not None):
         """ (PropID plist) => BOOL
 
@@ -125,13 +114,49 @@ cdef class PropID(ObjectID):
         """
         return <bint>(H5Pequal(self.id, plist.id))
 
+    def __richcmp__(self, object other, int how):
+        cdef bint truthval = 0
+        if how != 2 and how != 3:
+            return NotImplemented
+        if type(self) == type(other):
+            truthval = self.equal(other)
+        
+        if how == 2:
+            return truthval
+        return not truthval
+
+    def __hash__(self):
+        raise TypeError("Property lists are unhashable")
+
+cdef class PropClassID(PropID):
+
+    """
+        An HDF5 property list class.
+
+        Hashable: Yes, by identifier
+        Equality: Logical H5P comparison
+    """
+
+    def __richcmp__(self, object other, int how):
+        return PropID.__richcmp__(self, other, how)
+
+    def __hash__(self):
+        """ Since classes are library-created and immutable, they are uniquely
+            identified by their HDF5 identifiers.
+        """
+        return hash(self.id)
+
 cdef class PropInstanceID(PropID):
 
     """
         Base class for property list instance objects.  Provides methods which
         are common across all HDF5 property list classes.
+
+        Hashable: No
+        Equality: Logical H5P comparison
     """
 
+    @sync
     def copy(self):
         """ () => PropList newid
 
@@ -139,6 +164,7 @@ cdef class PropInstanceID(PropID):
         """
         return type(self)(H5Pcopy(self.id))
 
+    @sync
     def _close(self):
         """ ()
     
@@ -148,6 +174,7 @@ cdef class PropInstanceID(PropID):
         """
         H5Pclose(self.id)
 
+    @sync
     def get_class(self):
         """ () => PropClassID
 
@@ -164,6 +191,7 @@ cdef class PropFCID(PropInstanceID):
         File creation property list.
     """
 
+    @sync
     def get_version(self):
         """ () => TUPLE version_info
 
@@ -185,7 +213,7 @@ cdef class PropFCID(PropInstanceID):
 
         return (super_, freelist, stab, shhdr)
 
-
+    @sync
     def set_userblock(self, hsize_t size):
         """ (INT/LONG size)
 
@@ -194,6 +222,7 @@ cdef class PropFCID(PropInstanceID):
         """
         H5Pset_userblock(self.id, size)
 
+    @sync
     def get_userblock(self):
         """ () => LONG size
 
@@ -203,6 +232,7 @@ cdef class PropFCID(PropInstanceID):
         H5Pget_userblock(self.id, &size)
         return size
 
+    @sync
     def set_sizes(self, size_t addr, size_t size):
         """ (UINT addr, UINT size)
 
@@ -211,6 +241,7 @@ cdef class PropFCID(PropInstanceID):
         """
         H5Pset_sizes(self.id, addr, size)
 
+    @sync
     def get_sizes(self):
         """ () => TUPLE sizes
 
@@ -225,6 +256,7 @@ cdef class PropFCID(PropInstanceID):
         H5Pget_sizes(self.id, &addr, &size)
         return (addr, size)
 
+    @sync
     def set_sym_k(self, unsigned int ik, unsigned int lk):
         """ (INT ik, INT lk)
 
@@ -232,6 +264,7 @@ cdef class PropFCID(PropInstanceID):
         """
         H5Pset_sym_k(self.id, ik, lk)
 
+    @sync
     def get_sym_k(self):
         """ () => TUPLE settings
 
@@ -243,6 +276,7 @@ cdef class PropFCID(PropInstanceID):
         H5Pget_sym_k(self.id, &ik, &lk)
         return (ik, lk)
 
+    @sync
     def set_istore_k(self, unsigned int ik):
         """ (UINT ik)
 
@@ -250,6 +284,7 @@ cdef class PropFCID(PropInstanceID):
         """
         H5Pset_istore_k(self.id, ik)
     
+    @sync
     def get_istore_k(self):
         """ () => UINT ik
 
@@ -267,6 +302,7 @@ cdef class PropDCID(PropInstanceID):
         Dataset creation property list.
     """
 
+    @sync
     def set_layout(self, int layout_code):
         """ (INT layout_code)
 
@@ -277,6 +313,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Pset_layout(self.id, layout_code)
     
+    @sync
     def get_layout(self):
         """ () => INT layout_code
 
@@ -287,7 +324,7 @@ cdef class PropDCID(PropInstanceID):
         """
         return <int>H5Pget_layout(self.id)
 
-
+    @sync
     def set_chunk(self, object chunksize):
         """ (TUPLE chunksize)
 
@@ -307,7 +344,8 @@ cdef class PropDCID(PropInstanceID):
             H5Pset_chunk(self.id, rank, dims)
         finally:
             efree(dims)
-    
+
+    @sync
     def get_chunk(self):
         """ () => TUPLE chunk_dimensions
 
@@ -327,6 +365,7 @@ cdef class PropDCID(PropInstanceID):
         finally:
             efree(dims)
 
+    @sync
     def set_fill_value(self, ndarray value not None):
         """ (NDARRAY value)
 
@@ -337,9 +376,10 @@ cdef class PropDCID(PropInstanceID):
         cdef TypeID tid
 
         check_numpy_read(value, -1)
-        tid = h5t.py_create(value.dtype)        
+        tid = py_create(value.dtype)        
         H5Pset_fill_value(self.id, tid.id, value.data)
 
+    @sync
     def get_fill_value(self, ndarray value not None):
         """ (NDARRAY value)
 
@@ -350,9 +390,10 @@ cdef class PropDCID(PropInstanceID):
         cdef TypeID tid
 
         check_numpy_write(value, -1)
-        tid = h5t.py_create(value.dtype)
+        tid = py_create(value.dtype)
         H5Pget_fill_value(self.id, tid.id, value.data)
 
+    @sync
     def set_fill_time(self, int fill_time):
         """ (INT fill_time)
 
@@ -366,6 +407,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Pset_fill_time(self.id, <H5D_fill_time_t>fill_time)
 
+    @sync
     def get_fill_time(self):
         """ () => INT
 
@@ -381,8 +423,10 @@ cdef class PropDCID(PropInstanceID):
         H5Pget_fill_time(self.id, &fill_time)
         return <int>fill_time
 
+
     # === Filter functions ====================================================
     
+    @sync
     def set_deflate(self, unsigned int level=5):
         """ (UINT level=5)
 
@@ -390,7 +434,8 @@ cdef class PropDCID(PropInstanceID):
             Valid levels are 0-9, default is 5.
         """
         H5Pset_deflate(self.id, level)
-    
+
+    @sync
     def set_fletcher32(self):
         """ ()
 
@@ -398,6 +443,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Pset_fletcher32(self.id)
 
+    @sync
     def set_shuffle(self):
         """ ()
 
@@ -406,6 +452,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Pset_shuffle(self.id)
 
+    @sync
     def set_szip(self, unsigned int options, unsigned int pixels_per_block):
         """ (UINT options, UINT pixels_per_block)
 
@@ -414,6 +461,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Pset_szip(self.id, options, pixels_per_block)
 
+    @sync
     def get_nfilters(self):
         """ () => INT
 
@@ -421,6 +469,7 @@ cdef class PropDCID(PropInstanceID):
         """
         return H5Pget_nfilters(self.id)
 
+    @sync
     def set_filter(self, int filter_code, unsigned int flags=0, object values=None):
         """ (INT filter_code, UINT flags=0, TUPLE values=None)
 
@@ -458,6 +507,7 @@ cdef class PropDCID(PropInstanceID):
         finally:
             efree(cd_values)
 
+    @sync
     def all_filters_avail(self):
         """ () => BOOL
 
@@ -466,6 +516,7 @@ cdef class PropDCID(PropInstanceID):
         """
         return <bint>(H5Pall_filters_avail(self.id))
 
+    @sync
     def get_filter(self, int filter_idx):
         """ (UINT filter_idx) => TUPLE filter_info
 
@@ -499,6 +550,7 @@ cdef class PropDCID(PropInstanceID):
 
         return (filter_code, flags, tuple(vlist), name)
 
+    @sync
     def _has_filter(self, int filter_code):
         """ (INT filter_code)
 
@@ -513,6 +565,7 @@ cdef class PropDCID(PropInstanceID):
                 return True
         return False
 
+    @sync
     def get_filter_by_id(self, int filter_code):
         """ (INT filter_code) => TUPLE filter_info or None
 
@@ -549,6 +602,7 @@ cdef class PropDCID(PropInstanceID):
 
         return (flags, tuple(vlist), name)
 
+    @sync
     def remove_filter(self, int filter_class):
         """ (INT filter_class)
 
@@ -557,6 +611,7 @@ cdef class PropDCID(PropInstanceID):
         """
         H5Premove_filter(self.id, <H5Z_filter_t>filter_class)
 
+    @sync
     def fill_value_defined(self):
         """ () => INT fill_status
 
@@ -578,6 +633,7 @@ cdef class PropFAID(PropInstanceID):
         File access property list
     """
 
+    @sync
     def set_fclose_degree(self, int close_degree):
         """ (INT close_degree)
 
@@ -591,6 +647,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_fclose_degree(self.id, <H5F_close_degree_t>close_degree)
 
+    @sync
     def get_fclose_degree(self):
         """ () => INT close_degree
 
@@ -606,6 +663,7 @@ cdef class PropFAID(PropInstanceID):
         H5Pget_fclose_degree(self.id, &deg)
         return deg
 
+    @sync
     def set_fapl_core(self, size_t increment=1024*1024, hbool_t backing_store=0):
         """ (UINT increment=1M, BOOL backing_store=False)
 
@@ -616,6 +674,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_fapl_core(self.id, increment, backing_store)
 
+    @sync
     def get_fapl_core(self):
         """ () => TUPLE core_settings
 
@@ -630,6 +689,7 @@ cdef class PropFAID(PropInstanceID):
         H5Pget_fapl_core(self.id, &increment, &backing_store)
         return (increment, <bint>(backing_store))
 
+    @sync
     def set_fapl_family(self, hsize_t memb_size, PropID memb_fapl=None):
         """ (UINT memb_size, PropFAID memb_fapl=None)
 
@@ -641,6 +701,7 @@ cdef class PropFAID(PropInstanceID):
         plist_id = pdefault(memb_fapl)
         H5Pset_fapl_family(self.id, memb_size, plist_id)
 
+    @sync
     def get_fapl_family(self):
         """ () => TUPLE info
 
@@ -660,6 +721,7 @@ cdef class PropFAID(PropInstanceID):
 
         return (msize, plist)
 
+    @sync
     def set_fapl_log(self, char* logfile, unsigned int flags, size_t buf_size):
         """ (STRING logfile, UINT flags, UINT buf_size)
 
@@ -668,6 +730,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_fapl_log(self.id, logfile, flags, buf_size)
 
+    @sync
     def set_fapl_sec2(self):
         """ ()
 
@@ -675,6 +738,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_fapl_sec2(self.id)
 
+    @sync
     def set_fapl_stdio(self):
         """ ()
 
@@ -682,6 +746,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_fapl_stdio(self.id)
 
+    @sync
     def get_driver(self):
         """ () => INT driver code
 
@@ -699,6 +764,7 @@ cdef class PropFAID(PropInstanceID):
         """
         return H5Pget_driver(self.id)
 
+    @sync
     def set_cache(self, int mdc, int rdcc, size_t rdcc_nbytes, double rdcc_w0):
         """ (INT mdc, INT rdcc, UINT rdcc_nbytes, DOUBLE rdcc_w0)
 
@@ -707,6 +773,7 @@ cdef class PropFAID(PropInstanceID):
         """
         H5Pset_cache(self.id, mdc, rdcc, rdcc_nbytes, rdcc_w0)
 
+    @sync
     def get_cache(self):
         """ () => TUPLE cache info
 
diff --git a/h5py/h5r.pyx b/h5py/h5r.pyx
index 88c53df..c8077fe 100644
--- a/h5py/h5r.pyx
+++ b/h5py/h5r.pyx
@@ -36,6 +36,7 @@ DATASET_REGION = H5R_DATASET_REGION
 
 # === Reference API ===========================================================
 
+ at sync
 def create(ObjectID loc not None, char* name, int ref_type, SpaceID space=None):
     """ (ObjectID loc, STRING name, INT ref_type, SpaceID space=None)
         => ReferenceObject ref
@@ -76,6 +77,7 @@ cdef class Reference:
         or a dataset region (DATASET_REGION).
     """
 
+    @sync
     def dereference(self, ObjectID id not None):
         """ (ObjectID id) => ObjectID obj_id
 
@@ -87,6 +89,7 @@ cdef class Reference:
         """
         return wrap_identifier(H5Rdereference(id.id, <H5R_type_t>self.typecode, &self.ref))
 
+    @sync
     def get_region(self, ObjectID id not None):
         """ (ObjectID id) => SpaceID dataspace_id
 
@@ -100,6 +103,7 @@ cdef class Reference:
         """
         return SpaceID(H5Rget_region(id.id, <H5R_type_t>self.typecode, &self.ref))
 
+    @sync
     def get_obj_type(self, ObjectID id not None):
         """ (ObjectID id) => INT obj_code
 
@@ -116,6 +120,7 @@ cdef class Reference:
         """
         return <int>H5Rget_obj_type(id.id, <H5R_type_t>self.typecode, &self.ref)
 
+    @nosync
     def __str__(self):
         if self.typecode == H5R_OBJECT:
             return "HDF5 object reference"
diff --git a/h5py/h5s.pyx b/h5py/h5s.pyx
index b9b4086..920ec92 100644
--- a/h5py/h5s.pyx
+++ b/h5py/h5s.pyx
@@ -22,7 +22,7 @@ from h5 cimport init_hdf5
 from utils cimport  require_tuple, require_list, convert_dims, convert_tuple, \
                     emalloc, efree, create_numpy_hsize, create_hsize_array
 from numpy cimport ndarray
-from python cimport PyString_FromStringAndSize
+from python_string cimport PyString_FromStringAndSize
 
 # Initialization
 init_hdf5()
@@ -65,6 +65,7 @@ SEL_ALL         = H5S_SEL_ALL
 
 # === Basic dataspace operations ==============================================
 
+ at sync
 def create(int class_code):
     """ (INT class_code) => SpaceID
 
@@ -109,6 +110,7 @@ def create_simple(object dims_tpl, object max_dims_tpl=None):
         efree(max_dims)
 
 IF H5PY_18API:
+    @sync
     def decode(buf):
         """ (STRING buf) => SpaceID
 
@@ -128,6 +130,9 @@ cdef class SpaceID(ObjectID):
 
         Properties:
         shape:  Numpy-style shape tuple with dimensions.
+
+        Hashable: No
+        Equality: Unimplemented
     """
 
     property shape:
@@ -136,6 +141,7 @@ cdef class SpaceID(ObjectID):
         def __get__(self):
             return self.get_simple_extent_dims()
 
+    @sync
     def _close(self):
         """ ()
 
@@ -145,6 +151,7 @@ cdef class SpaceID(ObjectID):
         """
         H5Sclose(self.id)
 
+    @sync
     def copy(self):
         """ () => SpaceID
 
@@ -152,7 +159,8 @@ cdef class SpaceID(ObjectID):
         """
         return SpaceID(H5Scopy(self.id))
 
-    IF H5PY_18API:
+    IF H5PY_18API:    
+        @sync
         def encode(self):
             """ () => STRING
 
@@ -177,9 +185,11 @@ cdef class SpaceID(ObjectID):
     IF H5PY_18API:
         # Enable pickling
 
+        @nosync
         def __reduce__(self):
             return (type(self), (-1,), self.encode())
 
+        @sync
         def __setstate__(self, state):
             cdef char* buf
             buf = state
@@ -187,6 +197,7 @@ cdef class SpaceID(ObjectID):
 
     # === Simple dataspaces ===================================================
 
+    @sync
     def is_simple(self):
         """ () => BOOL is_simple
 
@@ -195,6 +206,7 @@ cdef class SpaceID(ObjectID):
         """
         return <bint>(H5Sis_simple(self.id))
 
+    @sync
     def offset_simple(self, object offset=None):
         """ (TUPLE offset=None)
 
@@ -229,6 +241,7 @@ cdef class SpaceID(ObjectID):
         finally:
             efree(dims)
 
+    @sync
     def get_simple_extent_ndims(self):
         """ () => INT rank
             
@@ -236,6 +249,7 @@ cdef class SpaceID(ObjectID):
         """
         return H5Sget_simple_extent_ndims(self.id)
 
+    @sync
     def get_simple_extent_dims(self, int maxdims=0):
         """ (BOOL maxdims=False) => TUPLE shape
 
@@ -260,6 +274,7 @@ cdef class SpaceID(ObjectID):
         finally:
             efree(dims)
     
+    @sync
     def get_simple_extent_npoints(self):
         """ () => LONG npoints
 
@@ -267,6 +282,7 @@ cdef class SpaceID(ObjectID):
         """
         return H5Sget_simple_extent_npoints(self.id)
 
+    @sync
     def get_simple_extent_type(self):
         """ () => INT class_code
 
@@ -276,6 +292,7 @@ cdef class SpaceID(ObjectID):
 
     # === Extents =============================================================
 
+    @sync
     def extent_copy(self, SpaceID source not None):
         """ (SpaceID source)
 
@@ -284,6 +301,7 @@ cdef class SpaceID(ObjectID):
         """
         H5Sextent_copy(self.id, source.id)
 
+    @sync
     def set_extent_simple(self, object dims_tpl, object max_dims_tpl=None):
         """ (TUPLE dims_tpl, TUPLE max_dims_tpl=None)
 
@@ -318,6 +336,7 @@ cdef class SpaceID(ObjectID):
             efree(dims)
             efree(max_dims)
 
+    @sync
     def set_extent_none(self):
         """ ()
 
@@ -327,6 +346,7 @@ cdef class SpaceID(ObjectID):
 
     # === General selection operations ========================================
 
+    @sync
     def get_select_type(self):
         """ () => INT select_code
 
@@ -338,6 +358,7 @@ cdef class SpaceID(ObjectID):
         """
         return <int>H5Sget_select_type(self.id)
 
+    @sync
     def get_select_npoints(self):
         """ () => LONG npoints
 
@@ -346,6 +367,7 @@ cdef class SpaceID(ObjectID):
         """
         return H5Sget_select_npoints(self.id)
 
+    @sync
     def get_select_bounds(self):
         """ () => (TUPLE start, TUPLE end)
 
@@ -374,6 +396,7 @@ cdef class SpaceID(ObjectID):
             efree(start)
             efree(end)
 
+    @sync
     def select_all(self):
         """ ()
 
@@ -381,6 +404,7 @@ cdef class SpaceID(ObjectID):
         """
         H5Sselect_all(self.id)
 
+    @sync
     def select_none(self):
         """ ()
 
@@ -388,6 +412,7 @@ cdef class SpaceID(ObjectID):
         """
         H5Sselect_none(self.id)
 
+    @sync
     def select_valid(self):
         """ () => BOOL select_valid
             
@@ -398,6 +423,7 @@ cdef class SpaceID(ObjectID):
 
     # === Point selection functions ===========================================
 
+    @sync
     def get_select_elem_npoints(self):
         """ () => LONG npoints
 
@@ -405,6 +431,7 @@ cdef class SpaceID(ObjectID):
         """
         return H5Sget_select_elem_npoints(self.id)
 
+    @sync
     def get_select_elem_pointlist(self):
         """ () => NDARRAY elements_list
 
@@ -423,6 +450,7 @@ cdef class SpaceID(ObjectID):
 
         return buf
 
+    @sync
     def select_elements(self, object coords, int op=H5S_SELECT_SET):
         """ (SEQUENCE coords, INT op=SELECT_SET)
 
@@ -459,6 +487,7 @@ cdef class SpaceID(ObjectID):
 
     # === Hyperslab selection functions =======================================
 
+    @sync
     def get_select_hyper_nblocks(self):
         """ () => LONG nblocks
 
@@ -466,6 +495,7 @@ cdef class SpaceID(ObjectID):
         """
         return H5Sget_select_hyper_nblocks(self.id)
 
+    @sync
     def get_select_hyper_blocklist(self):
         """ () => NDARRAY hyperslab_blocks
 
@@ -492,6 +522,7 @@ cdef class SpaceID(ObjectID):
 
         return buf
 
+    @sync
     def select_hyperslab(self, object start, object count, object stride=None, 
                          object block=None, int op=H5S_SELECT_SET):
         """ (TUPLE start, TUPLE count, TUPLE stride=None, TUPLE block=None, 
diff --git a/h5py/h5t.pxd b/h5py/h5t.pxd
index 1b8076c..448cc87 100644
--- a/h5py/h5t.pxd
+++ b/h5py/h5t.pxd
@@ -66,7 +66,15 @@ cdef class TypeEnumID(TypeCompositeID):
 cdef class TypeCompoundID(TypeCompositeID):
     pass
 
+# === C API for other modules =================================================
+
 cdef object typewrap(hid_t id_)
+cpdef object py_create(object dtype, object enum_vals=*)
+
+
+
+
+
 
 
 
diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 9b1b994..81c2279 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -35,8 +35,8 @@
         fields. When a two-element compound type is encountered in a file with
         compatible field names, it is treated as a complex type.
 
-        The names for these fields are taken from a global, which can be set
-        via the module function py_complex_names(realname, imgname).
+        The names for complex types are set as a property on the global
+        configuration object, available at h5.config.
 
     3. Enumerated types
 
@@ -61,9 +61,9 @@ include "config.pxi"
 include "sync.pxi"
 
 # Pyrex compile-time imports
-from h5 cimport init_hdf5, PHIL, get_phil
+from h5 cimport init_hdf5, PHIL, get_phil, H5PYConfig
 from numpy cimport dtype, ndarray
-from python cimport PyString_FromStringAndSize
+from python_string cimport PyString_FromStringAndSize
 
 from utils cimport  emalloc, efree, \
                     create_ieee_complex64, create_ieee_complex128, \
@@ -74,10 +74,12 @@ init_hdf5()
 
 # Runtime imports
 import sys
+import h5
 
+cdef H5PYConfig cfg = h5.config
 
 # === Custom C API ============================================================
-    
+
 cdef object typewrap(hid_t id_):
 
     cdef H5T_class_t cls
@@ -118,7 +120,6 @@ cdef object lockid(hid_t id_in):
 
 # === Public constants and data structures ====================================
 
-_complex_names = ('r','i')
 
 # Enumeration H5T_class_t
 NO_CLASS  = H5T_NO_CLASS
@@ -225,28 +226,14 @@ STD_REF_DSETREG = lockid(H5T_STD_REF_DSETREG)
 C_S1 = lockid(H5T_C_S1)
 FORTRAN_S1 = lockid(H5T_FORTRAN_S1)
 
-# Map array protocol strings to their HDF5 atomic equivalents
-# Not sure why LE/BE versions of I8/U8 exist; I'll include them anyway.
-_code_map = {
-    "<i1": STD_I8LE, "<i2": STD_I16LE, "<i4": STD_I32LE, "<i8": STD_I64LE,
-    ">i1": STD_I8BE, ">i2": STD_I16BE, ">i4": STD_I32BE, ">i8": STD_I64BE,
-    "|i1": NATIVE_INT8, "|u1": NATIVE_UINT8, 
-    "<u1": STD_U8LE, "<u2": STD_U16LE, "<u4": STD_U32LE, "<u8": STD_U64LE,
-    ">u1": STD_U8BE, ">u2": STD_U16BE, ">u4": STD_U32BE, ">u8": STD_U64BE,
-    "<f4": IEEE_F32LE, "<f8": IEEE_F64LE, ">f4": IEEE_F32BE, ">f8": IEEE_F64BE 
-            }
-
-# Intermediate mapping which takes complex types to their components
-_complex_map = { "<c8": IEEE_F32LE, "<c16": IEEE_F64LE, 
-                 ">c8": IEEE_F32BE, ">c16": IEEE_F64BE }
-
-_order_map = { H5T_ORDER_NONE: '|', H5T_ORDER_LE: '<', H5T_ORDER_BE: '>'}
-_sign_map  = { H5T_SGN_NONE: 'u', H5T_SGN_2: 'i' }
-
+# Translation tables for HDF5 -> NumPy dtype conversion
+cdef dict _order_map = { H5T_ORDER_NONE: '|', H5T_ORDER_LE: '<', H5T_ORDER_BE: '>'}
+cdef dict _sign_map  = { H5T_SGN_NONE: 'u', H5T_SGN_2: 'i' }
 
 
 # === General datatype operations =============================================
 
+ at sync
 def create(int classtype, size_t size):
     """ (INT classtype, UINT size) => TypeID
         
@@ -260,6 +247,7 @@ def create(int classtype, size_t size):
 
     return typewrap(H5Tcreate(<H5T_class_t>classtype, size))
 
+ at sync
 def open(ObjectID group not None, char* name):
     """ (ObjectID group, STRING name) => TypeID
 
@@ -267,6 +255,7 @@ def open(ObjectID group not None, char* name):
     """
     return typewrap(H5Topen(group.id, name))
 
+ at sync
 def array_create(TypeID base not None, object dims_tpl):
     """ (TypeID base, TUPLE dimensions)
 
@@ -288,6 +277,7 @@ def array_create(TypeID base not None, object dims_tpl):
     finally:
         efree(dims)
 
+ at sync
 def enum_create(TypeID base not None):
     """ (TypeID base) => TypeID
 
@@ -295,6 +285,7 @@ def enum_create(TypeID base not None):
     """
     return typewrap(H5Tenum_create(base.id))
 
+ at sync
 def vlen_create(TypeID base not None):
     """ (TypeID base) => TypeID
 
@@ -306,6 +297,7 @@ def vlen_create(TypeID base not None):
     return typewrap(H5Tvlen_create(base.id))
 
 IF H5PY_18API:
+    @sync
     def decode(buf):
         """ (STRING buf) => TypeID
 
@@ -322,13 +314,50 @@ cdef class TypeID(ObjectID):
 
     """
         Base class for type identifiers (implements common operations)
+
+        Hashable: If locked and committed; in HDF5 1.8.X, also if only locked
+        Equality: Logical H5T comparison
     """
 
+    def __hash__(self):
+        try:
+            # Try to use object header first
+            return ObjectID.__hash__(self)
+        except TypeError:
+            # It's a transient type object
+            IF H5PY_18API:
+                if self._locked:
+                    self._hash = hash(self.encode())
+                else:
+                    raise TypeError("Only locked or committed types can be hashed")
+            ELSE:
+                raise TypeError("Only committed types can be hashed")
+
+        return self._hash
+
+    def __richcmp__(self, object other, int how):
+        cdef bint truthval = 0
+        if how != 2 and how != 3:
+            return NotImplemented
+        if isinstance(other, TypeID):
+            truthval = self.equal(other)
+        
+        if how == 2:
+            return truthval
+        return not truthval
+
     def __copy__(self):
         cdef TypeID cpy
         cpy = ObjectID.__copy__(self)
         return cpy
 
+    def __repr__(self):
+        try:
+            dstr = " "+self.dtype.str
+        except Exception:
+            dstr = ""
+        return ObjectID.__repr__(self)+dstr
+
     property dtype:
         """ A Numpy-style dtype object representing this object.
         """
@@ -336,16 +365,9 @@ cdef class TypeID(ObjectID):
             return self.py_dtype()
 
     cdef object py_dtype(self):
-        raise NotImplementedError("Don't know how to convert %s objects to Numpy" % self.__class__.__name__)
-
-    def __repr__(self):
-        try:
-            dts = str(self.dtype)
-        except:
-            dts = "(Numpy type unknown)"
-
-        return str(self)+" "+dts
+        raise TypeError("No NumPy equivalent for %s exists" % self.__class__.__name__)
 
+    @sync
     def commit(self, ObjectID group not None, char* name):
         """ (ObjectID group, STRING name)
 
@@ -353,6 +375,7 @@ cdef class TypeID(ObjectID):
         """
         H5Tcommit(group.id, name, self.id)
 
+    @sync
     def committed(self):
         """ () => BOOL is_comitted
 
@@ -360,6 +383,7 @@ cdef class TypeID(ObjectID):
         """
         return <bint>(H5Tcommitted(self.id))
 
+    @sync
     def copy(self):
         """ () => TypeID
 
@@ -367,14 +391,16 @@ cdef class TypeID(ObjectID):
         """
         return typewrap(H5Tcopy(self.id))
 
+    @sync
     def equal(self, TypeID typeid):
         """ (TypeID typeid) => BOOL
 
-            Test whether two identifiers refer to the same datatype.  Seems
-            to perform a logical comparison.
+            Logical comparison between datatypes.  Also called by
+            Python's "==" operator.
         """
         return <bint>(H5Tequal(self.id, typeid.id))
 
+    @sync
     def lock(self):
         """ ()
 
@@ -384,6 +410,7 @@ cdef class TypeID(ObjectID):
         H5Tlock(self.id)
         self._locked = 1
 
+    @sync
     def get_class(self):
         """ () => INT classcode
 
@@ -391,6 +418,7 @@ cdef class TypeID(ObjectID):
         """
         return <int>H5Tget_class(self.id)
 
+    @sync
     def set_size(self, size_t size):
         """ (UINT size)
 
@@ -398,6 +426,7 @@ cdef class TypeID(ObjectID):
         """
         H5Tset_size(self.id, size)
 
+    @sync
     def get_size(self):
         """ () => INT size
 
@@ -405,6 +434,7 @@ cdef class TypeID(ObjectID):
         """
         return H5Tget_size(self.id)
 
+    @sync
     def get_super(self):
         """ () => TypeID
 
@@ -412,6 +442,7 @@ cdef class TypeID(ObjectID):
         """
         return typewrap(H5Tget_super(self.id))
 
+    @sync
     def detect_class(self, int classtype):
         """ (INT classtype) => BOOL class_is_present
 
@@ -420,6 +451,7 @@ cdef class TypeID(ObjectID):
         """
         return <bint>(H5Tdetect_class(self.id, <H5T_class_t>classtype))
 
+    @sync
     def _close(self):
         """ Close this datatype.  If it's locked, nothing happens.
 
@@ -430,6 +462,7 @@ cdef class TypeID(ObjectID):
             H5Tclose(self.id)
 
     IF H5PY_18API:
+        @sync
         def encode(self):
             """ () => STRING
 
@@ -458,11 +491,13 @@ cdef class TypeID(ObjectID):
         def __reduce__(self):
             return (type(self), (-1,), self.encode())
 
+        @sync
         def __setstate__(self, state):
             cdef char* buf
             buf = state
             self.id = H5Tdecode(<unsigned char*>buf)
 
+
 # === Top-level classes (inherit directly from TypeID) ========================
 
 cdef class TypeArrayID(TypeID):
@@ -471,6 +506,7 @@ cdef class TypeArrayID(TypeID):
         Represents an array datatype
     """
 
+    @sync
     def get_array_ndims(self):
         """ () => INT rank
 
@@ -478,6 +514,7 @@ cdef class TypeArrayID(TypeID):
         """
         return H5Tget_array_ndims(self.id)
 
+    @sync
     def get_array_dims(self):
         """ () => TUPLE dimensions
 
@@ -513,6 +550,7 @@ cdef class TypeOpaqueID(TypeID):
         Represents an opaque type
     """
 
+    @sync
     def set_tag(self, char* tag):
         """ (STRING tag)
 
@@ -521,6 +559,7 @@ cdef class TypeOpaqueID(TypeID):
         """
         H5Tset_tag(self.id, tag)
 
+    @sync
     def get_tag(self):
         """ () => STRING tag
 
@@ -547,6 +586,7 @@ cdef class TypeStringID(TypeID):
         String datatypes, both fixed and vlen.
     """
 
+    @sync
     def is_variable_str(self):
         """ () => BOOL is_variable
 
@@ -556,6 +596,7 @@ cdef class TypeStringID(TypeID):
         """
         return <bint>(H5Tis_variable_str(self.id))
 
+    @sync
     def get_cset(self):
         """ () => INT character_set
 
@@ -564,6 +605,7 @@ cdef class TypeStringID(TypeID):
         """
         return <int>H5Tget_cset(self.id)
 
+    @sync
     def set_cset(self, int cset):
         """ (INT character_set)
 
@@ -572,6 +614,7 @@ cdef class TypeStringID(TypeID):
         """
         H5Tset_cset(self.id, <H5T_cset_t>cset)
 
+    @sync
     def get_strpad(self):
         """ () => INT padding_type
 
@@ -582,6 +625,7 @@ cdef class TypeStringID(TypeID):
         """
         return <int>H5Tget_strpad(self.id)
 
+    @sync
     def set_strpad(self, int pad):
         """ (INT pad)
 
@@ -595,7 +639,7 @@ cdef class TypeStringID(TypeID):
     cdef object py_dtype(self):
         # Numpy translation function for string types
         if self.is_variable_str():
-            raise NotImplementedError("Variable-length strings are not supported.")
+            raise TypeError("Variable-length strings are not supported.")
 
         return dtype("|S" + str(self.get_size()))
 
@@ -635,6 +679,7 @@ cdef class TypeAtomicID(TypeID):
         Base class for atomic datatypes (float or integer)
     """
 
+    @sync
     def get_order(self):
         """ () => INT order
 
@@ -644,6 +689,7 @@ cdef class TypeAtomicID(TypeID):
         """
         return <int>H5Tget_order(self.id)
 
+    @sync
     def set_order(self, int order):
         """ (INT order)
 
@@ -653,6 +699,7 @@ cdef class TypeAtomicID(TypeID):
         """
         H5Tset_order(self.id, <H5T_order_t>order)
 
+    @sync
     def get_precision(self):
         """ () => UINT precision
 
@@ -660,6 +707,7 @@ cdef class TypeAtomicID(TypeID):
         """
         return H5Tget_precision(self.id)
 
+    @sync
     def set_precision(self, size_t precision):
         """ (UINT precision)
             
@@ -667,6 +715,7 @@ cdef class TypeAtomicID(TypeID):
         """
         H5Tset_precision(self.id, precision)
 
+    @sync
     def get_offset(self):
         """ () => INT offset
 
@@ -674,6 +723,7 @@ cdef class TypeAtomicID(TypeID):
         """
         return H5Tget_offset(self.id)
 
+    @sync
     def set_offset(self, size_t offset):
         """ (UINT offset)
 
@@ -681,6 +731,7 @@ cdef class TypeAtomicID(TypeID):
         """
         H5Tset_offset(self.id, offset)
 
+    @sync
     def get_pad(self):
         """ () => (INT lsb_pad_code, INT msb_pad_code)
 
@@ -694,6 +745,7 @@ cdef class TypeAtomicID(TypeID):
         H5Tget_pad(self.id, &lsb, &msb)
         return (<int>lsb, <int>msb)
 
+    @sync
     def set_pad(self, int lsb, int msb):
         """ (INT lsb_pad_code, INT msb_pad_code)
 
@@ -711,6 +763,7 @@ cdef class TypeIntegerID(TypeAtomicID):
         Integer atomic datatypes
     """
 
+    @sync
     def get_sign(self):
         """ () => INT sign
 
@@ -720,6 +773,7 @@ cdef class TypeIntegerID(TypeAtomicID):
         """
         return <int>H5Tget_sign(self.id)
 
+    @sync
     def set_sign(self, int sign):
         """ (INT sign)
 
@@ -740,6 +794,7 @@ cdef class TypeFloatID(TypeAtomicID):
         Floating-point atomic datatypes
     """
 
+    @sync
     def get_fields(self):
         """ () => TUPLE field_info
 
@@ -755,6 +810,7 @@ cdef class TypeFloatID(TypeAtomicID):
         H5Tget_fields(self.id, &spos, &epos, &esize, &mpos, &msize)
         return (spos, epos, esize, mpos, msize)
 
+    @sync
     def set_fields(self, size_t spos, size_t epos, size_t esize, 
                           size_t mpos, size_t msize):
         """ (UINT spos, UINT epos, UINT esize, UINT mpos, UINT msize)
@@ -764,6 +820,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         H5Tset_fields(self.id, spos, epos, esize, mpos, msize)
 
+    @sync
     def get_ebias(self):
         """ () => UINT ebias
 
@@ -771,6 +828,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         return H5Tget_ebias(self.id)
 
+    @sync
     def set_ebias(self, size_t ebias):
         """ (UINT ebias)
 
@@ -778,6 +836,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         H5Tset_ebias(self.id, ebias)
 
+    @sync
     def get_norm(self):
         """ () => INT normalization_code
 
@@ -788,6 +847,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         return <int>H5Tget_norm(self.id)
 
+    @sync
     def set_norm(self, int norm):
         """ (INT normalization_code)
 
@@ -798,6 +858,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         H5Tset_norm(self.id, <H5T_norm_t>norm)
 
+    @sync
     def get_inpad(self):
         """ () => INT pad_code
 
@@ -808,6 +869,7 @@ cdef class TypeFloatID(TypeAtomicID):
         """
         return <int>H5Tget_inpad(self.id)
 
+    @sync
     def set_inpad(self, int pad_code):
         """ (INT pad_code)
 
@@ -832,6 +894,7 @@ cdef class TypeCompositeID(TypeID):
         Base class for enumerated and compound types.
     """
 
+    @sync
     def get_nmembers(self):
         """ () => INT number_of_members
 
@@ -839,6 +902,7 @@ cdef class TypeCompositeID(TypeID):
         """
         return H5Tget_nmembers(self.id)
 
+    @sync
     def get_member_name(self, int member):
         """ (INT member) => STRING name
         
@@ -860,6 +924,7 @@ cdef class TypeCompositeID(TypeID):
 
         return pyname
 
+    @sync
     def get_member_index(self, char* name):
         """ (STRING name) => INT index
 
@@ -876,6 +941,7 @@ cdef class TypeCompoundID(TypeCompositeID):
     """
 
 
+    @sync
     def get_member_class(self, int member):
         """ (INT member) => INT class
 
@@ -887,6 +953,7 @@ cdef class TypeCompoundID(TypeCompositeID):
         return H5Tget_member_class(self.id, member)
 
 
+    @sync
     def get_member_offset(self, int member):
         """ (INT member) => INT offset
 
@@ -897,6 +964,7 @@ cdef class TypeCompoundID(TypeCompositeID):
             raise ValueError("Member index must be non-negative.")
         return H5Tget_member_offset(self.id, member)
 
+    @sync
     def get_member_type(self, int member):
         """ (INT member) => TypeID
 
@@ -907,6 +975,7 @@ cdef class TypeCompoundID(TypeCompositeID):
             raise ValueError("Member index must be non-negative.")
         return typewrap(H5Tget_member_type(self.id, member))
 
+    @sync
     def insert(self, char* name, size_t offset, TypeID field not None):
         """ (STRING name, UINT offset, TypeID field)
 
@@ -916,6 +985,7 @@ cdef class TypeCompoundID(TypeCompositeID):
         """
         H5Tinsert(self.id, name, offset, field.id)
 
+    @sync
     def pack(self):
         """ ()
 
@@ -943,9 +1013,9 @@ cdef class TypeCompoundID(TypeCompositeID):
 
 
         # 1. Check if it should be converted to a complex number
-        if len(field_names) == 2                     and \
-            tuple(field_names) == _complex_names     and \
-            field_types[0] == field_types[1]         and \
+        if len(field_names) == 2                                and \
+            tuple(field_names) == (cfg._r_name, cfg._i_name)    and \
+            field_types[0] == field_types[1]                    and \
             field_types[0].kind == 'f':
 
             bstring = field_types[0].str
@@ -988,6 +1058,7 @@ cdef class TypeEnumID(TypeCompositeID):
         finally:
             H5Tclose(basetype)
 
+    @sync
     def enum_insert(self, char* name, long long value):
         """ (STRING name, INT/LONG value)
 
@@ -1002,6 +1073,7 @@ cdef class TypeEnumID(TypeCompositeID):
         self.enum_convert(&buf, 0)
         H5Tenum_insert(self.id, name, &buf)
 
+    @sync
     def enum_nameof(self, long long value):
         """ (LLONG value) => STRING name
 
@@ -1020,6 +1092,7 @@ cdef class TypeEnumID(TypeCompositeID):
         retstring = name
         return retstring
 
+    @sync
     def enum_valueof(self, char* name):
         """ (STRING name) => LONG value
 
@@ -1031,6 +1104,7 @@ cdef class TypeEnumID(TypeCompositeID):
         self.enum_convert(&buf, 1)
         return buf
 
+    @sync
     def get_member_value(self, int idx):
         """ (UINT index) => LONG value
 
@@ -1057,30 +1131,18 @@ cdef class TypeEnumID(TypeCompositeID):
 
 # === Python extension functions ==============================================
 
-def py_complex_names(object realname=None, object imgname=None, reset=False):
-    """ (STRING realname=None, STRING imgname=None, reset=False)
-
-        Set the real and imaginary strings used to translate complex
-        numbers to and from HDF5 compound types.
-
-        Both realname and imgname must be supplied, or both can be omitted to
-        disable conversion completely.  Call with reset=True to reset to the
-        default pair ('r','i').
-    """
-    global _complex_names
-    if not ((realname is None and imgname is None) or \
-            (isinstance(realname, str) and isinstance(imgname, str))):
-        raise ValueError("Realname and imgname must both be specified, or both omitted.")
+# Map array protocol strings to their HDF5 atomic equivalents
+# This only works for integers (signed and unsigned) and floats
+cdef dict _code_map = {
+    "<i1": STD_I8LE, "<i2": STD_I16LE, "<i4": STD_I32LE, "<i8": STD_I64LE,
+    ">i1": STD_I8BE, ">i2": STD_I16BE, ">i4": STD_I32BE, ">i8": STD_I64BE,
+    "|i1": NATIVE_INT8, "|u1": NATIVE_UINT8, 
+    "<u1": STD_U8LE, "<u2": STD_U16LE, "<u4": STD_U32LE, "<u8": STD_U64LE,
+    ">u1": STD_U8BE, ">u2": STD_U16BE, ">u4": STD_U32BE, ">u8": STD_U64BE,
+    "<f4": IEEE_F32LE, "<f8": IEEE_F64LE, ">f4": IEEE_F32BE, ">f8": IEEE_F64BE 
+            }
 
-    if reset:
-        _complex_names = ('r','i')
-    else:
-        if realname is None:
-            _complex_names = None
-        else:
-            _complex_names = (realname, imgname)
-    
-def py_create(object dtype_in, enum=None):
+cpdef object py_create(object dtype_in, object enum_vals=None):
     """ (OBJECT dtype_in, DICT enum=None) => TypeID
 
         Given a Numpy dtype object, generate a byte-for-byte memory-compatible
@@ -1124,12 +1186,12 @@ def py_create(object dtype_in, enum=None):
             otype.insert(name, offset, tmp)
 
     # Enums may be created out of integer types
-    elif (kind == c'u' or kind == c'i') and enum is not None:
+    elif (kind == c'u' or kind == c'i') and enum_vals is not None:
 
         otype = enum_create(_code_map[dt.str])
 
-        for key in sorted(enum):
-            otype.enum_insert(key, enum[key])
+        for key in sorted(enum_vals):
+            otype.enum_insert(key, enum_vals[key])
 
     # Integers and floats map directly to HDF5 atomic types
     elif kind == c'u' or kind == c'i'or kind == c'f':
@@ -1139,13 +1201,10 @@ def py_create(object dtype_in, enum=None):
     # Complex numbers are stored as HDF5 structs, with names defined at runtime
     elif kind == c'c':
 
-        if _complex_names is None:
-            raise ValueError("Complex conversion is currently disabled.  Use py_complex_names to re-enable.")
-
         if length == 8:
-            otype = typewrap(create_ieee_complex64(byteorder, _complex_names[0], _complex_names[1]))
+            otype = typewrap(create_ieee_complex64(byteorder, cfg._r_name, cfg._i_name))
         elif length == 16:
-            otype = typewrap(create_ieee_complex128(byteorder, _complex_names[0], _complex_names[1]))
+            otype = typewrap(create_ieee_complex128(byteorder, cfg._r_name, cfg._i_name))
         else:
             raise ValueError("Unsupported length %d for complex dtype: %s" % (length, repr(dt)))
 
@@ -1169,11 +1228,6 @@ def py_create(object dtype_in, enum=None):
     else:
         raise ValueError("No conversion path for dtype: %s" % repr(dt))
 
-    IF H5PY_DEBUG:
-        import logging
-        logger = logging.getLogger('h5py')
-        logger.info( "H5T create: %s\n"
-                     "         => %s"  % (str(dt), repr(otype)))
     return otype
 
 
diff --git a/h5py/h5z.pyx b/h5py/h5z.pyx
index 1374264..f617249 100644
--- a/h5py/h5z.pyx
+++ b/h5py/h5z.pyx
@@ -58,8 +58,10 @@ DISABLE_EDC = H5Z_DISABLE_EDC
 ENABLE_EDC  = H5Z_ENABLE_EDC
 NO_EDC      = H5Z_NO_EDC
 
+
 # === Filter API  =============================================================
 
+ at sync
 def filter_avail(int filter_code):
     """ (INT filter_code) => BOOL available
 
@@ -73,6 +75,7 @@ def filter_avail(int filter_code):
     """
     return <bint>H5Zfilter_avail(<H5Z_filter_t>filter_code)
 
+ at sync
 def get_filter_info(int filter_code):
     """ (INT filter_code) => INT filter_flags
 
diff --git a/h5py/sync.pxi b/h5py/sync.pxi
index c81e704..1584d75 100644
--- a/h5py/sync.pxi
+++ b/h5py/sync.pxi
@@ -10,20 +10,16 @@
 # 
 #-
 
-# Header file which goes as the first line in all .pyx files.  Currently its
-# main function is to help simplify the .pxi-based import fiasco.
+# Header file which defines decorators for thread safety and debug logging.
+# Intended to be included in the beginning of module .pyx files.
 
-# hdr_pxd already brought in hdf5 and stdlib defines.  So we just need to
-# include the configs, and define things like synchronization decorators.
-
-include "config.pxi"
-
-# Defines the following decorators:
-#
 # sync:     Acquire PHIL for this function, and log function entry  in
 #           debug mode.
 # nosync:   Don't acquire PHIL, but log function entry in debug mode.
-#
+
+
+include "config.pxi"    # For H5PY_* defines
+
 
 IF H5PY_DEBUG:
     import logging
@@ -46,3 +42,5 @@ ELSE:
     ELSE:
         cdef inline object sync(object func):
             return func
+
+
diff --git a/h5py/utils.pyx b/h5py/utils.pyx
index 0cd1fd1..243f410 100644
--- a/h5py/utils.pyx
+++ b/h5py/utils.pyx
@@ -15,7 +15,8 @@ include "sync.pxi"
 
 # Compile-time imports
 from h5 cimport init_hdf5
-from python cimport PyTuple_Check, PyList_Check, PyErr_SetString, Py_INCREF
+from python_exc cimport PyErr_SetString
+
 from numpy cimport import_array, NPY_UINT16, NPY_UINT32, NPY_UINT64, \
                    npy_intp, PyArray_SimpleNew, PyArray_ContiguousFromAny, \
                     PyArray_FROM_OTF, NPY_CONTIGUOUS, NPY_NOTSWAPPED, \
@@ -106,7 +107,7 @@ cdef int require_tuple(object tpl, int none_allowed, int size, char* name) excep
     # Otherwise raises ValueError
 
     if (tpl is None and none_allowed) or \
-      ( PyTuple_Check(tpl) and (size < 0 or len(tpl) == size)):
+      (isinstance(tpl, tuple) and (size < 0 or len(tpl) == size)):
         return 1
 
     nmsg = ""
@@ -124,7 +125,7 @@ cdef int require_list(object lst, int none_allowed, int size, char* name) except
     # Counterpart of require_tuple, for lists
 
     if (lst is None and none_allowed) or \
-      (PyList_Check(lst) and (size < 0 or len(lst) == size)):
+      (isinstance(lst, list) and (size < 0 or len(lst) == size)):
         return 1
 
     nmsg = ""

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