[h5py] 311/455: Windows compiler (VS2005) can't handle long docstrings.

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:45 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 2377335d801dcb22e488e2ef4afe61124903f24c
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Mon Sep 14 21:41:49 2009 +0000

    Windows compiler (VS2005) can't handle long docstrings.
---
 h5py/h5t.pyx | 3042 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 1523 insertions(+), 1519 deletions(-)

diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 5cc40ab..462be12 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -1,1519 +1,1523 @@
-#+
-# 
-# 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$
-# 
-#-
-
-"""
-    HDF5 "H5T" data-type API
-
-    This module contains the datatype identifier class TypeID, and its
-    subclasses which represent things like integer/float/compound identifiers.
-    The majority of the H5T API is presented as methods on these identifiers.
-
-    1. Translating between Numpy dtypes and HDF5 type objects
-
-       All identifier classes have a property "dtype", returning a Numpy
-       dtype which as closely as possible matches the HDF5 type.
-
-       The module function py_create is the complement to this property, and
-       is the standard way to translate Numpy dtypes to HDF5 type identifiers.
-       Unlike the dtype property, HDF5 datatypes returned by this function are
-       guaranteed to be binary-compatible with their Numpy dtype counterparts.
-
-       The function py_create can also create "logically appropriate"
-       destination types; for example, the proper binary representation of
-       a Python string is an opaque type representing a char*, while the
-       "logical" type is an HDF5 variable-length string.
-
-    2. Complex numbers
-
-       Complex number support has been refactored in this version of h5py.
-       HDF5 has no native concept of a complex number.  Numpy complex types
-       are translated to two-element compound types with two floating-point
-       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 complex types are set as a property on the global
-       configuration object, available at h5py.get_config().
-
-    3. Boolan types
-
-       NumPy booleans are now supported.  They are stored as a 2-value byte
-       enum.  The enum names are set as a property on the global config
-       object, available at h5py.get_config().
-
-    4. Enumerated types
-
-       NumPy has no native concept of an enumerated type.  Enumerated types
-       are represented as "hinted" integer types, which are created and
-       tested with the convenience functions h5y.py_create_enum and
-       h5t.py_get_enum.  Values are handled in NumPy as integers.
-
-    5. Variable-length types
-
-       Variable-length strings are now supported, via "hinted" object dtypes
-       created and tested with the convenience functions h5t.py_create_vlen
-       and h5t.py_get_vlen.  Currently non-string vlens are not supported.
-
-       NOTE:  Only C-style strings are supported; NO embedded nulls are
-       allowed.  This is a limitation of the HDF5 library and won't change
-       until generic vlen support is added.
-
-    6. Datatypes can be pickled if HDF5 1.8.X is available.  The manual
-       HDF5 serialization routines (added in 1.8) are also available.
-"""
-
-include "config.pxi"
-
-# Pyrex compile-time imports
-from h5 cimport init_hdf5, H5PYConfig, get_config, PHIL, get_phil, get_object_type
-from h5p cimport PropID, pdefault
-from numpy cimport dtype, ndarray
-from python_string cimport PyString_FromStringAndSize
-
-from utils cimport  emalloc, efree, \
-                    require_tuple, convert_dims, convert_tuple
-
-# Initialization
-init_hdf5()
-
-# Runtime imports
-import sys
-import h5
-from _sync import sync, nosync
-
-cdef H5PYConfig cfg = get_config()
-cdef PHIL phil = get_phil()
-
-
-# === Custom C API ============================================================
-
-cdef TypeID typewrap(hid_t id_):
-
-    cdef H5T_class_t cls
-    cls = H5Tget_class(id_)
-
-    if cls == H5T_INTEGER:
-        pcls = TypeIntegerID
-    elif cls == H5T_FLOAT:
-        pcls = TypeFloatID
-    elif cls == H5T_TIME:
-        pcls = TypeTimeID
-    elif cls == H5T_STRING:
-        pcls = TypeStringID
-    elif cls == H5T_BITFIELD:
-        pcls = TypeBitfieldID
-    elif cls == H5T_OPAQUE:
-        pcls = TypeOpaqueID
-    elif cls == H5T_COMPOUND:
-        pcls = TypeCompoundID
-    elif cls == H5T_REFERENCE:
-        pcls = TypeReferenceID
-    elif cls == H5T_ENUM:
-        pcls = TypeEnumID
-    elif cls == H5T_VLEN:
-        pcls = TypeVlenID
-    elif cls == H5T_ARRAY:
-        pcls = TypeArrayID
-    else:
-        pcls = TypeID
-
-    return pcls(id_)
-
-cdef object lockid(hid_t id_in):
-    cdef TypeID tid
-    tid = typewrap(id_in)
-    tid._locked = 1
-    return tid
-
-# === Public constants and data structures ====================================
-
-
-# Enumeration H5T_class_t
-NO_CLASS  = H5T_NO_CLASS
-INTEGER   = H5T_INTEGER
-FLOAT     = H5T_FLOAT
-TIME      = H5T_TIME
-STRING    = H5T_STRING
-BITFIELD  = H5T_BITFIELD
-OPAQUE    = H5T_OPAQUE
-COMPOUND  = H5T_COMPOUND
-REFERENCE = H5T_REFERENCE
-ENUM      = H5T_ENUM
-VLEN      = H5T_VLEN
-ARRAY     = H5T_ARRAY
-
-# Enumeration H5T_sign_t
-SGN_NONE   = H5T_SGN_NONE
-SGN_2      = H5T_SGN_2
-
-# Enumeration H5T_order_t
-ORDER_LE    = H5T_ORDER_LE
-ORDER_BE    = H5T_ORDER_BE
-ORDER_VAX   = H5T_ORDER_VAX
-ORDER_NONE  = H5T_ORDER_NONE
-
-DIR_DEFAULT = H5T_DIR_DEFAULT
-DIR_ASCEND  = H5T_DIR_ASCEND
-DIR_DESCEND = H5T_DIR_DESCEND
-
-# Enumeration H5T_str_t
-STR_NULLTERM = H5T_STR_NULLTERM
-STR_NULLPAD  = H5T_STR_NULLPAD
-STR_SPACEPAD = H5T_STR_SPACEPAD
-
-# Enumeration H5T_norm_t
-NORM_IMPLIED = H5T_NORM_IMPLIED
-NORM_MSBSET = H5T_NORM_MSBSET
-NORM_NONE = H5T_NORM_NONE
-
-# Enumeration H5T_cset_t:
-CSET_ASCII = H5T_CSET_ASCII
-
-# Enumeration H5T_pad_t:
-PAD_ZERO = H5T_PAD_ZERO
-PAD_ONE = H5T_PAD_ONE
-PAD_BACKGROUND = H5T_PAD_BACKGROUND
-
-if sys.byteorder == "little":    # Custom python addition
-    ORDER_NATIVE = H5T_ORDER_LE
-else:
-    ORDER_NATIVE = H5T_ORDER_BE
-
-# --- Built-in HDF5 datatypes -------------------------------------------------
-
-# IEEE floating-point
-IEEE_F32LE = lockid(H5T_IEEE_F32LE)
-IEEE_F32BE = lockid(H5T_IEEE_F32BE)
-IEEE_F64LE = lockid(H5T_IEEE_F64LE)
-IEEE_F64BE = lockid(H5T_IEEE_F64BE)
-
-# Signed 2's complement integer types
-STD_I8LE  = lockid(H5T_STD_I8LE)
-STD_I16LE = lockid(H5T_STD_I16LE)
-STD_I32LE = lockid(H5T_STD_I32LE)
-STD_I64LE = lockid(H5T_STD_I64LE)
-
-STD_I8BE  = lockid(H5T_STD_I8BE)
-STD_I16BE = lockid(H5T_STD_I16BE)
-STD_I32BE = lockid(H5T_STD_I32BE)
-STD_I64BE = lockid(H5T_STD_I64BE)
-
-# Unsigned integers
-STD_U8LE  = lockid(H5T_STD_U8LE)
-STD_U16LE = lockid(H5T_STD_U16LE)
-STD_U32LE = lockid(H5T_STD_U32LE)
-STD_U64LE = lockid(H5T_STD_U64LE)
-
-STD_U8BE  = lockid(H5T_STD_U8BE)
-STD_U16BE = lockid(H5T_STD_U16BE)
-STD_U32BE = lockid(H5T_STD_U32BE)
-STD_U64BE = lockid(H5T_STD_U64BE)
-
-# Native types by bytesize
-NATIVE_INT8 = lockid(H5T_NATIVE_INT8)
-NATIVE_UINT8 = lockid(H5T_NATIVE_UINT8)
-NATIVE_INT16 = lockid(H5T_NATIVE_INT16)
-NATIVE_UINT16 = lockid(H5T_NATIVE_UINT16)
-NATIVE_INT32 = lockid(H5T_NATIVE_INT32)
-NATIVE_UINT32 = lockid(H5T_NATIVE_UINT32)
-NATIVE_INT64 = lockid(H5T_NATIVE_INT64)
-NATIVE_UINT64 = lockid(H5T_NATIVE_UINT64)
-NATIVE_FLOAT = lockid(H5T_NATIVE_FLOAT)
-NATIVE_DOUBLE = lockid(H5T_NATIVE_DOUBLE)
-
-# Unix time types
-UNIX_D32LE = lockid(H5T_UNIX_D32LE)
-UNIX_D64LE = lockid(H5T_UNIX_D64LE)
-UNIX_D32BE = lockid(H5T_UNIX_D32BE)
-UNIX_D64BE = lockid(H5T_UNIX_D64BE)
-
-# Reference types
-STD_REF_OBJ = lockid(H5T_STD_REF_OBJ)
-STD_REF_DSETREG = lockid(H5T_STD_REF_DSETREG)
-
-# Null terminated (C) and Fortran string types
-C_S1 = lockid(H5T_C_S1)
-FORTRAN_S1 = lockid(H5T_FORTRAN_S1)
-VARIABLE = H5T_VARIABLE
-
-# Custom Python object pointer type
-PYTHON_OBJECT = lockid(get_object_type())
-
-# 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
-        
-    Create a new HDF5 type object.  Legal class values are 
-    COMPOUND and OPAQUE.  Use enum_create for enums.
-    """
-
-    # HDF5 versions 1.6.X segfault with anything else
-    if classtype != H5T_COMPOUND and classtype != H5T_OPAQUE:
-        raise ValueError("Class must be COMPOUND or OPAQUE.")
-
-    return typewrap(H5Tcreate(<H5T_class_t>classtype, size))
-
- at sync
-def open(ObjectID group not None, char* name):
-    """(ObjectID group, STRING name) => TypeID
-
-    Open a named datatype from a file.
-    """
-    return typewrap(H5Topen(group.id, name))
-
- at sync
-def array_create(TypeID base not None, object dims_tpl):
-    """(TypeID base, TUPLE dimensions) => TypeArrayID
-
-    Create a new array datatype, using and HDF5 parent type and
-    dimensions given via a tuple of positive integers.  "Unlimited" 
-    dimensions are not allowed.
-    """
-    cdef hsize_t rank
-    cdef hsize_t *dims = NULL
-
-    require_tuple(dims_tpl, 0, -1, "dims_tpl")
-    rank = len(dims_tpl)
-    dims = <hsize_t*>emalloc(sizeof(hsize_t)*rank)
-
-    try:
-        convert_tuple(dims_tpl, dims, rank)
-        return TypeArrayID(H5Tarray_create(base.id, rank, dims, NULL))
-    finally:
-        efree(dims)
-
- at sync
-def enum_create(TypeID base not None):
-    """(TypeID base) => TypeID
-
-    Create a new enumerated type based on an (integer) parent type.
-    """
-    return typewrap(H5Tenum_create(base.id))
-
- at sync
-def vlen_create(TypeID base not None):
-    """(TypeID base) => TypeID
-
-    Create a new variable-length datatype, using any HDF5 type as a base.
-
-    Although the Python interface can manipulate these types, there is no
-    provision for reading/writing vlen data.
-    """
-    return typewrap(H5Tvlen_create(base.id))
-
-IF H5PY_18API:
-    @sync
-    def decode(char* buf):
-        """(STRING buf) => TypeID
-
-        Unserialize an HDF5 type.  You can also do this with the native
-        Python pickling machinery.
-        """
-        return typewrap(H5Tdecode(<unsigned char*>buf))
-
-# === Base type class =========================================================
-
-cdef class TypeID(ObjectID):
-
-    """
-        Base class for type identifiers (implements common operations)
-
-        * Hashable: If committed; in HDF5 1.8.X, also if locked
-        * Equality: Logical H5T comparison
-    """
-
-    def __hash__(self):
-        if self._hash is None:
-            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
-
-    property dtype:
-        """ A Numpy-style dtype object representing this object.
-        """
-        def __get__(self):
-            return self.py_dtype()
-
-    cdef object py_dtype(self):
-        raise TypeError("No NumPy equivalent for %s exists" % self.__class__.__name__)
-
-    IF H5PY_18API:
-        @sync
-        def commit(self, ObjectID group not None, char* name, PropID lcpl=None):
-            """(ObjectID group, STRING name, PropID lcpl=None)
-
-            Commit this (transient) datatype to a named datatype in a file.
-            If present, lcpl may be a link creation property list.
-            """
-            H5Tcommit2(group.id, name, self.id, pdefault(lcpl),
-                H5P_DEFAULT, H5P_DEFAULT)
-    ELSE:
-        @sync
-        def commit(self, ObjectID group not None, char* name):
-            """(ObjectID group, STRING name)
-
-            Commit this (transient) datatype to a named datatype in a file.
-            """
-            H5Tcommit(group.id, name, self.id)
-
-    @sync
-    def committed(self):
-        """() => BOOL is_comitted
-
-        Determine if a given type object is named (T) or transient (F).
-        """
-        return <bint>(H5Tcommitted(self.id))
-
-    @sync
-    def copy(self):
-        """() => TypeID
-
-        Create a copy of this type object.
-        """
-        return typewrap(H5Tcopy(self.id))
-
-    @sync
-    def equal(self, TypeID typeid):
-        """(TypeID typeid) => BOOL
-
-        Logical comparison between datatypes.  Also called by
-        Python's "==" operator.
-        """
-        return <bint>(H5Tequal(self.id, typeid.id))
-
-    @sync
-    def lock(self):
-        """()
-
-        Lock this datatype, which makes it immutable and indestructible.
-        Once locked, it can't be unlocked.
-        """
-        H5Tlock(self.id)
-        self._locked = 1
-
-    @sync
-    def get_class(self):
-        """() => INT classcode
-
-        Determine the datatype's class code.
-        """
-        return <int>H5Tget_class(self.id)
-
-    @sync
-    def set_size(self, size_t size):
-        """(UINT size)
-
-        Set the total size of the datatype, in bytes.
-        """
-        H5Tset_size(self.id, size)
-
-    @sync
-    def get_size(self):
-        """ () => INT size
-
-            Determine the total size of a datatype, in bytes.
-        """
-        return H5Tget_size(self.id)
-
-    @sync
-    def get_super(self):
-        """() => TypeID
-
-        Determine the parent type of an array, enumeration or vlen datatype.
-        """
-        return typewrap(H5Tget_super(self.id))
-
-    @sync
-    def detect_class(self, int classtype):
-        """(INT classtype) => BOOL class_is_present
-
-        Determine if a member of the given class exists in a compound
-        datatype.  The search is recursive.
-        """
-        return <bint>(H5Tdetect_class(self.id, <H5T_class_t>classtype))
-
-    @sync
-    def _close(self):
-        """()
-
-        Close this datatype.  If it's locked, nothing happens.
-
-        You shouldn't ordinarily need to call this function; datatype
-        objects are automatically closed when they're deallocated.
-        """
-        if not self._locked:
-            H5Tclose(self.id)
-
-    IF H5PY_18API:
-        @sync
-        def encode(self):
-            """() => STRING
-
-            Serialize an HDF5 type.  Bear in mind you can also use the
-            native Python pickle/unpickle machinery to do this.  The
-            returned string may contain binary values, including NULLs.
-            """
-            cdef size_t nalloc = 0
-            cdef char* buf = NULL
-
-            H5Tencode(self.id, NULL, &nalloc)
-            buf = <char*>emalloc(sizeof(char)*nalloc)
-            try:
-                H5Tencode(self.id, <unsigned char*>buf, &nalloc)
-                pystr = PyString_FromStringAndSize(buf, nalloc)
-            finally:
-                efree(buf)
-
-            return pystr
-
-    IF H5PY_18API:
-        # Enable pickling
-
-        def __reduce__(self):
-            return (type(self), (-1,), self.encode())
-
-        @sync
-        def __setstate__(self, char* state):
-            self.id = H5Tdecode(<unsigned char*>state)
-
-
-# === Top-level classes (inherit directly from TypeID) ========================
-
-cdef class TypeArrayID(TypeID):
-
-    """
-        Represents an array datatype
-    """
-
-    @sync
-    def get_array_ndims(self):
-        """() => INT rank
-
-        Get the rank of the given array datatype.
-        """
-        return H5Tget_array_ndims(self.id)
-
-    @sync
-    def get_array_dims(self):
-        """() => TUPLE dimensions
-
-        Get the dimensions of the given array datatype as
-        a tuple of integers.
-        """
-        cdef hsize_t rank   
-        cdef hsize_t* dims = NULL
-
-        rank = H5Tget_array_dims(self.id, NULL, NULL)
-        dims = <hsize_t*>emalloc(sizeof(hsize_t)*rank)
-        try:
-            H5Tget_array_dims(self.id, dims, NULL)
-            return convert_dims(dims, rank)
-        finally:
-            efree(dims)
-
-    cdef object py_dtype(self):
-        # Numpy translation function for array types
-        cdef TypeID tmp_type
-        tmp_type = self.get_super()
-
-        base_dtype = tmp_type.py_dtype()
-
-        shape = self.get_array_dims()
-        return dtype( (base_dtype, shape) )
-
-
-cdef class TypeOpaqueID(TypeID):
-
-    """
-        Represents an opaque type
-    """
-
-    @sync
-    def set_tag(self, char* tag):
-        """(STRING tag)
-
-        Set a string describing the contents of an opaque datatype.
-        Limited to 256 characters.
-        """
-        H5Tset_tag(self.id, tag)
-
-    @sync
-    def get_tag(self):
-        """() => STRING tag
-
-        Get the tag associated with an opaque datatype.
-        """
-        cdef char* buf = NULL
-
-        try:
-            buf = H5Tget_tag(self.id)
-            assert buf != NULL
-            tag = buf
-            return tag
-        finally:
-            free(buf)
-
-    cdef object py_dtype(self):
-        # Numpy translation function for opaque types
-        return dtype("|V" + str(self.get_size()))
-
-cdef class TypeStringID(TypeID):
-
-    """
-        String datatypes, both fixed and vlen.
-    """
-
-    @sync
-    def is_variable_str(self):
-        """() => BOOL is_variable
-
-        Determine if the given string datatype is a variable-length string.
-        """
-        return <bint>(H5Tis_variable_str(self.id))
-
-    @sync
-    def get_cset(self):
-        """() => INT character_set
-
-        Retrieve the character set used for a string.
-        """
-        return <int>H5Tget_cset(self.id)
-
-    @sync
-    def set_cset(self, int cset):
-        """(INT character_set)
-
-        Set the character set used for a string.
-        """
-        H5Tset_cset(self.id, <H5T_cset_t>cset)
-
-    @sync
-    def get_strpad(self):
-        """() => INT padding_type
-
-        Get the padding type.  Legal values are:
-
-        STR_NULLTERM
-            NULL termination only (C style)
-
-        STR_NULLPAD
-            Pad buffer with NULLs
-
-        STR_SPACEPAD
-            Pad buffer with spaces (FORTRAN style)
-        """
-        return <int>H5Tget_strpad(self.id)
-
-    @sync
-    def set_strpad(self, int pad):
-        """(INT pad)
-
-        Set the padding type.  Legal values are:
-
-        STR_NULLTERM
-            NULL termination only (C style)
-
-        STR_NULLPAD
-            Pad buffer with NULLs
-
-        STR_SPACEPAD
-            Pad buffer with spaces (FORTRAN style)
-        """
-        H5Tset_strpad(self.id, <H5T_str_t>pad)
-
-    cdef object py_dtype(self):
-        # Numpy translation function for string types
-        if self.is_variable_str():
-            return py_new_vlen(str)
-
-        return dtype("|S" + str(self.get_size()))
-
-cdef class TypeVlenID(TypeID):
-
-    """
-        Non-string vlen datatypes.
-    """
-    pass
-
-cdef class TypeTimeID(TypeID):
-
-    """
-        Unix-style time_t (deprecated)
-    """
-    pass
-
-cdef class TypeBitfieldID(TypeID):
-
-    """
-        HDF5 bitfield type
-    """
-    pass
-
-cdef class TypeReferenceID(TypeID):
-
-    """
-        HDF5 object or region reference
-    """
-    pass
-
-
-# === Numeric classes (integers and floats) ===================================
-
-cdef class TypeAtomicID(TypeID):
-
-    """
-        Base class for atomic datatypes (float or integer)
-    """
-
-    @sync
-    def get_order(self):
-        """() => INT order
-
-        Obtain the byte order of the datatype; one of:
-
-        - ORDER_LE
-        - ORDER_BE
-        """
-        return <int>H5Tget_order(self.id)
-
-    @sync
-    def set_order(self, int order):
-        """(INT order)
-
-        Set the byte order of the datatype; one of:
-
-        - ORDER_LE
-        - ORDER_BE
-        """
-        H5Tset_order(self.id, <H5T_order_t>order)
-
-    @sync
-    def get_precision(self):
-        """() => UINT precision
-
-        Get the number of significant bits (excludes padding).
-        """
-        return H5Tget_precision(self.id)
-
-    @sync
-    def set_precision(self, size_t precision):
-        """(UINT precision)
-            
-        Set the number of significant bits (excludes padding).
-        """
-        H5Tset_precision(self.id, precision)
-
-    @sync
-    def get_offset(self):
-        """() => INT offset
-
-        Get the offset of the first significant bit.
-        """
-        return H5Tget_offset(self.id)
-
-    @sync
-    def set_offset(self, size_t offset):
-        """(UINT offset)
-
-        Set the offset of the first significant bit.
-        """
-        H5Tset_offset(self.id, offset)
-
-    @sync
-    def get_pad(self):
-        """() => (INT lsb_pad_code, INT msb_pad_code)
-
-        Determine the padding type.  Possible values are:
-
-        - PAD_ZERO
-        - PAD_ONE
-        - PAD_BACKGROUND
-        """
-        cdef H5T_pad_t lsb
-        cdef H5T_pad_t msb
-        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)
-
-        Set the padding type.  Possible values are:
-
-        - PAD_ZERO
-        - PAD_ONE
-        - PAD_BACKGROUND
-        """
-        H5Tset_pad(self.id, <H5T_pad_t>lsb, <H5T_pad_t>msb)
-
-
-cdef class TypeIntegerID(TypeAtomicID):
-
-    """
-        Integer atomic datatypes
-    """
-
-    @sync
-    def get_sign(self):
-        """() => INT sign
-
-        Get the "signedness" of the datatype; one of:
-
-        SGN_NONE
-            Unsigned
-
-        SGN_2
-            Signed 2's complement
-        """
-        return <int>H5Tget_sign(self.id)
-
-    @sync
-    def set_sign(self, int sign):
-        """(INT sign)
-
-        Set the "signedness" of the datatype; one of:
-
-        SGN_NONE
-            Unsigned
-
-        SGN_2
-            Signed 2's complement
-        """
-        H5Tset_sign(self.id, <H5T_sign_t>sign)
-
-    cdef object py_dtype(self):
-        # Translation function for integer types
-        return dtype( _order_map[self.get_order()] + 
-                      _sign_map[self.get_sign()] + str(self.get_size()) )
-
-
-cdef class TypeFloatID(TypeAtomicID):
-
-    """
-        Floating-point atomic datatypes
-    """
-
-    @sync
-    def get_fields(self):
-        """() => TUPLE field_info
-
-        Get information about floating-point bit fields.  See the HDF5
-        docs for a full description.  Tuple has the following members:
-
-        0. UINT spos
-        1. UINT epos
-        2. UINT esize
-        3. UINT mpos
-        4. UINT msize
-        """
-        cdef size_t spos, epos, esize, mpos, msize
-        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)
-
-        Set floating-point bit fields.  Refer to the HDF5 docs for
-        argument definitions.
-        """
-        H5Tset_fields(self.id, spos, epos, esize, mpos, msize)
-
-    @sync
-    def get_ebias(self):
-        """() => UINT ebias
-
-        Get the exponent bias.
-        """
-        return H5Tget_ebias(self.id)
-
-    @sync
-    def set_ebias(self, size_t ebias):
-        """(UINT ebias)
-
-        Set the exponent bias.
-        """
-        H5Tset_ebias(self.id, ebias)
-
-    @sync
-    def get_norm(self):
-        """() => INT normalization_code
-
-        Get the normalization strategy.  Legal values are:
-
-        - NORM_IMPLIED
-        - NORM_MSBSET
-        - NORM_NONE
-        """
-        return <int>H5Tget_norm(self.id)
-
-    @sync
-    def set_norm(self, int norm):
-        """(INT normalization_code)
-
-        Set the normalization strategy.  Legal values are:
-
-        - NORM_IMPLIED
-        - NORM_MSBSET
-        - NORM_NONE
-        """
-        H5Tset_norm(self.id, <H5T_norm_t>norm)
-
-    @sync
-    def get_inpad(self):
-        """() => INT pad_code
-
-        Determine the internal padding strategy.  Legal values are:
-
-        - PAD_ZERO
-        - PAD_ONE
-        - PAD_BACKGROUND
-        """
-        return <int>H5Tget_inpad(self.id)
-
-    @sync
-    def set_inpad(self, int pad_code):
-        """(INT pad_code)
-
-        Set the internal padding strategy.  Legal values are:
-
-        - PAD_ZERO
-        - PAD_ONE
-        - PAD_BACKGROUND
-        """
-        H5Tset_inpad(self.id, <H5T_pad_t>pad_code)
-
-    cdef object py_dtype(self):
-        # Translation function for floating-point types
-        return dtype( _order_map[self.get_order()] + "f" + \
-                      str(self.get_size()) )
-
-
-# === Composite types (enums and compound) ====================================
-
-cdef class TypeCompositeID(TypeID):
-
-    """
-        Base class for enumerated and compound types.
-    """
-
-    @sync
-    def get_nmembers(self):
-        """() => INT number_of_members
-
-        Determine the number of members in a compound or enumerated type.
-        """
-        return H5Tget_nmembers(self.id)
-
-    @sync
-    def get_member_name(self, int member):
-        """(INT member) => STRING name
-        
-        Determine the name of a member of a compound or enumerated type,
-        identified by its index (0 <= member < nmembers).
-        """
-        cdef char* name
-        name = NULL
-
-        if member < 0:
-            raise ValueError("Member index must be non-negative.")
-
-        try:
-            name = H5Tget_member_name(self.id, member)
-            assert name != NULL
-            pyname = name
-        finally:
-            free(name)
-
-        return pyname
-
-    @sync
-    def get_member_index(self, char* name):
-        """(STRING name) => INT index
-
-        Determine the index of a member of a compound or enumerated datatype
-        identified by a string name.
-        """
-        return H5Tget_member_index(self.id, name)
-
-
-cdef class TypeCompoundID(TypeCompositeID):
-
-    """
-        Represents a compound datatype
-    """
-
-
-    @sync
-    def get_member_class(self, int member):
-        """(INT member) => INT class
-
-        Determine the datatype class of the member of a compound type,
-        identified by its index (0 <= member < nmembers).
-        """
-        if member < 0:
-            raise ValueError("Member index must be non-negative.")
-        return H5Tget_member_class(self.id, member)
-
-
-    @sync
-    def get_member_offset(self, int member):
-        """(INT member) => INT offset
-
-        Determine the offset, in bytes, of the beginning of the specified
-        member of a compound datatype.
-        """
-        if member < 0:
-            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
-
-        Create a copy of a member of a compound datatype, identified by its
-        index.
-        """
-        if member < 0:
-            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)
-
-        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(self.id, name, offset, field.id)
-
-    @sync
-    def pack(self):
-        """()
-
-        Recursively removes padding (introduced on account of e.g. compiler
-        alignment rules) from a compound datatype.
-        """
-        H5Tpack(self.id)
-
-    cdef object py_dtype(self):
-
-        cdef TypeID tmp_type
-        cdef list field_names
-        cdef list field_types
-        cdef int nfields
-        field_names = []
-        field_types = []
-        nfields = self.get_nmembers()
-
-        # First step: read field names and their Numpy dtypes into 
-        # two separate arrays.
-        for i from 0 <= i < nfields:
-            tmp_type = self.get_member_type(i)
-            field_names.append(self.get_member_name(i))
-            field_types.append(tmp_type.py_dtype())
-
-
-        # 1. Check if it should be converted to a complex number
-        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
-            blen = int(bstring[2:])
-            nstring = bstring[0] + "c" + str(2*blen)
-            typeobj = dtype(nstring)
-
-        # 2. Otherwise, read all fields of the compound type, in HDF5 order.
-        else:
-            typeobj = dtype(zip(field_names, field_types))
-
-        return typeobj
-
-cdef class TypeEnumID(TypeCompositeID):
-
-    """
-        Represents an enumerated type
-    """
-
-    cdef int enum_convert(self, long long *buf, int reverse) except -1:
-        # Convert the long long value in "buf" to the native representation
-        # of this (enumerated) type.  Conversion performed in-place.
-        # Reverse: false => llong->type; true => type->llong
-
-        cdef hid_t basetype
-        cdef H5T_class_t class_code
-
-        class_code = H5Tget_class(self.id)
-        if class_code != H5T_ENUM:
-            raise ValueError("This type (class %d) is not of class ENUM" % class_code)
-
-        basetype = H5Tget_super(self.id)
-        assert basetype > 0
-
-        try:
-            if not reverse:
-                H5Tconvert(H5T_NATIVE_LLONG, basetype, 1, buf, NULL, H5P_DEFAULT)
-            else:
-                H5Tconvert(basetype, H5T_NATIVE_LLONG, 1, buf, NULL, H5P_DEFAULT)
-        finally:
-            H5Tclose(basetype)
-
-    @sync
-    def enum_insert(self, char* name, long long value):
-        """(STRING name, INT/LONG value)
-
-        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 long long buf
-
-        buf = value
-        self.enum_convert(&buf, 0)
-        H5Tenum_insert(self.id, name, &buf)
-
-    @sync
-    def enum_nameof(self, long long value):
-        """(LONG 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 in length.
-        """
-        cdef herr_t retval
-        cdef char name[1024]
-        cdef long long buf
-
-        buf = value
-        self.enum_convert(&buf, 0)
-        retval = H5Tenum_nameof(self.id, &buf, name, 1024)
-        assert retval >= 0
-        retstring = name
-        return retstring
-
-    @sync
-    def enum_valueof(self, char* name):
-        """(STRING name) => LONG value
-
-        Get the value associated with an enum name.
-        """
-        cdef long long buf
-
-        H5Tenum_valueof(self.id, name, &buf)
-        self.enum_convert(&buf, 1)
-        return buf
-
-    @sync
-    def get_member_value(self, int idx):
-        """(UINT index) => LONG value
-
-        Determine the value for the member at the given zero-based index.
-        """
-        cdef herr_t retval
-        cdef hid_t ptype
-        cdef long long val
-        ptype = 0
-
-        if idx < 0:
-            raise ValueError("Index must be non-negative.")
-
-        H5Tget_member_value(self.id, idx, &val)
-        self.enum_convert(&val, 1)
-        return val
-
-    cdef object py_dtype(self):
-        # Translation function for enum types
-
-        cdef TypeID basetype = self.get_super()
-
-        nmembers = self.get_nmembers()
-        members = {}
-
-        for idx in xrange(nmembers):
-            name = self.get_member_name(idx)
-            val = self.get_member_value(idx) 
-            members[name] = val
-
-        ref = {cfg._f_name: 0, cfg._t_name: 1}
-
-        # Boolean types have priority over standard enums
-        if members == ref:
-            return dtype('bool')
-    
-        return py_new_enum(basetype.py_dtype(), members)
-
-
-# === Translation from NumPy dtypes to HDF5 type objects ======================
-
-# The following series of native-C functions each translate a specific class
-# of NumPy dtype into an HDF5 type object.  The result is guaranteed to be
-# transient and unlocked.
-
-cdef dict _float_le = {4: H5T_IEEE_F32LE, 8: H5T_IEEE_F64LE}
-cdef dict _float_be = {4: H5T_IEEE_F32BE, 8: H5T_IEEE_F64BE}
-cdef dict _float_nt = {4: H5T_NATIVE_FLOAT, 8: H5T_NATIVE_DOUBLE}
-
-cdef dict _int_le = {1: H5T_STD_I8LE, 2: H5T_STD_I16LE, 4: H5T_STD_I32LE, 8: H5T_STD_I64LE}
-cdef dict _int_be = {1: H5T_STD_I8BE, 2: H5T_STD_I16BE, 4: H5T_STD_I32BE, 8: H5T_STD_I64BE}
-cdef dict _int_nt = {1: H5T_NATIVE_INT8, 2: H5T_NATIVE_INT16, 4: H5T_NATIVE_INT32, 8: H5T_NATIVE_INT64}
-
-cdef dict _uint_le = {1: H5T_STD_U8LE, 2: H5T_STD_U16LE, 4: H5T_STD_U32LE, 8: H5T_STD_U64LE}
-cdef dict _uint_be = {1: H5T_STD_U8BE, 2: H5T_STD_U16BE, 4: H5T_STD_U32BE, 8: H5T_STD_U64BE}
-cdef dict _uint_nt = {1: H5T_NATIVE_UINT8, 2: H5T_NATIVE_UINT16, 4: H5T_NATIVE_UINT32, 8: H5T_NATIVE_UINT64} 
-
-cdef TypeFloatID _c_float(dtype dt):
-    # Floats (single and double)
-    cdef hid_t tid
-
-    if dt.byteorder == c'<':
-        tid =  _float_le[dt.elsize]
-    elif dt.byteorder == c'>':
-        tid =  _float_be[dt.elsize]
-    else:
-        tid =  _float_nt[dt.elsize]
-
-    return TypeFloatID(H5Tcopy(tid))
-
-cdef TypeIntegerID _c_int(dtype dt):
-    # Integers (ints and uints)
-    cdef hid_t tid
-
-    if dt.kind == c'i':
-        if dt.byteorder == c'<':
-            tid = _int_le[dt.elsize]
-        elif dt.byteorder == c'>':
-            tid = _int_be[dt.elsize]
-        else:
-            tid = _int_nt[dt.elsize]
-    elif dt.kind == c'u':
-        if dt.byteorder == c'<':
-            tid = _uint_le[dt.elsize]
-        elif dt.byteorder == c'>':
-            tid = _uint_be[dt.elsize]
-        else:
-            tid = _uint_nt[dt.elsize]
-    else:
-        raise TypeError('Illegal int kind "%s"' % dt.kind)
-
-    return TypeIntegerID(H5Tcopy(tid))
-
-cdef TypeEnumID _c_enum(dtype dt, dict vals):
-    # Enums
-    cdef TypeIntegerID base
-    cdef TypeEnumID out
-
-    base = _c_int(dt)
-
-    out = TypeEnumID(H5Tenum_create(base.id))
-    for name in sorted(vals):
-        out.enum_insert(name, vals[name])
-    return out
-
-cdef TypeEnumID _c_bool(dtype dt):
-    # Booleans
-    global cfg
-
-    cdef TypeEnumID out
-    out = TypeEnumID(H5Tenum_create(H5T_NATIVE_INT8))
-
-    out.enum_insert(cfg._f_name, 0)
-    out.enum_insert(cfg._t_name, 1)
-
-    return out
-
-cdef TypeArrayID _c_array(dtype dt, int logical):
-    # Arrays
-    cdef dtype base
-    cdef TypeID type_base
-    cdef tuple shape
-
-    base, shape = dt.subdtype
-    type_base = py_create(base, logical=logical)
-    return array_create(type_base, shape)
-
-cdef TypeOpaqueID _c_opaque(dtype dt):
-    # Opaque
-    return TypeOpaqueID(H5Tcreate(H5T_OPAQUE, dt.itemsize))
-
-cdef TypeStringID _c_string(dtype dt):
-    # Strings (fixed-length)
-    cdef hid_t tid
-
-    tid = H5Tcopy(H5T_C_S1)
-    H5Tset_size(tid, dt.itemsize)
-    H5Tset_strpad(tid, H5T_STR_NULLPAD)
-    return TypeStringID(tid)
-
-cdef TypeCompoundID _c_complex(dtype dt):
-    # Complex numbers (names depend on cfg)
-    global cfg
-
-    cdef hid_t tid, tid_sub
-    cdef size_t size, off_r, off_i
-
-    cdef size_t length = dt.itemsize
-    cdef char byteorder = dt.byteorder
-
-    if length == 8:
-        size = h5py_size_n64
-        off_r = h5py_offset_n64_real
-        off_i = h5py_offset_n64_imag
-        if byteorder == c'<':
-            tid_sub = H5T_IEEE_F32LE
-        elif byteorder == c'>':
-            tid_sub = H5T_IEEE_F32BE
-        else:
-            tid_sub = H5T_NATIVE_FLOAT
-    elif length == 16:
-        size = h5py_size_n128
-        off_r = h5py_offset_n128_real
-        off_i = h5py_offset_n128_imag
-        if byteorder == c'<':
-            tid_sub = H5T_IEEE_F64LE
-        elif byteorder == c'>':
-            tid_sub = H5T_IEEE_F64BE
-        else:
-            tid_sub = H5T_NATIVE_DOUBLE
-    else:
-        raise TypeError("Illegal length %d for complex dtype" % length)
-
-    tid = H5Tcreate(H5T_COMPOUND, size)
-    H5Tinsert(tid, cfg._r_name, off_r, tid_sub)
-    H5Tinsert(tid, cfg._i_name, off_i, tid_sub)
-
-    return TypeCompoundID(tid)
-
-cdef TypeCompoundID _c_compound(dtype dt, int logical):
-    # Compound datatypes
-
-    cdef hid_t tid
-    cdef TypeID type_tmp
-    cdef dtype dt_tmp
-    cdef size_t offset
-
-    cdef dict fields = dt.fields
-    cdef tuple names = dt.names
-
-    tid = H5Tcreate(H5T_COMPOUND, dt.itemsize)
-
-    for name in names:
-        dt_tmp, offset = dt.fields[name]
-        type_tmp = py_create(dt_tmp, logical=logical)
-        H5Tinsert(tid, name, offset, type_tmp.id)
-
-    return TypeCompoundID(tid)
-
-cdef TypeOpaqueID _c_object(dtype dt):
-    # Object types are represented by a custom opaque type
-    # Currently no other logic is required
-    return PYTHON_OBJECT
-
-cdef TypeStringID _c_vlen_str(object basetype):
-    # Variable-length strings
-    cdef hid_t tid
-    tid = H5Tcopy(H5T_C_S1)
-    H5Tset_size(tid, H5T_VARIABLE)
-    return TypeStringID(tid)
-
-cpdef TypeID py_create(object dtype_in, bint logical=0):
-    """(OBJECT dtype_in, BOOL logical=False) => TypeID
-
-    Given a Numpy dtype object, generate a byte-for-byte memory-compatible
-    HDF5 datatype object.  The result is guaranteed to be transient and
-    unlocked.
-
-    Argument dtype_in may be a dtype object, or anything which can be
-    converted to a dtype, including strings like '<i4'.
-
-    logical
-        If this flag is set, instead of returning a byte-for-byte identical
-        representation of the type, the function returns the closest logically
-        appropriate HDF5 type.  For example, in the case of a "hinted" dtype
-        of kind "O" representing a string, it would return an HDF5 variable-
-        length string type.
-    """
-    cdef dtype dt = dtype(dtype_in)
-    cdef char kind = dt.kind
-
-    phil.acquire()
-    try:
-        # Float
-        if kind == c'f':
-            return _c_float(dt)
-        
-        # Integer
-        elif kind == c'u' or kind == c'i':
-
-            if logical:
-                # Check for an enumeration hint
-                enum_vals = py_get_enum(dt)
-                if enum_vals is not None:
-                    return _c_enum(dt, enum_vals)
-
-            return _c_int(dt)
-
-        # Complex
-        elif kind == c'c':
-            return _c_complex(dt)
-
-        # Compound
-        elif kind == c'V' and dt.names is not None:
-            return _c_compound(dt, logical)
-
-        # Array or opaque
-        elif kind == c'V':
-            if dt.subdtype is not None:
-                return _c_array(dt, logical)
-            else:
-                return _c_opaque(dt)
-
-        # String
-        elif kind == c'S':
-            return _c_string(dt)
-
-        # Boolean
-        elif kind == c'b':
-            return _c_bool(dt)
-
-        # Object types (including those with vlen hints)
-        elif kind == c'O':
-
-            if logical:
-                # Check for vlen hints
-                vlen = py_get_vlen(dt)
-                if vlen is not None:
-                    return _c_vlen_str(vlen)
-                raise TypeError("Object dtype has no native HDF5 equivalent")
-
-            return _c_object(dt)
-
-        # Unrecognized
-        else:
-            raise TypeError("No conversion path for dtype: %s" % repr(dt))
-
-    finally:
-        phil.release()
-
-cpdef dtype py_new_enum(dtype dt_in, dict enum_vals):
-    """ (DTYPE dt_in, DICT enum_vals) => DTYPE
-
-    Create a new NumPy integer dtype, which contains "hint" metadata for
-    an enum. Only dtypes of kind 'i' or 'u' are allowed.  The enum_vals
-    dict must consist only of string keys and integer values.
-    """
-
-    cdef dtype dt = dtype(dt_in)
-    if dt.kind != 'i' and dt.kind != 'u':
-        raise TypeError("Only integer types can be used as enums")
-
-    return dtype((dt, [( ({'vals': enum_vals},'enum'), dt )] ))
-    
-cpdef dict py_get_enum(object dt):
-    """ (DTYPE dt_in) => DICT
-
-    Determine the enum values associated with a "hinted" NumPy integer type.
-    Returns None if the type does not contain hints, or is of the wrong kind.
-    """
-    
-    if dt.kind != 'i' and dt.kind != 'u':
-        return None
-
-    if dt.fields is not None and 'enum' in dt.fields:
-        tpl = dt.fields['enum']
-        if len(tpl) == 3:
-            info_dict = tpl[2]
-            if 'vals' in info_dict:
-                return info_dict['vals']
-
-    return None
-
-cpdef dtype py_new_vlen(object kind):
-    """ (OBJECT kind) => DTYPE
-
-    Create a new NumPy object dtype, which contains "hint" metadata
-    identifying the proper HDF5 vlen base type.  For now, only the native
-    Python string object (str) is supported.
-    """
-    if kind is not str:
-        raise NotImplementedError("Only string vlens are currently supported")
-
-    return dtype(('O', [( ({'type': kind},'vlen'), 'O' )] ))
-
-cpdef object py_get_vlen(object dt_in):
-    """ (OBJECT dt_in) => TYPE
-
-    Determine the vlen "hint" type associated with a NumPy object type,
-    or None if the dtype does not contain a hint or is not of kind "O".
-    """
-    cdef dtype dt = dtype(dt_in)
-
-    if dt.kind != 'O':
-        return None
-
-    if dt.fields is not None and 'vlen' in dt.fields:
-        tpl = dt.fields['vlen']
-        if len(tpl) == 3:
-            hint_dict = tpl[2]
-            if 'type' in hint_dict:
-                return hint_dict['type']
-
-    return None
-
-        
-def _path_exists(TypeID src not None, TypeID dst not None):
-    """ Undocumented and unsupported """
-    cdef H5T_cdata_t *data
-    cdef H5T_conv_t result = NULL
-    
-    result = H5Tfind(src.id, dst.id, &data)
-    return result != NULL
-
-
-
+#+
+# 
+# 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$
+# 
+#-
+
+IF UNAME_SYSNAME == "Windows":
+    __doc__ = """ HDF5 "H5T" data-type API """
+ELSE:
+    __doc__ = \
+"""
+    HDF5 "H5T" data-type API
+
+    This module contains the datatype identifier class TypeID, and its
+    subclasses which represent things like integer/float/compound identifiers.
+    The majority of the H5T API is presented as methods on these identifiers.
+
+    1. Translating between Numpy dtypes and HDF5 type objects
+
+       All identifier classes have a property "dtype", returning a Numpy
+       dtype which as closely as possible matches the HDF5 type.
+
+       The module function py_create is the complement to this property, and
+       is the standard way to translate Numpy dtypes to HDF5 type identifiers.
+       Unlike the dtype property, HDF5 datatypes returned by this function are
+       guaranteed to be binary-compatible with their Numpy dtype counterparts.
+
+       The function py_create can also create "logically appropriate"
+       destination types; for example, the proper binary representation of
+       a Python string is an opaque type representing a char*, while the
+       "logical" type is an HDF5 variable-length string.
+
+    2. Complex numbers
+
+       Complex number support has been refactored in this version of h5py.
+       HDF5 has no native concept of a complex number.  Numpy complex types
+       are translated to two-element compound types with two floating-point
+       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 complex types are set as a property on the global
+       configuration object, available at h5py.get_config().
+
+    3. Boolan types
+
+       NumPy booleans are now supported.  They are stored as a 2-value byte
+       enum.  The enum names are set as a property on the global config
+       object, available at h5py.get_config().
+
+    4. Enumerated types
+
+       NumPy has no native concept of an enumerated type.  Enumerated types
+       are represented as "hinted" integer types, which are created and
+       tested with the convenience functions h5y.py_create_enum and
+       h5t.py_get_enum.  Values are handled in NumPy as integers.
+
+    5. Variable-length types
+
+       Variable-length strings are now supported, via "hinted" object dtypes
+       created and tested with the convenience functions h5t.py_create_vlen
+       and h5t.py_get_vlen.  Currently non-string vlens are not supported.
+
+       NOTE:  Only C-style strings are supported; NO embedded nulls are
+       allowed.  This is a limitation of the HDF5 library and won't change
+       until generic vlen support is added.
+
+    6. Datatypes can be pickled if HDF5 1.8.X is available.  The manual
+       HDF5 serialization routines (added in 1.8) are also available.
+"""
+
+include "config.pxi"
+
+# Pyrex compile-time imports
+from h5 cimport init_hdf5, H5PYConfig, get_config, PHIL, get_phil, get_object_type
+from h5p cimport PropID, pdefault
+from numpy cimport dtype, ndarray
+from python_string cimport PyString_FromStringAndSize
+
+from utils cimport  emalloc, efree, \
+                    require_tuple, convert_dims, convert_tuple
+
+# Initialization
+init_hdf5()
+
+# Runtime imports
+import sys
+import h5
+from _sync import sync, nosync
+
+cdef H5PYConfig cfg = get_config()
+cdef PHIL phil = get_phil()
+
+
+# === Custom C API ============================================================
+
+cdef TypeID typewrap(hid_t id_):
+
+    cdef H5T_class_t cls
+    cls = H5Tget_class(id_)
+
+    if cls == H5T_INTEGER:
+        pcls = TypeIntegerID
+    elif cls == H5T_FLOAT:
+        pcls = TypeFloatID
+    elif cls == H5T_TIME:
+        pcls = TypeTimeID
+    elif cls == H5T_STRING:
+        pcls = TypeStringID
+    elif cls == H5T_BITFIELD:
+        pcls = TypeBitfieldID
+    elif cls == H5T_OPAQUE:
+        pcls = TypeOpaqueID
+    elif cls == H5T_COMPOUND:
+        pcls = TypeCompoundID
+    elif cls == H5T_REFERENCE:
+        pcls = TypeReferenceID
+    elif cls == H5T_ENUM:
+        pcls = TypeEnumID
+    elif cls == H5T_VLEN:
+        pcls = TypeVlenID
+    elif cls == H5T_ARRAY:
+        pcls = TypeArrayID
+    else:
+        pcls = TypeID
+
+    return pcls(id_)
+
+cdef object lockid(hid_t id_in):
+    cdef TypeID tid
+    tid = typewrap(id_in)
+    tid._locked = 1
+    return tid
+
+# === Public constants and data structures ====================================
+
+
+# Enumeration H5T_class_t
+NO_CLASS  = H5T_NO_CLASS
+INTEGER   = H5T_INTEGER
+FLOAT     = H5T_FLOAT
+TIME      = H5T_TIME
+STRING    = H5T_STRING
+BITFIELD  = H5T_BITFIELD
+OPAQUE    = H5T_OPAQUE
+COMPOUND  = H5T_COMPOUND
+REFERENCE = H5T_REFERENCE
+ENUM      = H5T_ENUM
+VLEN      = H5T_VLEN
+ARRAY     = H5T_ARRAY
+
+# Enumeration H5T_sign_t
+SGN_NONE   = H5T_SGN_NONE
+SGN_2      = H5T_SGN_2
+
+# Enumeration H5T_order_t
+ORDER_LE    = H5T_ORDER_LE
+ORDER_BE    = H5T_ORDER_BE
+ORDER_VAX   = H5T_ORDER_VAX
+ORDER_NONE  = H5T_ORDER_NONE
+
+DIR_DEFAULT = H5T_DIR_DEFAULT
+DIR_ASCEND  = H5T_DIR_ASCEND
+DIR_DESCEND = H5T_DIR_DESCEND
+
+# Enumeration H5T_str_t
+STR_NULLTERM = H5T_STR_NULLTERM
+STR_NULLPAD  = H5T_STR_NULLPAD
+STR_SPACEPAD = H5T_STR_SPACEPAD
+
+# Enumeration H5T_norm_t
+NORM_IMPLIED = H5T_NORM_IMPLIED
+NORM_MSBSET = H5T_NORM_MSBSET
+NORM_NONE = H5T_NORM_NONE
+
+# Enumeration H5T_cset_t:
+CSET_ASCII = H5T_CSET_ASCII
+
+# Enumeration H5T_pad_t:
+PAD_ZERO = H5T_PAD_ZERO
+PAD_ONE = H5T_PAD_ONE
+PAD_BACKGROUND = H5T_PAD_BACKGROUND
+
+if sys.byteorder == "little":    # Custom python addition
+    ORDER_NATIVE = H5T_ORDER_LE
+else:
+    ORDER_NATIVE = H5T_ORDER_BE
+
+# --- Built-in HDF5 datatypes -------------------------------------------------
+
+# IEEE floating-point
+IEEE_F32LE = lockid(H5T_IEEE_F32LE)
+IEEE_F32BE = lockid(H5T_IEEE_F32BE)
+IEEE_F64LE = lockid(H5T_IEEE_F64LE)
+IEEE_F64BE = lockid(H5T_IEEE_F64BE)
+
+# Signed 2's complement integer types
+STD_I8LE  = lockid(H5T_STD_I8LE)
+STD_I16LE = lockid(H5T_STD_I16LE)
+STD_I32LE = lockid(H5T_STD_I32LE)
+STD_I64LE = lockid(H5T_STD_I64LE)
+
+STD_I8BE  = lockid(H5T_STD_I8BE)
+STD_I16BE = lockid(H5T_STD_I16BE)
+STD_I32BE = lockid(H5T_STD_I32BE)
+STD_I64BE = lockid(H5T_STD_I64BE)
+
+# Unsigned integers
+STD_U8LE  = lockid(H5T_STD_U8LE)
+STD_U16LE = lockid(H5T_STD_U16LE)
+STD_U32LE = lockid(H5T_STD_U32LE)
+STD_U64LE = lockid(H5T_STD_U64LE)
+
+STD_U8BE  = lockid(H5T_STD_U8BE)
+STD_U16BE = lockid(H5T_STD_U16BE)
+STD_U32BE = lockid(H5T_STD_U32BE)
+STD_U64BE = lockid(H5T_STD_U64BE)
+
+# Native types by bytesize
+NATIVE_INT8 = lockid(H5T_NATIVE_INT8)
+NATIVE_UINT8 = lockid(H5T_NATIVE_UINT8)
+NATIVE_INT16 = lockid(H5T_NATIVE_INT16)
+NATIVE_UINT16 = lockid(H5T_NATIVE_UINT16)
+NATIVE_INT32 = lockid(H5T_NATIVE_INT32)
+NATIVE_UINT32 = lockid(H5T_NATIVE_UINT32)
+NATIVE_INT64 = lockid(H5T_NATIVE_INT64)
+NATIVE_UINT64 = lockid(H5T_NATIVE_UINT64)
+NATIVE_FLOAT = lockid(H5T_NATIVE_FLOAT)
+NATIVE_DOUBLE = lockid(H5T_NATIVE_DOUBLE)
+
+# Unix time types
+UNIX_D32LE = lockid(H5T_UNIX_D32LE)
+UNIX_D64LE = lockid(H5T_UNIX_D64LE)
+UNIX_D32BE = lockid(H5T_UNIX_D32BE)
+UNIX_D64BE = lockid(H5T_UNIX_D64BE)
+
+# Reference types
+STD_REF_OBJ = lockid(H5T_STD_REF_OBJ)
+STD_REF_DSETREG = lockid(H5T_STD_REF_DSETREG)
+
+# Null terminated (C) and Fortran string types
+C_S1 = lockid(H5T_C_S1)
+FORTRAN_S1 = lockid(H5T_FORTRAN_S1)
+VARIABLE = H5T_VARIABLE
+
+# Custom Python object pointer type
+PYTHON_OBJECT = lockid(get_object_type())
+
+# 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
+        
+    Create a new HDF5 type object.  Legal class values are 
+    COMPOUND and OPAQUE.  Use enum_create for enums.
+    """
+
+    # HDF5 versions 1.6.X segfault with anything else
+    if classtype != H5T_COMPOUND and classtype != H5T_OPAQUE:
+        raise ValueError("Class must be COMPOUND or OPAQUE.")
+
+    return typewrap(H5Tcreate(<H5T_class_t>classtype, size))
+
+ at sync
+def open(ObjectID group not None, char* name):
+    """(ObjectID group, STRING name) => TypeID
+
+    Open a named datatype from a file.
+    """
+    return typewrap(H5Topen(group.id, name))
+
+ at sync
+def array_create(TypeID base not None, object dims_tpl):
+    """(TypeID base, TUPLE dimensions) => TypeArrayID
+
+    Create a new array datatype, using and HDF5 parent type and
+    dimensions given via a tuple of positive integers.  "Unlimited" 
+    dimensions are not allowed.
+    """
+    cdef hsize_t rank
+    cdef hsize_t *dims = NULL
+
+    require_tuple(dims_tpl, 0, -1, "dims_tpl")
+    rank = len(dims_tpl)
+    dims = <hsize_t*>emalloc(sizeof(hsize_t)*rank)
+
+    try:
+        convert_tuple(dims_tpl, dims, rank)
+        return TypeArrayID(H5Tarray_create(base.id, rank, dims, NULL))
+    finally:
+        efree(dims)
+
+ at sync
+def enum_create(TypeID base not None):
+    """(TypeID base) => TypeID
+
+    Create a new enumerated type based on an (integer) parent type.
+    """
+    return typewrap(H5Tenum_create(base.id))
+
+ at sync
+def vlen_create(TypeID base not None):
+    """(TypeID base) => TypeID
+
+    Create a new variable-length datatype, using any HDF5 type as a base.
+
+    Although the Python interface can manipulate these types, there is no
+    provision for reading/writing vlen data.
+    """
+    return typewrap(H5Tvlen_create(base.id))
+
+IF H5PY_18API:
+    @sync
+    def decode(char* buf):
+        """(STRING buf) => TypeID
+
+        Unserialize an HDF5 type.  You can also do this with the native
+        Python pickling machinery.
+        """
+        return typewrap(H5Tdecode(<unsigned char*>buf))
+
+# === Base type class =========================================================
+
+cdef class TypeID(ObjectID):
+
+    """
+        Base class for type identifiers (implements common operations)
+
+        * Hashable: If committed; in HDF5 1.8.X, also if locked
+        * Equality: Logical H5T comparison
+    """
+
+    def __hash__(self):
+        if self._hash is None:
+            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
+
+    property dtype:
+        """ A Numpy-style dtype object representing this object.
+        """
+        def __get__(self):
+            return self.py_dtype()
+
+    cdef object py_dtype(self):
+        raise TypeError("No NumPy equivalent for %s exists" % self.__class__.__name__)
+
+    IF H5PY_18API:
+        @sync
+        def commit(self, ObjectID group not None, char* name, PropID lcpl=None):
+            """(ObjectID group, STRING name, PropID lcpl=None)
+
+            Commit this (transient) datatype to a named datatype in a file.
+            If present, lcpl may be a link creation property list.
+            """
+            H5Tcommit2(group.id, name, self.id, pdefault(lcpl),
+                H5P_DEFAULT, H5P_DEFAULT)
+    ELSE:
+        @sync
+        def commit(self, ObjectID group not None, char* name):
+            """(ObjectID group, STRING name)
+
+            Commit this (transient) datatype to a named datatype in a file.
+            """
+            H5Tcommit(group.id, name, self.id)
+
+    @sync
+    def committed(self):
+        """() => BOOL is_comitted
+
+        Determine if a given type object is named (T) or transient (F).
+        """
+        return <bint>(H5Tcommitted(self.id))
+
+    @sync
+    def copy(self):
+        """() => TypeID
+
+        Create a copy of this type object.
+        """
+        return typewrap(H5Tcopy(self.id))
+
+    @sync
+    def equal(self, TypeID typeid):
+        """(TypeID typeid) => BOOL
+
+        Logical comparison between datatypes.  Also called by
+        Python's "==" operator.
+        """
+        return <bint>(H5Tequal(self.id, typeid.id))
+
+    @sync
+    def lock(self):
+        """()
+
+        Lock this datatype, which makes it immutable and indestructible.
+        Once locked, it can't be unlocked.
+        """
+        H5Tlock(self.id)
+        self._locked = 1
+
+    @sync
+    def get_class(self):
+        """() => INT classcode
+
+        Determine the datatype's class code.
+        """
+        return <int>H5Tget_class(self.id)
+
+    @sync
+    def set_size(self, size_t size):
+        """(UINT size)
+
+        Set the total size of the datatype, in bytes.
+        """
+        H5Tset_size(self.id, size)
+
+    @sync
+    def get_size(self):
+        """ () => INT size
+
+            Determine the total size of a datatype, in bytes.
+        """
+        return H5Tget_size(self.id)
+
+    @sync
+    def get_super(self):
+        """() => TypeID
+
+        Determine the parent type of an array, enumeration or vlen datatype.
+        """
+        return typewrap(H5Tget_super(self.id))
+
+    @sync
+    def detect_class(self, int classtype):
+        """(INT classtype) => BOOL class_is_present
+
+        Determine if a member of the given class exists in a compound
+        datatype.  The search is recursive.
+        """
+        return <bint>(H5Tdetect_class(self.id, <H5T_class_t>classtype))
+
+    @sync
+    def _close(self):
+        """()
+
+        Close this datatype.  If it's locked, nothing happens.
+
+        You shouldn't ordinarily need to call this function; datatype
+        objects are automatically closed when they're deallocated.
+        """
+        if not self._locked:
+            H5Tclose(self.id)
+
+    IF H5PY_18API:
+        @sync
+        def encode(self):
+            """() => STRING
+
+            Serialize an HDF5 type.  Bear in mind you can also use the
+            native Python pickle/unpickle machinery to do this.  The
+            returned string may contain binary values, including NULLs.
+            """
+            cdef size_t nalloc = 0
+            cdef char* buf = NULL
+
+            H5Tencode(self.id, NULL, &nalloc)
+            buf = <char*>emalloc(sizeof(char)*nalloc)
+            try:
+                H5Tencode(self.id, <unsigned char*>buf, &nalloc)
+                pystr = PyString_FromStringAndSize(buf, nalloc)
+            finally:
+                efree(buf)
+
+            return pystr
+
+    IF H5PY_18API:
+        # Enable pickling
+
+        def __reduce__(self):
+            return (type(self), (-1,), self.encode())
+
+        @sync
+        def __setstate__(self, char* state):
+            self.id = H5Tdecode(<unsigned char*>state)
+
+
+# === Top-level classes (inherit directly from TypeID) ========================
+
+cdef class TypeArrayID(TypeID):
+
+    """
+        Represents an array datatype
+    """
+
+    @sync
+    def get_array_ndims(self):
+        """() => INT rank
+
+        Get the rank of the given array datatype.
+        """
+        return H5Tget_array_ndims(self.id)
+
+    @sync
+    def get_array_dims(self):
+        """() => TUPLE dimensions
+
+        Get the dimensions of the given array datatype as
+        a tuple of integers.
+        """
+        cdef hsize_t rank   
+        cdef hsize_t* dims = NULL
+
+        rank = H5Tget_array_dims(self.id, NULL, NULL)
+        dims = <hsize_t*>emalloc(sizeof(hsize_t)*rank)
+        try:
+            H5Tget_array_dims(self.id, dims, NULL)
+            return convert_dims(dims, rank)
+        finally:
+            efree(dims)
+
+    cdef object py_dtype(self):
+        # Numpy translation function for array types
+        cdef TypeID tmp_type
+        tmp_type = self.get_super()
+
+        base_dtype = tmp_type.py_dtype()
+
+        shape = self.get_array_dims()
+        return dtype( (base_dtype, shape) )
+
+
+cdef class TypeOpaqueID(TypeID):
+
+    """
+        Represents an opaque type
+    """
+
+    @sync
+    def set_tag(self, char* tag):
+        """(STRING tag)
+
+        Set a string describing the contents of an opaque datatype.
+        Limited to 256 characters.
+        """
+        H5Tset_tag(self.id, tag)
+
+    @sync
+    def get_tag(self):
+        """() => STRING tag
+
+        Get the tag associated with an opaque datatype.
+        """
+        cdef char* buf = NULL
+
+        try:
+            buf = H5Tget_tag(self.id)
+            assert buf != NULL
+            tag = buf
+            return tag
+        finally:
+            free(buf)
+
+    cdef object py_dtype(self):
+        # Numpy translation function for opaque types
+        return dtype("|V" + str(self.get_size()))
+
+cdef class TypeStringID(TypeID):
+
+    """
+        String datatypes, both fixed and vlen.
+    """
+
+    @sync
+    def is_variable_str(self):
+        """() => BOOL is_variable
+
+        Determine if the given string datatype is a variable-length string.
+        """
+        return <bint>(H5Tis_variable_str(self.id))
+
+    @sync
+    def get_cset(self):
+        """() => INT character_set
+
+        Retrieve the character set used for a string.
+        """
+        return <int>H5Tget_cset(self.id)
+
+    @sync
+    def set_cset(self, int cset):
+        """(INT character_set)
+
+        Set the character set used for a string.
+        """
+        H5Tset_cset(self.id, <H5T_cset_t>cset)
+
+    @sync
+    def get_strpad(self):
+        """() => INT padding_type
+
+        Get the padding type.  Legal values are:
+
+        STR_NULLTERM
+            NULL termination only (C style)
+
+        STR_NULLPAD
+            Pad buffer with NULLs
+
+        STR_SPACEPAD
+            Pad buffer with spaces (FORTRAN style)
+        """
+        return <int>H5Tget_strpad(self.id)
+
+    @sync
+    def set_strpad(self, int pad):
+        """(INT pad)
+
+        Set the padding type.  Legal values are:
+
+        STR_NULLTERM
+            NULL termination only (C style)
+
+        STR_NULLPAD
+            Pad buffer with NULLs
+
+        STR_SPACEPAD
+            Pad buffer with spaces (FORTRAN style)
+        """
+        H5Tset_strpad(self.id, <H5T_str_t>pad)
+
+    cdef object py_dtype(self):
+        # Numpy translation function for string types
+        if self.is_variable_str():
+            return py_new_vlen(str)
+
+        return dtype("|S" + str(self.get_size()))
+
+cdef class TypeVlenID(TypeID):
+
+    """
+        Non-string vlen datatypes.
+    """
+    pass
+
+cdef class TypeTimeID(TypeID):
+
+    """
+        Unix-style time_t (deprecated)
+    """
+    pass
+
+cdef class TypeBitfieldID(TypeID):
+
+    """
+        HDF5 bitfield type
+    """
+    pass
+
+cdef class TypeReferenceID(TypeID):
+
+    """
+        HDF5 object or region reference
+    """
+    pass
+
+
+# === Numeric classes (integers and floats) ===================================
+
+cdef class TypeAtomicID(TypeID):
+
+    """
+        Base class for atomic datatypes (float or integer)
+    """
+
+    @sync
+    def get_order(self):
+        """() => INT order
+
+        Obtain the byte order of the datatype; one of:
+
+        - ORDER_LE
+        - ORDER_BE
+        """
+        return <int>H5Tget_order(self.id)
+
+    @sync
+    def set_order(self, int order):
+        """(INT order)
+
+        Set the byte order of the datatype; one of:
+
+        - ORDER_LE
+        - ORDER_BE
+        """
+        H5Tset_order(self.id, <H5T_order_t>order)
+
+    @sync
+    def get_precision(self):
+        """() => UINT precision
+
+        Get the number of significant bits (excludes padding).
+        """
+        return H5Tget_precision(self.id)
+
+    @sync
+    def set_precision(self, size_t precision):
+        """(UINT precision)
+            
+        Set the number of significant bits (excludes padding).
+        """
+        H5Tset_precision(self.id, precision)
+
+    @sync
+    def get_offset(self):
+        """() => INT offset
+
+        Get the offset of the first significant bit.
+        """
+        return H5Tget_offset(self.id)
+
+    @sync
+    def set_offset(self, size_t offset):
+        """(UINT offset)
+
+        Set the offset of the first significant bit.
+        """
+        H5Tset_offset(self.id, offset)
+
+    @sync
+    def get_pad(self):
+        """() => (INT lsb_pad_code, INT msb_pad_code)
+
+        Determine the padding type.  Possible values are:
+
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
+        """
+        cdef H5T_pad_t lsb
+        cdef H5T_pad_t msb
+        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)
+
+        Set the padding type.  Possible values are:
+
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
+        """
+        H5Tset_pad(self.id, <H5T_pad_t>lsb, <H5T_pad_t>msb)
+
+
+cdef class TypeIntegerID(TypeAtomicID):
+
+    """
+        Integer atomic datatypes
+    """
+
+    @sync
+    def get_sign(self):
+        """() => INT sign
+
+        Get the "signedness" of the datatype; one of:
+
+        SGN_NONE
+            Unsigned
+
+        SGN_2
+            Signed 2's complement
+        """
+        return <int>H5Tget_sign(self.id)
+
+    @sync
+    def set_sign(self, int sign):
+        """(INT sign)
+
+        Set the "signedness" of the datatype; one of:
+
+        SGN_NONE
+            Unsigned
+
+        SGN_2
+            Signed 2's complement
+        """
+        H5Tset_sign(self.id, <H5T_sign_t>sign)
+
+    cdef object py_dtype(self):
+        # Translation function for integer types
+        return dtype( _order_map[self.get_order()] + 
+                      _sign_map[self.get_sign()] + str(self.get_size()) )
+
+
+cdef class TypeFloatID(TypeAtomicID):
+
+    """
+        Floating-point atomic datatypes
+    """
+
+    @sync
+    def get_fields(self):
+        """() => TUPLE field_info
+
+        Get information about floating-point bit fields.  See the HDF5
+        docs for a full description.  Tuple has the following members:
+
+        0. UINT spos
+        1. UINT epos
+        2. UINT esize
+        3. UINT mpos
+        4. UINT msize
+        """
+        cdef size_t spos, epos, esize, mpos, msize
+        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)
+
+        Set floating-point bit fields.  Refer to the HDF5 docs for
+        argument definitions.
+        """
+        H5Tset_fields(self.id, spos, epos, esize, mpos, msize)
+
+    @sync
+    def get_ebias(self):
+        """() => UINT ebias
+
+        Get the exponent bias.
+        """
+        return H5Tget_ebias(self.id)
+
+    @sync
+    def set_ebias(self, size_t ebias):
+        """(UINT ebias)
+
+        Set the exponent bias.
+        """
+        H5Tset_ebias(self.id, ebias)
+
+    @sync
+    def get_norm(self):
+        """() => INT normalization_code
+
+        Get the normalization strategy.  Legal values are:
+
+        - NORM_IMPLIED
+        - NORM_MSBSET
+        - NORM_NONE
+        """
+        return <int>H5Tget_norm(self.id)
+
+    @sync
+    def set_norm(self, int norm):
+        """(INT normalization_code)
+
+        Set the normalization strategy.  Legal values are:
+
+        - NORM_IMPLIED
+        - NORM_MSBSET
+        - NORM_NONE
+        """
+        H5Tset_norm(self.id, <H5T_norm_t>norm)
+
+    @sync
+    def get_inpad(self):
+        """() => INT pad_code
+
+        Determine the internal padding strategy.  Legal values are:
+
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
+        """
+        return <int>H5Tget_inpad(self.id)
+
+    @sync
+    def set_inpad(self, int pad_code):
+        """(INT pad_code)
+
+        Set the internal padding strategy.  Legal values are:
+
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
+        """
+        H5Tset_inpad(self.id, <H5T_pad_t>pad_code)
+
+    cdef object py_dtype(self):
+        # Translation function for floating-point types
+        return dtype( _order_map[self.get_order()] + "f" + \
+                      str(self.get_size()) )
+
+
+# === Composite types (enums and compound) ====================================
+
+cdef class TypeCompositeID(TypeID):
+
+    """
+        Base class for enumerated and compound types.
+    """
+
+    @sync
+    def get_nmembers(self):
+        """() => INT number_of_members
+
+        Determine the number of members in a compound or enumerated type.
+        """
+        return H5Tget_nmembers(self.id)
+
+    @sync
+    def get_member_name(self, int member):
+        """(INT member) => STRING name
+        
+        Determine the name of a member of a compound or enumerated type,
+        identified by its index (0 <= member < nmembers).
+        """
+        cdef char* name
+        name = NULL
+
+        if member < 0:
+            raise ValueError("Member index must be non-negative.")
+
+        try:
+            name = H5Tget_member_name(self.id, member)
+            assert name != NULL
+            pyname = name
+        finally:
+            free(name)
+
+        return pyname
+
+    @sync
+    def get_member_index(self, char* name):
+        """(STRING name) => INT index
+
+        Determine the index of a member of a compound or enumerated datatype
+        identified by a string name.
+        """
+        return H5Tget_member_index(self.id, name)
+
+
+cdef class TypeCompoundID(TypeCompositeID):
+
+    """
+        Represents a compound datatype
+    """
+
+
+    @sync
+    def get_member_class(self, int member):
+        """(INT member) => INT class
+
+        Determine the datatype class of the member of a compound type,
+        identified by its index (0 <= member < nmembers).
+        """
+        if member < 0:
+            raise ValueError("Member index must be non-negative.")
+        return H5Tget_member_class(self.id, member)
+
+
+    @sync
+    def get_member_offset(self, int member):
+        """(INT member) => INT offset
+
+        Determine the offset, in bytes, of the beginning of the specified
+        member of a compound datatype.
+        """
+        if member < 0:
+            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
+
+        Create a copy of a member of a compound datatype, identified by its
+        index.
+        """
+        if member < 0:
+            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)
+
+        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(self.id, name, offset, field.id)
+
+    @sync
+    def pack(self):
+        """()
+
+        Recursively removes padding (introduced on account of e.g. compiler
+        alignment rules) from a compound datatype.
+        """
+        H5Tpack(self.id)
+
+    cdef object py_dtype(self):
+
+        cdef TypeID tmp_type
+        cdef list field_names
+        cdef list field_types
+        cdef int nfields
+        field_names = []
+        field_types = []
+        nfields = self.get_nmembers()
+
+        # First step: read field names and their Numpy dtypes into 
+        # two separate arrays.
+        for i from 0 <= i < nfields:
+            tmp_type = self.get_member_type(i)
+            field_names.append(self.get_member_name(i))
+            field_types.append(tmp_type.py_dtype())
+
+
+        # 1. Check if it should be converted to a complex number
+        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
+            blen = int(bstring[2:])
+            nstring = bstring[0] + "c" + str(2*blen)
+            typeobj = dtype(nstring)
+
+        # 2. Otherwise, read all fields of the compound type, in HDF5 order.
+        else:
+            typeobj = dtype(zip(field_names, field_types))
+
+        return typeobj
+
+cdef class TypeEnumID(TypeCompositeID):
+
+    """
+        Represents an enumerated type
+    """
+
+    cdef int enum_convert(self, long long *buf, int reverse) except -1:
+        # Convert the long long value in "buf" to the native representation
+        # of this (enumerated) type.  Conversion performed in-place.
+        # Reverse: false => llong->type; true => type->llong
+
+        cdef hid_t basetype
+        cdef H5T_class_t class_code
+
+        class_code = H5Tget_class(self.id)
+        if class_code != H5T_ENUM:
+            raise ValueError("This type (class %d) is not of class ENUM" % class_code)
+
+        basetype = H5Tget_super(self.id)
+        assert basetype > 0
+
+        try:
+            if not reverse:
+                H5Tconvert(H5T_NATIVE_LLONG, basetype, 1, buf, NULL, H5P_DEFAULT)
+            else:
+                H5Tconvert(basetype, H5T_NATIVE_LLONG, 1, buf, NULL, H5P_DEFAULT)
+        finally:
+            H5Tclose(basetype)
+
+    @sync
+    def enum_insert(self, char* name, long long value):
+        """(STRING name, INT/LONG value)
+
+        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 long long buf
+
+        buf = value
+        self.enum_convert(&buf, 0)
+        H5Tenum_insert(self.id, name, &buf)
+
+    @sync
+    def enum_nameof(self, long long value):
+        """(LONG 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 in length.
+        """
+        cdef herr_t retval
+        cdef char name[1024]
+        cdef long long buf
+
+        buf = value
+        self.enum_convert(&buf, 0)
+        retval = H5Tenum_nameof(self.id, &buf, name, 1024)
+        assert retval >= 0
+        retstring = name
+        return retstring
+
+    @sync
+    def enum_valueof(self, char* name):
+        """(STRING name) => LONG value
+
+        Get the value associated with an enum name.
+        """
+        cdef long long buf
+
+        H5Tenum_valueof(self.id, name, &buf)
+        self.enum_convert(&buf, 1)
+        return buf
+
+    @sync
+    def get_member_value(self, int idx):
+        """(UINT index) => LONG value
+
+        Determine the value for the member at the given zero-based index.
+        """
+        cdef herr_t retval
+        cdef hid_t ptype
+        cdef long long val
+        ptype = 0
+
+        if idx < 0:
+            raise ValueError("Index must be non-negative.")
+
+        H5Tget_member_value(self.id, idx, &val)
+        self.enum_convert(&val, 1)
+        return val
+
+    cdef object py_dtype(self):
+        # Translation function for enum types
+
+        cdef TypeID basetype = self.get_super()
+
+        nmembers = self.get_nmembers()
+        members = {}
+
+        for idx in xrange(nmembers):
+            name = self.get_member_name(idx)
+            val = self.get_member_value(idx) 
+            members[name] = val
+
+        ref = {cfg._f_name: 0, cfg._t_name: 1}
+
+        # Boolean types have priority over standard enums
+        if members == ref:
+            return dtype('bool')
+    
+        return py_new_enum(basetype.py_dtype(), members)
+
+
+# === Translation from NumPy dtypes to HDF5 type objects ======================
+
+# The following series of native-C functions each translate a specific class
+# of NumPy dtype into an HDF5 type object.  The result is guaranteed to be
+# transient and unlocked.
+
+cdef dict _float_le = {4: H5T_IEEE_F32LE, 8: H5T_IEEE_F64LE}
+cdef dict _float_be = {4: H5T_IEEE_F32BE, 8: H5T_IEEE_F64BE}
+cdef dict _float_nt = {4: H5T_NATIVE_FLOAT, 8: H5T_NATIVE_DOUBLE}
+
+cdef dict _int_le = {1: H5T_STD_I8LE, 2: H5T_STD_I16LE, 4: H5T_STD_I32LE, 8: H5T_STD_I64LE}
+cdef dict _int_be = {1: H5T_STD_I8BE, 2: H5T_STD_I16BE, 4: H5T_STD_I32BE, 8: H5T_STD_I64BE}
+cdef dict _int_nt = {1: H5T_NATIVE_INT8, 2: H5T_NATIVE_INT16, 4: H5T_NATIVE_INT32, 8: H5T_NATIVE_INT64}
+
+cdef dict _uint_le = {1: H5T_STD_U8LE, 2: H5T_STD_U16LE, 4: H5T_STD_U32LE, 8: H5T_STD_U64LE}
+cdef dict _uint_be = {1: H5T_STD_U8BE, 2: H5T_STD_U16BE, 4: H5T_STD_U32BE, 8: H5T_STD_U64BE}
+cdef dict _uint_nt = {1: H5T_NATIVE_UINT8, 2: H5T_NATIVE_UINT16, 4: H5T_NATIVE_UINT32, 8: H5T_NATIVE_UINT64} 
+
+cdef TypeFloatID _c_float(dtype dt):
+    # Floats (single and double)
+    cdef hid_t tid
+
+    if dt.byteorder == c'<':
+        tid =  _float_le[dt.elsize]
+    elif dt.byteorder == c'>':
+        tid =  _float_be[dt.elsize]
+    else:
+        tid =  _float_nt[dt.elsize]
+
+    return TypeFloatID(H5Tcopy(tid))
+
+cdef TypeIntegerID _c_int(dtype dt):
+    # Integers (ints and uints)
+    cdef hid_t tid
+
+    if dt.kind == c'i':
+        if dt.byteorder == c'<':
+            tid = _int_le[dt.elsize]
+        elif dt.byteorder == c'>':
+            tid = _int_be[dt.elsize]
+        else:
+            tid = _int_nt[dt.elsize]
+    elif dt.kind == c'u':
+        if dt.byteorder == c'<':
+            tid = _uint_le[dt.elsize]
+        elif dt.byteorder == c'>':
+            tid = _uint_be[dt.elsize]
+        else:
+            tid = _uint_nt[dt.elsize]
+    else:
+        raise TypeError('Illegal int kind "%s"' % dt.kind)
+
+    return TypeIntegerID(H5Tcopy(tid))
+
+cdef TypeEnumID _c_enum(dtype dt, dict vals):
+    # Enums
+    cdef TypeIntegerID base
+    cdef TypeEnumID out
+
+    base = _c_int(dt)
+
+    out = TypeEnumID(H5Tenum_create(base.id))
+    for name in sorted(vals):
+        out.enum_insert(name, vals[name])
+    return out
+
+cdef TypeEnumID _c_bool(dtype dt):
+    # Booleans
+    global cfg
+
+    cdef TypeEnumID out
+    out = TypeEnumID(H5Tenum_create(H5T_NATIVE_INT8))
+
+    out.enum_insert(cfg._f_name, 0)
+    out.enum_insert(cfg._t_name, 1)
+
+    return out
+
+cdef TypeArrayID _c_array(dtype dt, int logical):
+    # Arrays
+    cdef dtype base
+    cdef TypeID type_base
+    cdef tuple shape
+
+    base, shape = dt.subdtype
+    type_base = py_create(base, logical=logical)
+    return array_create(type_base, shape)
+
+cdef TypeOpaqueID _c_opaque(dtype dt):
+    # Opaque
+    return TypeOpaqueID(H5Tcreate(H5T_OPAQUE, dt.itemsize))
+
+cdef TypeStringID _c_string(dtype dt):
+    # Strings (fixed-length)
+    cdef hid_t tid
+
+    tid = H5Tcopy(H5T_C_S1)
+    H5Tset_size(tid, dt.itemsize)
+    H5Tset_strpad(tid, H5T_STR_NULLPAD)
+    return TypeStringID(tid)
+
+cdef TypeCompoundID _c_complex(dtype dt):
+    # Complex numbers (names depend on cfg)
+    global cfg
+
+    cdef hid_t tid, tid_sub
+    cdef size_t size, off_r, off_i
+
+    cdef size_t length = dt.itemsize
+    cdef char byteorder = dt.byteorder
+
+    if length == 8:
+        size = h5py_size_n64
+        off_r = h5py_offset_n64_real
+        off_i = h5py_offset_n64_imag
+        if byteorder == c'<':
+            tid_sub = H5T_IEEE_F32LE
+        elif byteorder == c'>':
+            tid_sub = H5T_IEEE_F32BE
+        else:
+            tid_sub = H5T_NATIVE_FLOAT
+    elif length == 16:
+        size = h5py_size_n128
+        off_r = h5py_offset_n128_real
+        off_i = h5py_offset_n128_imag
+        if byteorder == c'<':
+            tid_sub = H5T_IEEE_F64LE
+        elif byteorder == c'>':
+            tid_sub = H5T_IEEE_F64BE
+        else:
+            tid_sub = H5T_NATIVE_DOUBLE
+    else:
+        raise TypeError("Illegal length %d for complex dtype" % length)
+
+    tid = H5Tcreate(H5T_COMPOUND, size)
+    H5Tinsert(tid, cfg._r_name, off_r, tid_sub)
+    H5Tinsert(tid, cfg._i_name, off_i, tid_sub)
+
+    return TypeCompoundID(tid)
+
+cdef TypeCompoundID _c_compound(dtype dt, int logical):
+    # Compound datatypes
+
+    cdef hid_t tid
+    cdef TypeID type_tmp
+    cdef dtype dt_tmp
+    cdef size_t offset
+
+    cdef dict fields = dt.fields
+    cdef tuple names = dt.names
+
+    tid = H5Tcreate(H5T_COMPOUND, dt.itemsize)
+
+    for name in names:
+        dt_tmp, offset = dt.fields[name]
+        type_tmp = py_create(dt_tmp, logical=logical)
+        H5Tinsert(tid, name, offset, type_tmp.id)
+
+    return TypeCompoundID(tid)
+
+cdef TypeOpaqueID _c_object(dtype dt):
+    # Object types are represented by a custom opaque type
+    # Currently no other logic is required
+    return PYTHON_OBJECT
+
+cdef TypeStringID _c_vlen_str(object basetype):
+    # Variable-length strings
+    cdef hid_t tid
+    tid = H5Tcopy(H5T_C_S1)
+    H5Tset_size(tid, H5T_VARIABLE)
+    return TypeStringID(tid)
+
+cpdef TypeID py_create(object dtype_in, bint logical=0):
+    """(OBJECT dtype_in, BOOL logical=False) => TypeID
+
+    Given a Numpy dtype object, generate a byte-for-byte memory-compatible
+    HDF5 datatype object.  The result is guaranteed to be transient and
+    unlocked.
+
+    Argument dtype_in may be a dtype object, or anything which can be
+    converted to a dtype, including strings like '<i4'.
+
+    logical
+        If this flag is set, instead of returning a byte-for-byte identical
+        representation of the type, the function returns the closest logically
+        appropriate HDF5 type.  For example, in the case of a "hinted" dtype
+        of kind "O" representing a string, it would return an HDF5 variable-
+        length string type.
+    """
+    cdef dtype dt = dtype(dtype_in)
+    cdef char kind = dt.kind
+
+    phil.acquire()
+    try:
+        # Float
+        if kind == c'f':
+            return _c_float(dt)
+        
+        # Integer
+        elif kind == c'u' or kind == c'i':
+
+            if logical:
+                # Check for an enumeration hint
+                enum_vals = py_get_enum(dt)
+                if enum_vals is not None:
+                    return _c_enum(dt, enum_vals)
+
+            return _c_int(dt)
+
+        # Complex
+        elif kind == c'c':
+            return _c_complex(dt)
+
+        # Compound
+        elif kind == c'V' and dt.names is not None:
+            return _c_compound(dt, logical)
+
+        # Array or opaque
+        elif kind == c'V':
+            if dt.subdtype is not None:
+                return _c_array(dt, logical)
+            else:
+                return _c_opaque(dt)
+
+        # String
+        elif kind == c'S':
+            return _c_string(dt)
+
+        # Boolean
+        elif kind == c'b':
+            return _c_bool(dt)
+
+        # Object types (including those with vlen hints)
+        elif kind == c'O':
+
+            if logical:
+                # Check for vlen hints
+                vlen = py_get_vlen(dt)
+                if vlen is not None:
+                    return _c_vlen_str(vlen)
+                raise TypeError("Object dtype has no native HDF5 equivalent")
+
+            return _c_object(dt)
+
+        # Unrecognized
+        else:
+            raise TypeError("No conversion path for dtype: %s" % repr(dt))
+
+    finally:
+        phil.release()
+
+cpdef dtype py_new_enum(dtype dt_in, dict enum_vals):
+    """ (DTYPE dt_in, DICT enum_vals) => DTYPE
+
+    Create a new NumPy integer dtype, which contains "hint" metadata for
+    an enum. Only dtypes of kind 'i' or 'u' are allowed.  The enum_vals
+    dict must consist only of string keys and integer values.
+    """
+
+    cdef dtype dt = dtype(dt_in)
+    if dt.kind != 'i' and dt.kind != 'u':
+        raise TypeError("Only integer types can be used as enums")
+
+    return dtype((dt, [( ({'vals': enum_vals},'enum'), dt )] ))
+    
+cpdef dict py_get_enum(object dt):
+    """ (DTYPE dt_in) => DICT
+
+    Determine the enum values associated with a "hinted" NumPy integer type.
+    Returns None if the type does not contain hints, or is of the wrong kind.
+    """
+    
+    if dt.kind != 'i' and dt.kind != 'u':
+        return None
+
+    if dt.fields is not None and 'enum' in dt.fields:
+        tpl = dt.fields['enum']
+        if len(tpl) == 3:
+            info_dict = tpl[2]
+            if 'vals' in info_dict:
+                return info_dict['vals']
+
+    return None
+
+cpdef dtype py_new_vlen(object kind):
+    """ (OBJECT kind) => DTYPE
+
+    Create a new NumPy object dtype, which contains "hint" metadata
+    identifying the proper HDF5 vlen base type.  For now, only the native
+    Python string object (str) is supported.
+    """
+    if kind is not str:
+        raise NotImplementedError("Only string vlens are currently supported")
+
+    return dtype(('O', [( ({'type': kind},'vlen'), 'O' )] ))
+
+cpdef object py_get_vlen(object dt_in):
+    """ (OBJECT dt_in) => TYPE
+
+    Determine the vlen "hint" type associated with a NumPy object type,
+    or None if the dtype does not contain a hint or is not of kind "O".
+    """
+    cdef dtype dt = dtype(dt_in)
+
+    if dt.kind != 'O':
+        return None
+
+    if dt.fields is not None and 'vlen' in dt.fields:
+        tpl = dt.fields['vlen']
+        if len(tpl) == 3:
+            hint_dict = tpl[2]
+            if 'type' in hint_dict:
+                return hint_dict['type']
+
+    return None
+
+        
+def _path_exists(TypeID src not None, TypeID dst not None):
+    """ Undocumented and unsupported """
+    cdef H5T_cdata_t *data
+    cdef H5T_conv_t result = NULL
+    
+    result = H5Tfind(src.id, dst.id, &data)
+    return result != NULL
+
+
+

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