[h5py] 143/455: Major documentation updates, more 1.8 additions

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:26 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 7ed470093b73d2da714ccf7378ceeb0f032ba6c7
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Wed Oct 22 03:16:09 2008 +0000

    Major documentation updates, more 1.8 additions
---
 docs_api/source/automod.py  |  86 ++++++++-
 docs_api/source/index.rst   | 200 +++++++++++++++++++++
 docs_api/source/low/h5.rst  |  30 +++-
 docs_api/source/low/h5a.rst |   1 -
 docs_api/source/low/h5g.rst |  53 ++++++
 docs_api/source/low/h5r.rst |  12 ++
 docs_api/source/low/h5s.rst |  57 ++++++
 docs_api/source/low/h5t.rst | 246 ++++++++++++++++++++++----
 h5py/_extras.py             |   2 +-
 h5py/defs.pxd               |  17 +-
 h5py/h5.pxd                 |   1 +
 h5py/h5.pyx                 |  56 +++---
 h5py/h5a.pyx                | 308 +++++++++++++++++++++-----------
 h5py/h5d.pyx                |  15 +-
 h5py/h5f.pyx                |  34 ++--
 h5py/h5g.pyx                | 163 +++++++++--------
 h5py/h5l.pyx                |  41 +++--
 h5py/h5o.pyx                | 162 +++++++++++++++--
 h5py/h5r.pyx                |  73 ++++----
 h5py/h5s.pyx                | 202 ++++++++++-----------
 h5py/h5t.pyx                | 423 ++++++++++++++++++++++++--------------------
 h5py/h5z.pyx                |  35 ++--
 h5py/highlevel.py           |   7 +-
 h5py/tests/test_h5a.py      |  12 +-
 h5py/tests/test_utils.py    |   5 -
 25 files changed, 1572 insertions(+), 669 deletions(-)

diff --git a/docs_api/source/automod.py b/docs_api/source/automod.py
index f2b9388..1d2bd78 100644
--- a/docs_api/source/automod.py
+++ b/docs_api/source/automod.py
@@ -3,10 +3,79 @@
     Requires patched version of autodoc.py
     http://bugs.python.org/issue3422
 """
+import re
+from functools import partial
+
+
+# --- Literal replacements for common class names ---
+
+class_types = { "ObjectID": "h5py.h5.ObjectID",
+                "GroupID": "h5py.h5g.GroupID",
+                "FileID": "h5py.h5f.FileID",
+                "DatasetID": "h5py.h5d.DatasetID",
+                "TypeID": "h5py.h5t.TypeID",
+                "dataset creation property list": "h5py.h5p.PropDCID",
+                "dataset access property list": "h5py.h5p.PropDAID",
+                "file creation property list": "h5py.h5p.PropFCID",
+                "file access property list": "h5py.h5p.PropFAID"}
+
+
+def mkclass(ipt, cls):
+    return ":class:`%s <%s>`" % (ipt, cls)
+
+replacements = {}
+replacements.update((x, mkclass(x,y)) for x, y in class_types.items())
+
+def replaceall(instring, rdict):
+    for orig, new in rdict.iteritems():
+        instring = instring.replace(orig, new)
+    return instring
+
+
+# --- "Smart" regexp replacements for UPPER_CASE constant names ---
+
+# Just the constant name, with or without the h5x. prefix.
+# Legal constant names are of the form CONST" or "h5p.CONST"
+const_only = r"(?:h5[a-z]{0,2}\.)?[A-Z_][A-Z0-9_]+"
+
+# Constant name embeddded in context (whitespace, parens, etc.)
+const_pattern = r"(?:^|\s+)\W?%s[\):\.,]?\.?(?:$|\s+)" % const_only
+
+# These match the regexp but are not valid constants
+const_exclude = r"HDF5|API|H5|H5A|H5D|H5F|H5P|H5Z|" + \
+                r"\sINT\s|\sUINT\s|\sSTRING\s|LONG|PHIL|GIL|TUPLE|LIST|FORTRAN|" +\
+                r"\sBOOL\s|\sNULL\s|\sNOT\s"
+
+def replace_constant(instring, mod, match):
+    """ Callback for re.sub, to generate the ReST for a constant in-place """
+
+    matchstring = instring[match.start():match.end()]
+
+    if re.search(const_exclude, matchstring):
+        return matchstring
+
+    display = re.findall(const_only, matchstring)[0]
+    target = display
+    if 'h5' in target:
+        target = 'h5py.%s' % target
+    else:
+        target = '%s.%s' % (mod, target)
+
+    rpl = ':data:`%s <%s>`' % (display, target)
+    print rpl
+    return re.sub(const_only, rpl, matchstring)
+
+
+# --- Sphinx extension code ---
 
 def setup(spx):
 
     def proc_doc(app, what, name, obj, options, lines):
+        """ Process docstrings for modules and routines """
+
+        final_lines = lines[:]
+
+        # Remove the signature lines from the docstring
         if what in ("function", "method") and lines[0].strip().startswith('('):
             doclines = []
             arglines = []
@@ -15,12 +84,23 @@ def setup(spx):
                 if len(line.strip()) == 0:
                     final_lines = doclines
                 final_lines.append(line)
-            lines[:] = final_lines
+
+        # Resolve class names, constants and modules
+        print name
+        if hasattr(obj, 'im_class'):
+            mod = obj.im_class.__module__
+        elif hasattr(obj, '__module__'):
+            mod = obj.__module__
+        else:
+            mod = ".".join(name.split('.')[0:2])  # i.e. "h5py.h5z"
+        lines[:] = [re.sub(const_pattern, partial(replace_constant, x, mod), x) for x in final_lines]
+        lines[:] = [replaceall(x, replacements) for x in lines]
 
     def proc_sig(app, what, name, obj, options, signature, return_annotation):
+        """ Auto-generate function signatures from docstrings """
 
         def getsig(docstring):
-            """ Get sig, return from a docstring, or None. """
+            """ Get (sig, return) from a docstring, or None. """
             if docstring is None or not docstring.strip().startswith('('):
                 return None
 
@@ -36,7 +116,7 @@ def setup(spx):
                 ret = " -> "+ret
             else:
                 sig = sig[0]
-            if len(sig) == 2: sig = sig[0]+" "+sig[1]  # stupid bug in autodoc
+            if len(sig) == 2: sig = sig[0]+" "+sig[1]  # autodoc hates "()"
             return (sig, ret)
 
         if what not in ("function", "method"):
diff --git a/docs_api/source/index.rst b/docs_api/source/index.rst
new file mode 100644
index 0000000..f044c81
--- /dev/null
+++ b/docs_api/source/index.rst
@@ -0,0 +1,200 @@
+Low-level (``h5py.h5*``) guide
+==============================
+
+This is a general overview of the lowest-level API in h5py, the layer that
+calls into HDF5 directly.  A lot of effort has been put into making even this
+component useful in a Python context.  It provides the most general interface
+to HDF5, including the vast majority of the C library.
+
+Documentation for the high-level component (which is significantly easier to
+use) is `available here`__.
+
+__ http://h5py.alfven.org
+
+You'll probably also find the `official HDF5 documentation`__ useful as a guide
+to how the library itself operates.  In particular, the HDF5 User Guide is
+an excellent description of each major component.
+
+__ http://hdf.ncsa.uiuc.edu/HDF5/doc/index.html
+
+Version of this documentation
+-----------------------------
+
+.. automodule:: h5py.version
+
+Two major versions of HDF5 currently exist; the 1.6 and 1.8 series.  Rather
+than force you to use either version, h5py can be compiled in one of two
+"API compatibility levels".  When compiled against HDF5 1.6 (or 1.8, using the
+``--api=16`` compile-time switch), only HDF5 1.6 routines and structures are
+available.  When compiled against HDF5 1.8 (``--api=18``), many new features
+are available.
+
+The `1.6 mode`_ and `1.8 mode`_ are therefore documented separately.
+
+.. _`1.6 mode`: http://h5py.alfven.org/doc16
+.. _`1.8 mode`: http://h5py.alfven.org/doc18
+
+Despite the major differences between these two versions of HDF5, the
+signatures of all routines in the "1.6 API" mode of h5py are
+forward-compatible with the "1.8 API" mode.  Code written against the 1.6 mode
+should work fine when moving to 1.8.
+
+Low-level API reference
+=======================
+
+.. toctree::
+    :maxdepth: 1
+
+    low/h5
+    low/h5a
+    low/h5d
+    low/h5f
+    low/h5g
+    low/h5i
+    low/h5p
+    low/h5r
+    low/h5s
+    low/h5t
+    low/h5z
+
+Library organization
+====================
+
+Modules
+-------
+
+While HDF5 is a C library, and therefore uses on global namespace for all
+functions and constants, their naming scheme is designed to partition the API
+into modules of related code.  H5py uses this as a guide for the Python-side
+module organization.  For example, the Python wrapping of the HDF5 function
+``H5Dwrite`` is contained in module ``h5d``, while the Python equivalent of
+``H5Aiterate`` is in module ``h5a``.
+
+Identifier wrapping
+-------------------
+
+No matter how complete, a library full of C functions is not very fun to use.
+Additionally, since HDF5 identifiers are natively expressed as integers, their
+lifespan must be manually tracked by the library user.  This quickly becomes
+impossible for applications of even a moderate size; errors will lead to
+resource leaks or (in the worst case) accidentally invalidating identifiers.
+
+Rather than a straight C-API mapping, all HDF5 identifiers are presented as
+Python extension types.  The root type ``h5.ObjectID`` provides a container
+for an integer identifier, which allows Python reference counting to manage
+the lifespan of the identifer.  When no more references exist to the Python
+object, the HDF5 identifier is automatically closed.
+
+    >>> from h5py import h5s
+    >>> sid = h5s.create_simple( (2,3) )
+    >>> sid
+    67108866 [1] (U) SpaceID
+    >>> sid.id
+    67108866
+
+A side benefit is that many HDF5 functions take an identifier as their first
+argument.  These are naturally expressed as methods on an identifier object.
+For example, the HDF5 function``H5Dwrite`` becomes the method
+``h5d.DatasetID.write``.  Code using this technique is easier to write and
+maintain.
+
+    >>> sid.select_hyperslab((0,0),(2,2))
+    >>> sid.get_select_bounds()
+    ((0L, 0L), (1L, 1L))
+
+State & Hashing
+---------------
+
+Since the ``h5py.h5*`` family of modules is intended to be a straightforward
+interface to HDF5, almost all state information resides with the HDF5 library
+itself.  A side effect of this is that the hash and equality operations on
+ObjectID instances are determined by the status of the underlying HDF5 object.
+For example, if two GroupID objects with different HDF5 integer identifiers
+point to the same group, they will have identical hashes and compare equal.
+Among other things, this means that you can reliably use identifiers as keys
+in a dictionary.
+
+    >>> from h5py import h5f, h5g
+    >>> fid = h5f.open('foo.hdf5')
+    >>> grp1 = h5g.open(fid, '/')
+    >>> grp2 = h5g.open(fid, '/')
+    >>> grp1.id == grp2.id
+    False
+    >>> grp1 == grp2
+    True
+    >>> hash(grp1) == hash(grp2)
+    True
+    >>> x = {grp1: "The root group"}
+    >>> x[grp2]
+    'The root group'
+
+.. note::
+    Currently all subclasses of ObjectID are hashable, including "transient"
+    identifiers like datatypes.  A future version may restrict hashing to
+    "committed", file-resident objects.
+
+Data Conversion
+===============
+
+The natural numerical layer between h5py and the Python user is NumPy.  It
+provides the mechanism to transfer large datasets between HDF5 and Python
+analysis routines.  Additionally, its type infrastructure ("dtype" objects)
+closely matches the HDF5 hierarchy of types.  With very few exceptions, there
+is good mapping between NumPy dtypes and HDF5 basic types.
+
+The actual conversion between datatypes is performed by the optimised routines
+inside the HDF5 library; all h5py does is provide the mapping between NumPy
+and HDF5 type objects.  Because the HDF5 typing system is more comprehensive
+than the NumPy system, this is an asymmetrical process. 
+
+Translating from an HDF5 datatype object to a dtype results in the closest
+standard NumPy representation of the datatype:
+
+    >>> from h5py import h5t
+    >>> h5t.STD_I32LE
+    50331712 [1] (L) TypeIntegerID int32
+    >>> h5t.STD_I32LE.dtype 
+    dtype('int32')
+
+In the vast majority of cases the two datatypes will have exactly identical
+binary layouts, but not always.  For example, an HDF5 integer can have
+additional leading or trailing padding, which has no NumPy equivalent.  In
+this case the dtype will capture the logical intent of the type (as a 32-bit
+signed integer), but not its layout.
+
+The reverse transformation (NumPy type to HDF5 type) is handled by a separate
+function.  It's guaranteed to result in an exact, binary-compatible
+representation:
+
+    >>> tid = h5t.py_create('=u8')
+    >>> tid
+    50331956 [1] (U) TypeIntegerID uint64
+
+The HDF5 library contains translation routines which can handle almost any
+conversion between types of the same class, including odd precisions and
+padding combinations.  This process is entirely transparent to the user.
+
+
+API Versioning
+==============
+
+HDF5 recently went though a major release, in the form of version 1.8.0.
+In addition to various stability improvements, it introduces a number of
+new and changed functions.  Rather than force people to use a particular
+version, h5py deals with this by specifying an "API compatibility" level.
+In "1.6" mode, the extension can be compiled with either 1.6.X or 1.8.X, and
+will function identically.  In this mode, only the functions from the 1.6.X
+series are exposed.  In "1.8" mode, new features and function signatures from
+HDF5 1.8.X are available.
+
+Currently, while h5py can be built in both modes, not many 1.8.X features are
+available.
+
+
+
+
+
+
+
+
+
diff --git a/docs_api/source/low/h5.rst b/docs_api/source/low/h5.rst
index 1afec92..9982fd6 100644
--- a/docs_api/source/low/h5.rst
+++ b/docs_api/source/low/h5.rst
@@ -2,6 +2,34 @@ Module H5
 =========
 
 .. automodule:: h5py.h5
-    :members:
+
+Library API
+-----------
+
+.. autofunction:: get_config
+.. autofunction:: get_phil
+.. autofunction:: loglevel
+.. autofunction:: get_libversion
+
+
+Base classes for library
+------------------------
+
 .. autoclass:: ObjectID
+.. autoclass:: H5Error
+.. autoclass:: H5PYConfig
+.. autoclass:: PHIL
 
+
+Error handling routines
+-----------------------
+
+Keep in mind that errors are already handled by Python exceptions.  These
+functions exist for low-level inspection of the HDF5 error stack.
+
+.. autofunction:: error_stack
+.. autofunction:: error_string
+.. autofunction:: clear
+
+.. autoclass:: ErrorStackElement
+    :members:
diff --git a/docs_api/source/low/h5a.rst b/docs_api/source/low/h5a.rst
index f2f59ec..2be39e1 100644
--- a/docs_api/source/low/h5a.rst
+++ b/docs_api/source/low/h5a.rst
@@ -3,4 +3,3 @@ Module H5A
 
 .. automodule:: h5py.h5a
     :members:
-
diff --git a/docs_api/source/low/h5g.rst b/docs_api/source/low/h5g.rst
index 88f06ad..e86d796 100644
--- a/docs_api/source/low/h5g.rst
+++ b/docs_api/source/low/h5g.rst
@@ -2,5 +2,58 @@ Module H5G
 ==========
 
 .. automodule:: h5py.h5g
+
+Functional API
+--------------
+
+.. autofunction:: open
+.. autofunction:: create
+.. autofunction:: iterate
+.. autofunction:: get_objinfo
+.. autoclass:: GroupStat
     :members:
 
+Group objects
+-------------
+
+.. autoclass:: GroupID
+    :members:
+
+Module constants
+----------------
+
+Object type codes
+~~~~~~~~~~~~~~~~~
+
+.. data:: LINK
+
+    Symbolic link
+
+.. data:: GROUP
+
+    HDF5 group
+
+.. data:: DATASET
+
+    HDF5 dataset
+
+.. data:: TYPE
+
+    Named (file-resident) datatype
+
+Link type codes
+~~~~~~~~~~~~~~~
+
+.. data:: LINK_HARD
+.. data:: LINK_SOFT
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs_api/source/low/h5r.rst b/docs_api/source/low/h5r.rst
index 8d9392b..38ddf6a 100644
--- a/docs_api/source/low/h5r.rst
+++ b/docs_api/source/low/h5r.rst
@@ -4,3 +4,15 @@ Module H5R
 .. automodule:: h5py.h5r
     :members:
 
+API constants
+-------------
+
+.. data:: OBJECT
+
+    Typecode for object references
+
+.. data:: DATASET_REGION
+
+    Typecode for dataset region references
+
+
diff --git a/docs_api/source/low/h5s.rst b/docs_api/source/low/h5s.rst
index 6516cc3..4fb83b8 100644
--- a/docs_api/source/low/h5s.rst
+++ b/docs_api/source/low/h5s.rst
@@ -2,5 +2,62 @@ Module H5S
 ==========
 
 .. automodule:: h5py.h5s
+
+Functional API
+--------------
+
+.. autofunction:: create
+.. autofunction:: create_simple
+.. autofunction:: decode
+
+Dataspace objects
+-----------------
+
+.. autoclass:: SpaceID
+    :show-inheritance:
     :members:
 
+Module constants
+----------------
+
+.. data:: ALL
+
+    Accepted in place of an actual datapace; means "every point"
+
+.. data:: UNLIMITED
+    
+    Indicates an unlimited maximum dimension
+
+Dataspace class codes
+~~~~~~~~~~~~~~~~~~~~~
+
+.. data:: NO_CLASS
+.. data:: SCALAR
+.. data:: SIMPLE
+
+Selection codes
+~~~~~~~~~~~~~~~
+
+.. data:: SELECT_NOOP
+.. data:: SELECT_SET
+.. data:: SELECT_OR
+.. data:: SELECT_AND
+.. data:: SELECT_XOR
+.. data:: SELECT_NOTB
+.. data:: SELECT_NOTA
+.. data:: SELECT_APPEND
+.. data:: SELECT_PREPEND
+.. data:: SELECT_INVALID
+
+Existing selection type
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. data:: SEL_ERROR
+.. data:: SEL_NONE
+.. data:: SEL_POINTS
+.. data:: SEL_HYPERSLABS
+.. data:: SEL_ALL
+
+
+
+
diff --git a/docs_api/source/low/h5t.rst b/docs_api/source/low/h5t.rst
index c5dee7d..f380abf 100644
--- a/docs_api/source/low/h5t.rst
+++ b/docs_api/source/low/h5t.rst
@@ -2,46 +2,216 @@ Module H5T
 ==========
 
 .. automodule:: h5py.h5t
+
+Functional API
+--------------
+
+.. autofunction:: py_create
+.. autofunction:: create
+.. autofunction:: open
+.. autofunction:: array_create
+.. autofunction:: enum_create
+.. autofunction:: vlen_create
+.. autofunction:: decode
+
+Type classes
+------------
+
+.. autoclass:: TypeID
+    :members:
+
+Atomic classes
+~~~~~~~~~~~~~~
+
+Atomic types are integers and floats.  Much of the functionality for each is
+inherited from the base class :class:`TypeAtomicID`.
+
+.. autoclass:: TypeAtomicID
+    :show-inheritance:
+    :members:
+    
+.. autoclass:: TypeIntegerID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeFloatID
+    :show-inheritance:
+    :members:
+
+Strings
+~~~~~~~
+
+.. autoclass:: TypeStringID
+    :show-inheritance:
+    :members:
+
+Compound Types
+~~~~~~~~~~~~~~
+
+Traditional compound type (like NumPy record type) and enumerated types share
+a base class, :class:`TypeCompositeID`.
+
+.. autoclass:: TypeCompositeID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeCompoundID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeEnumID
+    :show-inheritance:
+    :members:
+
+Other types
+~~~~~~~~~~~
+
+.. autoclass:: TypeArrayID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeOpaqueID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeVlenID
+    :show-inheritance:
     :members:
 
+.. autoclass:: TypeBitfieldID
+    :show-inheritance:
+    :members:
+
+.. autoclass:: TypeReferenceID
+    :show-inheritance:
+    :members:
+
+Predefined Datatypes
+--------------------
+
+These locked types are pre-allocated by the library.
+
+Floating-point
+~~~~~~~~~~~~~~
+
+.. data:: IEEE_F32LE
+.. data:: IEEE_F32BE
+.. data:: IEEE_F64LE
+.. data:: IEEE_F64BE
+
+Integer types
+~~~~~~~~~~~~~
+
+.. data:: STD_I8LE
+.. data:: STD_I16LE
+.. data:: STD_I32LE
+.. data:: STD_I64LE
+
+.. data:: STD_I8BE
+.. data:: STD_I16BE
+.. data:: STD_I32BE
+.. data:: STD_I64BE
+
+.. data:: STD_U8LE
+.. data:: STD_U16LE
+.. data:: STD_U32LE
+.. data:: STD_U64LE
+
+.. data:: STD_U8BE
+.. data:: STD_U16BE
+.. data:: STD_U32BE
+.. data:: STD_U64BE
+
+.. data:: NATIVE_INT8
+.. data:: NATIVE_UINT8
+.. data:: NATIVE_INT16
+.. data:: NATIVE_UINT16
+.. data:: NATIVE_INT32
+.. data:: NATIVE_UINT32
+.. data:: NATIVE_INT64
+.. data:: NATIVE_UINT64
+.. data:: NATIVE_FLOAT
+.. data:: NATIVE_DOUBLE 
+
+Other types
+~~~~~~~~~~~
+
+
+.. data:: STD_REF_OBJ
+
+    Object reference
+
+.. data:: STD_REF_DSETREG
+
+    Dataset region reference
+
+.. data:: C_S1
+
+    Null-terminated fixed-length string
+
+.. data:: FORTRAN_S1
+
+    Zero-padded fixed-length string
+    
+
 Module constants
 ----------------
 
-::
-
-    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
+Datatype class codes
+~~~~~~~~~~~~~~~~~~~~
+
+.. data:: NO_CLASS
+.. data:: INTEGER
+.. data:: FLOAT
+.. data:: TIME
+.. data:: STRING
+.. data:: BITFIELD
+.. data:: OPAQUE
+.. data:: COMPOUND
+.. data:: REFERENCE
+.. data:: ENUM
+.. data:: VLEN
+.. data:: ARRAY
+
+API Constants
+~~~~~~~~~~~~~
+
+.. data:: SGN_NONE
+.. data:: SGN_2
+
+.. data:: ORDER_LE
+.. data:: ORDER_BE
+.. data:: ORDER_VAX
+.. data:: ORDER_NONE
+.. data:: ORDER_NATIVE
+
+.. data:: DIR_DEFAULT
+.. data:: DIR_ASCEND
+.. data:: DIR_DESCEND
+
+.. data:: STR_NULLTERM
+.. data:: STR_NULLPAD
+.. data:: STR_SPACEPAD
+
+.. data:: NORM_IMPLIED
+.. data:: NORM_MSBSET
+.. data:: NORM_NONE
+
+.. data:: CSET_ASCII
+
+.. data:: PAD_ZERO
+.. data:: PAD_ONE
+.. data:: PAD_BACKGROUND
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5py/_extras.py b/h5py/_extras.py
index b1bb975..5df3626 100644
--- a/h5py/_extras.py
+++ b/h5py/_extras.py
@@ -20,7 +20,7 @@ phil = get_phil()
 def uw_apply(wrap, func):
     # Cython methods don't have a "module" attribute for some reason
     if hasattr(func, '__module__'):
-        update_wrapper(wrap, func)
+        update_wrapper(wrap, func, assigned=('__module__', '__name__', '__doc__'))
     else:
         update_wrapper(wrap, func, assigned=('__name__','__doc__'))
 
diff --git a/h5py/defs.pxd b/h5py/defs.pxd
index c57b5ff..8e3a4e3 100644
--- a/h5py/defs.pxd
+++ b/h5py/defs.pxd
@@ -578,17 +578,17 @@ IF H5PY_18API:
 
     # --- Components for the H5O_info_t struct ----------------------------------
 
-    cdef struct space:
+    ctypedef struct space:
       hsize_t total           #  Total space for storing object header in file 
       hsize_t meta            #  Space within header for object header metadata information 
       hsize_t mesg            #  Space within header for actual message information 
       hsize_t free            #  Free space within object header 
 
-    cdef struct mesg:
+    ctypedef struct mesg:
       unsigned long present   #  Flags to indicate presence of message type in header 
       unsigned long shared    #  Flags to indicate message type is shared in header 
 
-    cdef struct hdr:
+    ctypedef struct hdr:
       unsigned version        #  Version number of header format in file 
       unsigned nmesgs         #  Number of object header messages 
       unsigned nchunks        #  Number of object header chunks 
@@ -1225,6 +1225,11 @@ cdef extern from "hdf5.h":
       H5T_cset_t        cset        # Character set of attribute name
       hsize_t           data_size   # Size of raw data
 
+    herr_t  H5Adelete_by_name(hid_t loc_id, char *obj_name, char *attr_name,
+                hid_t lapl_id) except *
+    herr_t  H5Adelete_by_idx(hid_t loc_id, char *obj_name, H5_index_t idx_type,
+                H5_iter_order_t order, hsize_t n, hid_t lapl_id) except *
+
     hid_t H5Acreate_by_name(hid_t loc_id, char *obj_name, char *attr_name,
         hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t lapl_id) except *
  
@@ -1247,7 +1252,11 @@ cdef extern from "hdf5.h":
     herr_t H5Aget_info_by_idx(hid_t loc_id, char *obj_name, H5_index_t idx_type,
               H5_iter_order_t order, hsize_t n, H5A_info_t *ainfo, hid_t lapl_id) except *
 
+    ctypedef herr_t (*H5A_operator2_t)(hid_t location_id, char *attr_name,
+            H5A_info_t *ainfo, void *op_data) except 2
+    herr_t H5Aiterate2(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
+            hsize_t *n, H5A_operator2_t op, void *op_data) except *
 
-
+    hsize_t H5Aget_storage_size(hid_t attr_id) except *
 
 
diff --git a/h5py/h5.pxd b/h5py/h5.pxd
index c05246a..ae97d1e 100644
--- a/h5py/h5.pxd
+++ b/h5py/h5.pxd
@@ -43,6 +43,7 @@ cdef class ObjectID:
 
 cdef class SmartStruct:
     cdef object __weakref__
+    cdef object _title
 
 # 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 746afee..5f2d09e 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -14,7 +14,7 @@ __doc__ = \
     Common support and versioning module for the h5py HDF5 interface.
 
     This is an internal module which is designed to set up the library and
-    enable HDF5 exception handline.  It also enables debug logging, if the
+    enables HDF5 exception handling.  It also enables debug logging, if the
     library has been compiled with a nonzero debugging level.
 
     All exception classes and error handling functions are also in this module.
@@ -26,7 +26,6 @@ from python_exc cimport PyErr_SetString
 
 import atexit
 import threading
-import inspect
 
 IF H5PY_18API:
     ITER_INC    = H5_ITER_INC     # Increasing order
@@ -48,7 +47,7 @@ cdef class SmartStruct:
         return self._hash()
 
     def __richcmp__(self, object other, int how):
-        """Equality based on hash"""
+        """Equality based on hash.  If unhashable, NotImplemented."""
         cdef bint truthval = 0
 
         if how != 2 and how != 3:
@@ -58,18 +57,20 @@ cdef class SmartStruct:
             try:
                 truthval = hash(self) == hash(other)
             except TypeError:
-                pass
+                return NotImplemented
 
         if how == 2:
             return truthval
         return not truthval
 
-    def __repr__(self):
-        """ Prints a header followed by a list of public property values """
-        ostr = "=== %s ===\n%s"
-        attrstring = ["%s: %s" % x for x in inspect.getmembers(self) if not x[0].startswith('_')]
-        ostr %= (self.__class__.__name__, attrstring)
-        return ostr
+    def __str__(self):
+        """Format "name: value" pairs recursively for public attributes"""
+        mems = dict([(x, str(getattr(self, x))) for x in dir(self) if not x.startswith('_')])
+        for x in mems:
+            if isinstance(getattr(self,x), SmartStruct):
+                mems[x] = "\n"+"\n".join(["    "+y for y in mems[x].split("\n")[1:]])
+        hdr = "=== %s ===\n" % self.__class__.__name__ if self._title is None else self._title
+        return hdr+"\n".join(["%s: %s" % (name, mems[name]) for name in sorted(mems)])
 
 cdef class H5PYConfig:
 
@@ -123,7 +124,10 @@ Complex names: %s"""
 cdef H5PYConfig cfg = H5PYConfig()
 
 cpdef H5PYConfig get_config():
-    """ Get a reference to the global library configuration object """
+    """() => H5PYConfig
+
+    Get a reference to the global library configuration object
+    """
     return cfg
 
 # === Bootstrap diagnostics and threading, before decorator is defined ===
@@ -163,8 +167,8 @@ cdef class PHIL:
         acquire this lock first.  When h5py is built without thread awareness,
         all locking methods are no-ops.
 
-        This object supports the context manager protocol ("with" statement)
-        in addition to the methods acquire() and release().
+        You should NOT use this object in your code.  It's internal to the
+        library.
     """
 
     IF H5PY_THREADS:
@@ -199,7 +203,10 @@ cdef class PHIL:
 cdef PHIL phil = PHIL()
 
 cpdef PHIL get_phil():
-    """ Obtain a reference to the PHIL. """
+    """() => PHIL
+
+    Obtain a reference to the PHIL.
+    """
     global phil
     return phil
 
@@ -537,13 +544,14 @@ cdef class ErrorStackElement:
         Represents an entry in the HDF5 error stack.
         Modeled on the H5E_error_t struct.  All properties are read-only.
 
-        Atributes
-        maj_num:    INT major error number
-        min_num:    INT minor error number
-        func_name:  STRING name of failing function
-        file_name:  STRING name of file in which error occurreed
-        line:       UINT line number at which error occured
-        desc:       STRING description of error
+        Attributes:
+
+        * maj_num:    INT major error number
+        * min_num:    INT minor error number
+        * func_name:  STRING name of failing function
+        * file_name:  STRING name of file in which error occurreed
+        * line:       UINT line number at which error occured
+        * desc:       STRING description of error
     """
     cdef readonly int maj_num
     cdef readonly int min_num
@@ -590,11 +598,13 @@ cpdef object error_string():
     """ () => STRING error_stack
 
         Return a string representation of the current error condition.
-        Format is one line of the format 
+        Format is one line of the format::
+
             '<Description> (<Function name>: <error type>)'
 
         If the stack is more than one level deep, this is followed by a
-        header and then n lines of the format:
+        header and then n lines of the format::
+
             '    n: "<Description>" at <function name>'
     """
     cdef int stacklen
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index 29f1d69..ebffb91 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -14,7 +14,6 @@ __doc__=\
 """
     Provides access to the low-level HDF5 "H5A" attribute interface.
 """
-__all__ = ['create','AttrID']
 
 include "config.pxi"
 include "sync.pxi"
@@ -43,11 +42,13 @@ IF H5PY_18API:
         SpaceID space not None, *, char* obj_name='.', PropID lapl=None):
         """(ObjectID loc, STRING name, TypeID tid, SpaceID space, **kwds) => AttrID
             
-        Create a new attribute, attached to an existing object.
+        Create a new attribute, attached to an existing object.  Keywords:
 
-        Keywords:
-        * STRING obj_name (".")     Attach attribute to this group member instead
-        * PropID lapl (None)        Determines how obj_name is interpreted
+        STRING obj_name (".")
+            Attach attribute to this group member instead
+
+        PropID lapl (None)
+            Link access property list for obj_name
         """
 
         return AttrID(H5Acreate_by_name(loc.id, obj_name, name, tid.id,
@@ -75,13 +76,18 @@ IF H5PY_18API:
         """(ObjectID loc, STRING name=, INT index=, **kwds) => AttrID
        
         Open an attribute attached to an existing object.  You must specify
-        exactly one of either name or idx.
+        exactly one of either name or idx.  Keywords are:
+
+        STRING obj_name (".")
+            Attribute is attached to this group member
+
+        PropID lapl (None)
+            Link access property list for obj_name
+
+        INT index_type (h5.INDEX_NAME)
+
+        INT order (h5.ITER_NATIVE)
 
-        Keyword-only arguments:
-        * STRING obj_name ("."):         Attribute is attached to this group member
-        * PropID lapl (None):            Controls how "obj_name" is interpreted
-        * INT index_type (h5.INDEX_NAME) Controls how idx is interpreted
-        * INT order (h5.ITER_NATIVE)     Controls how idx is interpreted
         """
         if (name == NULL and index < 0) or (name != NULL and index >= 0):
             raise TypeError("Exactly one of name or idx must be specified")
@@ -116,19 +122,19 @@ ELSE:
 IF H5PY_18API:
     @sync
     def exists(ObjectID loc not None, char* name, *,
-                char* obj_name=NULL, PropID lapl=None):
+                char* obj_name=".", PropID lapl=None):
         """(ObjectID loc, STRING name, **kwds) => BOOL
 
-        Determine if an attribute is attached to this object.
+        Determine if an attribute is attached to this object.  Keywords:
 
-        Keywords:
-        * STRING obj_name:  Look for attributes attached to this group member
-        * PropID lapl:      Determines how "obj_name" is interpreted
+        STRING obj_name (".")
+            Look for attributes attached to this group member
+        
+        PropID lapl (None):
+            Link access property list for obj_name
         """
-        if obj_name is NULL:
-            return <bint>H5Aexists(loc.id, name)
-        else:
-            return <bint>H5Aexists_by_name(loc.id, obj_name, name, pdefault(lapl))
+        return <bint>H5Aexists_by_name(loc.id, obj_name, name, pdefault(lapl))
+
 ELSE:
     cdef herr_t cb_exist(hid_t loc_id, char* attr_name, void* ref_name) except 2:
 
@@ -140,7 +146,7 @@ ELSE:
     def exists(ObjectID loc not None, char* name):
         """(ObjectID loc, STRING name) => BOOL
 
-        Determine if an attribute named "ref_name" is attached to this object.
+        Determine if an attribute named "name" is attached to this object.
         """
         cdef unsigned int i=0
 
@@ -155,88 +161,60 @@ IF H5PY_18API:
         char* obj_name='.', PropID lapl=None):
         """(ObjectID loc, STRING name, STRING new_name, **kwds)
 
-        Rename an attribute.
+        Rename an attribute.  Keywords:
 
-        Keywords:
-        * STRING obj_name (".")     Attribute is attached to this group member
-        * PropID lapl (None)        Determines how obj_name is interpreted
+        STRING obj_name (".")
+            Attribute is attached to this group member
+
+        PropID lapl (None)
+            Link access property list for obj_name
         """
         H5Arename_by_name(loc.id, obj_name, name, new_name, pdefault(lapl))
 
- at sync
-def delete(ObjectID loc not None, char* name):
-    """(ObjectID loc, STRING name)
-
-    Remove an attribute from an object.
-    """
-    H5Adelete(loc.id, name)
-
- at sync
-def get_num_attrs(ObjectID loc not None):
-    """(ObjectID loc) => INT
-
-    Determine the number of attributes attached to an HDF5 object.
-    """
-    return H5Aget_num_attrs(loc.id)
-
-cdef class _AttrVisitor:
-
-    cdef object func
-    cdef object retval
-
-    def __init__(self, func):
-        self.func = func
-        self.retval = None
-
-cdef herr_t cb_attr_iter(hid_t loc_id, char* attr_name, void* vis_in) except 2:
-
-    cdef _AttrVisitor vis = <_AttrVisitor>vis_in
-
-    vis.retval = vis.func(attr_name)
-
-    if vis.retval is not None:
-        return 1
-    return 0
-
- at sync
-def iterate(ObjectID loc not None, object func, int index=0):
-    """(ObjectID loc, CALLABLE func, INT index=0) => <Return value from func>
-
-    Iterate a callable (function, method or callable object) over the
-    attributes attached to this object.  You callable should have the
-    signature:
+IF H5PY_18API:
+    @sync
+    def delete(ObjectID loc not None, char* name=NULL, int index=-1, *,
+        char* obj_name='.', int index_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
+        PropID lapl=None):
+        """(ObjectID loc, STRING name=, INT index=, **kwds)
 
-        func(STRING name) => Result
+        Remove an attribute from an object.  Specify exactly one of "name"
+        or "index". Keyword-only arguments:
 
-    Returning None continues iteration; returning anything else aborts
-    iteration and returns that value.
+        STRING obj_name (".")
+            Attribute is attached to this group member
 
-    Tip: To make your code forward-compatible with later versions of this
-    function (which supply more arguments to the callback), add an
-    additional ``*args`` parameter.
-    """
-    if index < 0:
-        raise ValueError("Starting index must be a non-negative integer.")
+        PropID lapl (None)
+            Link access property list for obj_name
 
-    cdef unsigned int i = index
-    cdef _AttrVisitor vis = _AttrVisitor(func)
+        INT index_type (h5.INDEX_NAME)
 
-    H5Aiterate(loc.id, &i, <H5A_operator_t>cb_attr_iter, <void*>vis)
+        INT order (h5.ITER_NATIVE)
+        """
+        if name != NULL and index < 0:
+            H5Adelete_by_name(loc.id, obj_name, name, pdefault(lapl))
+        elif name == NULL and index >= 0:
+            H5Adelete_by_idx(loc.id, obj_name, <H5_index_t>index_type,
+                <H5_iter_order_t>order, index, pdefault(lapl))
+        else:
+            raise TypeError("Exactly one of index or name must be specified.")
 
-    return vis.retval
+ELSE:
+    @sync
+    def delete(ObjectID loc not None, char* name):
+        """(ObjectID loc, STRING name)
 
+        Remove an attribute from an object.
+        """
+        H5Adelete(loc.id, name)
 
 @sync
-def py_listattrs(ObjectID loc not None):
-    """(ObjectID loc) => LIST
+def get_num_attrs(ObjectID loc not None):
+    """(ObjectID loc) => INT
 
-    Get a list of the names of the attributes attached to an object.
+    Determine the number of attributes attached to an HDF5 object.
     """
-    retlist = []
-    iterate(loc, retlist.append)
-    return retlist
-
-
+    return H5Aget_num_attrs(loc.id)
 
 
 IF H5PY_18API:
@@ -276,11 +254,19 @@ IF H5PY_18API:
         2. If you have the parent object, supply it and exactly one of
            either name or index.
 
-        Keywords:
-        * STRING obj_name (".")             Use this group member instead
-        * PropID lapl (None)                How "obj_name" is resolved
-        * INT index_type (h5.INDEX_NAME)    Which index to use
-        * INT order (h5.ITER_NATIVE)        What order the index is in
+        Keyword-only arguments:
+
+        STRING obj_name (".")
+            Use this group member instead
+
+        PropID lapl (None)
+            Link access property list for obj_name
+
+        INT index_type (h5.INDEX_NAME)
+            Which index to use
+
+        INT order (h5.ITER_NATIVE)
+            What order the index is in
         """
         cdef AttrInfo info = AttrInfo()
 
@@ -296,6 +282,110 @@ IF H5PY_18API:
 
         return info
 
+# === Iteration routines ======================================================
+
+cdef class _AttrVisitor:
+    cdef object func
+    cdef object retval
+    def __init__(self, func):
+        self.func = func
+        self.retval = None
+
+IF H5PY_18API:
+
+    cdef herr_t cb_attr_iter(hid_t loc_id, char* attr_name, H5A_info_t *ainfo, void* vis_in) except 2:
+        cdef _AttrVisitor vis = <_AttrVisitor>vis_in
+        cdef AttrInfo info = AttrInfo()
+        info.info = ainfo[0]
+        vis.retval = vis.func(attr_name, info)
+        if vis.retval is not None:
+            return 1
+        return 0
+
+    cdef herr_t cb_attr_simple(hid_t loc_id, char* attr_name, H5A_info_t *ainfo, void* vis_in) except 2:
+        cdef _AttrVisitor vis = <_AttrVisitor>vis_in
+        vis.retval = vis.func(attr_name)
+        if vis.retval is not None:
+            return 1
+        return 0
+
+    @sync
+    def iterate(ObjectID loc not None, object func, int index=0, *,
+        int index_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE, bint info=0):
+        """(ObjectID loc, CALLABLE func, INT index=0, **kwds) => <Return value from func>
+
+        Iterate a callable (function, method or callable object) over the
+        attributes attached to this object.  You callable should have the
+        signature::
+
+            func(STRING name) => Result
+
+        or if the keyword argument "info" is True::
+
+            func(STRING name, AttrInfo info) => Result
+
+        Returning None continues iteration; returning anything else aborts
+        iteration and returns that value.  Keywords:
+        
+        BOOL info (False)
+            Callback is func(STRING name, AttrInfo info), not func(STRING name)
+
+        INT index_type (h5.INDEX_NAME)
+            Which index to use
+
+        INT order (h5.ORDER_NATIVE)
+            Index order to use
+        """
+        if index < 0:
+            raise ValueError("Starting index must be a non-negative integer.")
+
+        cdef hsize_t i = index
+        cdef _AttrVisitor vis = _AttrVisitor(func)
+        cdef H5A_operator2_t cfunc
+
+        if info:
+            cfunc = cb_attr_iter
+        else:
+            cfunc = cb_attr_simple
+
+        H5Aiterate2(loc.id, <H5_index_t>index_type, <H5_iter_order_t>order,
+            &i, cfunc, <void*>vis)
+
+        return vis.retval
+
+ELSE:
+
+    cdef herr_t cb_attr_iter(hid_t loc_id, char* attr_name, void* vis_in) except 2:
+        cdef _AttrVisitor vis = <_AttrVisitor>vis_in
+        vis.retval = vis.func(attr_name)
+        if vis.retval is not None:
+            return 1
+        return 0
+
+    @sync
+    def iterate(ObjectID loc not None, object func, int index=0):
+        """(ObjectID loc, CALLABLE func, INT index=0) => <Return value from func>
+
+        Iterate a callable (function, method or callable object) over the
+        attributes attached to this object.  You callable should have the
+        signature::
+
+            func(STRING name) => Result
+
+        Returning None continues iteration; returning anything else aborts
+        iteration and returns that value.
+        """
+        if index < 0:
+            raise ValueError("Starting index must be a non-negative integer.")
+
+        cdef unsigned int i = index
+        cdef _AttrVisitor vis = _AttrVisitor(func)
+
+        H5Aiterate(loc.id, &i, <H5A_operator_t>cb_attr_iter, <void*>vis)
+
+        return vis.retval
+
+
 # === Attribute class & methods ===============================================
 
 cdef class AttrID(ObjectID):
@@ -304,13 +394,14 @@ cdef class AttrID(ObjectID):
         Logical representation of an HDF5 attribute identifier.
 
         Objects of this class can be used in any HDF5 function call
-        which expects an attribute identifier.  Additionally, all H5A*
+        which expects an attribute identifier.  Additionally, all ``H5A*``
         functions which always take an attribute instance as the first
         argument are presented as methods of this class.  
 
         * Hashable: No
         * Equality: Identifier comparison
     """
+
     property name:
         """The attribute's name"""
         def __get__(self):
@@ -343,8 +434,8 @@ cdef class AttrID(ObjectID):
         H5Aclose(self.id)
 
     @sync
-    def read(self, ndarray arr_obj not None):
-        """(NDARRAY arr_obj)
+    def read(self, ndarray arr not None):
+        """(NDARRAY arr)
 
         Read the attribute data into the given Numpy array.  Note that the 
         Numpy array must have the same shape as the HDF5 attribute, and a 
@@ -359,19 +450,19 @@ cdef class AttrID(ObjectID):
 
         try:
             space_id = H5Aget_space(self.id)
-            check_numpy_write(arr_obj, space_id)
+            check_numpy_write(arr, space_id)
 
-            mtype = py_create(arr_obj.dtype)
+            mtype = py_create(arr.dtype)
 
-            H5Aread(self.id, mtype.id, PyArray_DATA(arr_obj))
+            H5Aread(self.id, mtype.id, PyArray_DATA(arr))
 
         finally:
             if space_id:
                 H5Sclose(space_id)
 
     @sync
-    def write(self, ndarray arr_obj not None):
-        """(NDARRAY arr_obj)
+    def write(self, ndarray arr not None):
+        """(NDARRAY arr)
 
         Write the contents of a Numpy array too the attribute.  Note that
         the Numpy array must have the same shape as the HDF5 attribute, and
@@ -386,10 +477,10 @@ cdef class AttrID(ObjectID):
 
         try:
             space_id = H5Aget_space(self.id)
-            check_numpy_read(arr_obj, space_id)
-            mtype = py_create(arr_obj.dtype)
+            check_numpy_read(arr, space_id)
+            mtype = py_create(arr.dtype)
 
-            H5Awrite(self.id, mtype.id, PyArray_DATA(arr_obj))
+            H5Awrite(self.id, mtype.id, PyArray_DATA(arr))
 
         finally:
             if space_id:
@@ -399,7 +490,7 @@ cdef class AttrID(ObjectID):
     def get_name(self):
         """() => STRING name
 
-        Determine the name of an attribute, given its identifier.
+        Determine the name of this attribute.
         """
         cdef int blen
         cdef char* buf
@@ -432,8 +523,13 @@ cdef class AttrID(ObjectID):
         """
         return typewrap(H5Aget_type(self.id))
 
+    @sync
+    def get_storage_size(self):
+        """() => INT
 
-
+        Get the amount of storage required for this attribute.
+        """
+        return H5Aget_storage_size(self.id)
 
 
 
diff --git a/h5py/h5d.pyx b/h5py/h5d.pyx
index 48533b0..157b9af 100644
--- a/h5py/h5d.pyx
+++ b/h5py/h5d.pyx
@@ -116,8 +116,8 @@ cdef class DatasetID(ObjectID):
         shape:  Numpy-style shape tuple representing the dataspace
         rank:   Integer giving dataset rank
 
-        Hashable: Yes, unless anonymous
-        Equality: True HDF5 identity if unless anonymous
+        * Hashable: Yes, unless anonymous
+        * Equality: True HDF5 identity if unless anonymous
     """
 
     property dtype:
@@ -165,9 +165,9 @@ cdef class DatasetID(ObjectID):
             flexibility, you can specify dataspaces for the file and the Numpy
             object. Keyword dxpl may be a dataset transfer property list.
 
-            The provided Numpy array must be writable, C-contiguous, and own
-            its data.  If this is not the case, ValueError will be raised and 
-            the read will fail.
+            The provided Numpy array must be writable and C-contiguous.  If
+            this is not the case, ValueError will be raised and the read will
+            fail.
 
             It is your responsibility to ensure that the memory dataspace
             provided is compatible with the shape of the Numpy array.  Since a
@@ -214,9 +214,8 @@ cdef class DatasetID(ObjectID):
             Write data from a Numpy array to an HDF5 dataset. Keyword dxpl may 
             be a dataset transfer property list.
 
-            The provided Numpy array must be C-contiguous, and own its data.  
-            If this is not the case, ValueError will be raised and the read 
-            will fail.
+            The provided Numpy array must be C-contiguous.  If this is not the
+            case, ValueError will be raised and the read will fail.
 
             The actual write is non-blocking; the array object is temporarily
             marked read-only, but attempting to mutate it in another thread
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index 4434300..b92f238 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -153,15 +153,17 @@ def get_obj_count(object where=OBJ_ALL, int types=H5F_OBJ_ALL):
 
         Get the number of open objects.
 
-        * where:  Either a FileID instance representing an HDF5 file, or the
-                  special constant OBJ_ALL, to count objects in all files.
+        where:
+            Either a FileID instance representing an HDF5 file, or the
+            special constant OBJ_ALL, to count objects in all files.
 
-        * type: Specify what kinds of object to include.  May be one of OBJ_*, 
-                or any bitwise combination (e.g. OBJ_FILE | OBJ_ATTR).  
+        type:
+            Specify what kinds of object to include.  May be one of OBJ_*, 
+            or any bitwise combination (e.g. OBJ_FILE | OBJ_ATTR).  
 
-                The special value OBJ_ALL matches all object types, and 
-                OBJ_LOCAL will only match objects opened through a specific 
-                identifier.
+            The special value OBJ_ALL matches all object types, and 
+            OBJ_LOCAL will only match objects opened through a specific 
+            identifier.
     """
     cdef hid_t where_id
     if isinstance(where, FileID):
@@ -179,15 +181,17 @@ def get_obj_ids(object where=OBJ_ALL, int types=H5F_OBJ_ALL):
 
         Get a list of identifier instances for open objects.
 
-        where:  Either a FileID instance representing an HDF5 file, or the
-                special constant OBJ_ALL, to list objects in all files.
+        where:
+            Either a FileID instance representing an HDF5 file, or the
+            special constant OBJ_ALL, to list objects in all files.
 
-        type:   Specify what kinds of object to include.  May be one of OBJ_*, 
-                or any bitwise combination (e.g. OBJ_FILE | OBJ_ATTR).  
+        type:   
+            Specify what kinds of object to include.  May be one of OBJ_*, 
+            or any bitwise combination (e.g. OBJ_FILE | OBJ_ATTR).  
 
-                The special value OBJ_ALL matches all object types, and 
-                OBJ_LOCAL will only match objects opened through a specific 
-                identifier.
+            The special value OBJ_ALL matches all object types, and 
+            OBJ_LOCAL will only match objects opened through a specific 
+            identifier.
     """
     cdef int count
     cdef int i
@@ -230,9 +234,11 @@ cdef class FileID(ObjectID):
         file identifiers are provided as functions in the h5f module.
 
         Properties:
+
         * name:   File name on disk
 
         Behavior:
+
         * Hashable: Yes, unique to the file (but not the access mode)
         * Equality: Hash comparison
     """
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index e4370b8..b1d9763 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -49,17 +49,18 @@ cdef class GroupStat(SmartStruct):
     """Represents the H5G_stat_t structure containing group member info.
 
     Fields (read-only):
-    fileno  ->  2-tuple uniquely* identifying the current file
-    objno   ->  2-tuple uniquely* identifying this object
-    nlink   ->  Number of hard links to this object
-    mtime   ->  Modification time of this object
-    linklen ->  Length of the symbolic link name, or 0 if not a link.
 
-    *"Uniquely identifying" means unique among currently open files, 
+    * fileno:   2-tuple uniquely identifying the current file
+    * objno:    2-tuple uniquely identifying this object
+    * nlink:    Number of hard links to this object
+    * mtime:    Modification time of this object
+    * linklen:  Length of the symbolic link name, or 0 if not a link.
+
+    "Uniquely identifying" means unique among currently open files, 
     not universally unique.
 
-    Hashable: Yes
-    Equality: Yes
+    * Hashable: Yes
+    * Equality: Yes
     """
     cdef H5G_stat_t infostruct
 
@@ -119,17 +120,17 @@ cdef class GroupIter:
 IF H5PY_18API:
     @sync
     def open(ObjectID loc not None, char* name, PropID gapl=None):
-        """ (ObjectID loc, STRING name, PropGAID gapl=None)
+        """(ObjectID loc, STRING name, PropGAID gapl=None)
 
-            Open an existing HDF5 group, attached to some other group.
+        Open an existing HDF5 group, attached to some other group.
         """
         return GroupID(H5Gopen2(loc.id, name, pdefault(gapl)))
 ELSE:
     @sync
     def open(ObjectID loc not None, char* name):
-        """ (ObjectID loc, STRING name) => GroupID
+        """(ObjectID loc, STRING name) => GroupID
 
-            Open an existing HDF5 group, attached to some other group.
+        Open an existing HDF5 group, attached to some other group.
         """
         return GroupID(H5Gopen(loc.id, name))
 
@@ -138,10 +139,10 @@ IF H5PY_18API:
     @sync
     def create(ObjectID loc not None, char* name, PropID lcpl=None,
                PropID gcpl=None, PropID gapl=None):
-        """ (ObjectID loc, STRING name, PropLCID lcpl=None, PropGCID gcpl=None,
-             PropGAID gapl=None) => GroupID
+        """(ObjectID loc, STRING name, PropLCID lcpl=None, PropGCID gcpl=None,
+        PropGAID gapl=None) => GroupID
 
-            Create a new group, under a given parent group.
+        Create a new group, under a given parent group.
         """
         return GroupID(H5Gcreate2(loc.id, name, pdefault(lcpl),
                                                 pdefault(gcpl),
@@ -149,9 +150,9 @@ IF H5PY_18API:
 ELSE:
     @sync
     def create(ObjectID loc not None, char* name):
-        """ (ObjectID loc, STRING name) => GroupID
+        """(ObjectID loc, STRING name) => GroupID
 
-            Create a new group, under a given parent group.
+        Create a new group, under a given parent group.
         """
         return GroupID(H5Gcreate(loc.id, name, -1))
 
@@ -181,15 +182,15 @@ def iterate(GroupID loc not None, object func, int startidx=0, *,
         => Return value from func
 
         Iterate a callable (function, method or callable object) over the
-        members of a group.  Your callable should have the signature:
+        members of a group.  Your callable should have the signature::
 
             func(STRING name) => Result
 
         Returning None continues iteration; returning anything else aborts
-        iteration and returns that value.
+        iteration and returns that value. Keywords:
 
-        Keywords:
-        * STRING obj_name (".")     Iterate over this subgroup instead
+        STRING obj_name (".")
+            Iterate over this subgroup instead
     """
     if startidx < 0:
         raise ValueError("Starting index must be non-negative")
@@ -203,16 +204,16 @@ def iterate(GroupID loc not None, object func, int startidx=0, *,
 
 @sync
 def get_objinfo(ObjectID obj not None, object name='.', int follow_link=1):
-    """ (ObjectID obj, STRING name='.', BOOL follow_link=True) => GroupStat object
+    """(ObjectID obj, STRING name='.', BOOL follow_link=True) => GroupStat object
 
-        Obtain information about a named object.  If "name" is provided,
-        "obj" is taken to be a GroupID object containing the target.
-        The return value is a GroupStat object; see that class's docstring
-        for a description of its attributes.  
+    Obtain information about a named object.  If "name" is provided,
+    "obj" is taken to be a GroupID object containing the target.
+    The return value is a GroupStat object; see that class's docstring
+    for a description of its attributes.  
 
-        If follow_link is True (default) and the object is a symbolic link, 
-        the information returned describes its target.  Otherwise the 
-        information describes the link itself.
+    If follow_link is True (default) and the object is a symbolic link, 
+    the information returned describes its target.  Otherwise the 
+    information describes the link itself.
     """
     cdef GroupStat statobj
     statobj = GroupStat()
@@ -232,16 +233,21 @@ cdef class GroupID(ObjectID):
 
         Python extensions:
 
-        __contains__(name)   Test for group member ("if name in grpid")
-        __iter__             Get an iterator over member names
-        __len__              Number of members in this group; len(grpid) = N
+        __contains__
+            Test for group member ("if name in grpid")
+
+        __iter__
+            Get an iterator over member names
+
+        __len__
+            Number of members in this group; len(grpid) = N
 
         If HDF5 1.8.X is used, the attribute "links" contains a proxy object
         providing access to the H5L family of routines.  See the docs
         for h5py.h5l.LinkProxy for more information.
 
-        Hashable: Yes, unless anonymous
-        Equality: True HDF5 identity unless anonymous
+        * Hashable: Yes, unless anonymous
+        * Equality: True HDF5 identity unless anonymous
     """
 
     IF H5PY_18API:
@@ -250,11 +256,11 @@ cdef class GroupID(ObjectID):
 
     @sync
     def _close(self):
-        """ ()
+        """()
 
-            Terminate access through this identifier.  You shouldn't have to
-            call this manually; group identifiers are automatically released
-            when their Python wrappers are freed.
+        Terminate access through this identifier.  You shouldn't have to
+        call this manually; group identifiers are automatically released
+        when their Python wrappers are freed.
         """
         H5Gclose(self.id)
         IF H5PY_18API:
@@ -264,16 +270,20 @@ cdef class GroupID(ObjectID):
     @sync
     def link(self, char* current_name, char* new_name, 
              int link_type=H5G_LINK_HARD, GroupID remote=None):
-        """ (STRING current_name, STRING new_name, INT link_type=LINK_HARD, 
-             GroupID remote=None)
+        """(STRING current_name, STRING new_name, INT link_type=LINK_HARD, 
+        GroupID remote=None)
 
-            Create a new hard or soft link.  current_name identifies
-            the link target (object the link will point to).  The new link is
-            identified by new_name and (optionally) another group "remote".
+        Create a new hard or soft link.  current_name identifies
+        the link target (object the link will point to).  The new link is
+        identified by new_name and (optionally) another group "remote".
 
-            Link types are:
-                LINK_HARD:  Hard link to existing object (default)
-                LINK_SOFT:  Symbolic link; link target need not exist.
+        Link types are:
+
+        LINK_HARD
+            Hard link to existing object (default)
+
+        LINK_SOFT
+            Symbolic link; link target need not exist.
         """
         cdef hid_t remote_id
         if remote is None:
@@ -286,20 +296,20 @@ cdef class GroupID(ObjectID):
 
     @sync
     def unlink(self, char* name):
-        """ (STRING name)
+        """(STRING name)
 
-            Remove a link to an object from this group.
+        Remove a link to an object from this group.
         """
         H5Gunlink(self.id, name)
    
 
     @sync
     def move(self, char* current_name, char* new_name, GroupID remote=None):
-        """ (STRING current_name, STRING new_name, GroupID remote=None)
+        """(STRING current_name, STRING new_name, GroupID remote=None)
 
-            Relink an object.  current_name identifies the object.
-            new_name and (optionally) another group "remote" determine
-            where it should be moved.
+        Relink an object.  current_name identifies the object.
+        new_name and (optionally) another group "remote" determine
+        where it should be moved.
         """
         cdef hid_t remote_id
         if remote is None:
@@ -312,9 +322,9 @@ cdef class GroupID(ObjectID):
 
     @sync
     def get_num_objs(self):
-        """ () => INT number_of_objects
+        """() => INT number_of_objects
 
-            Get the number of objects directly attached to a given group.
+        Get the number of objects directly attached to a given group.
         """
         cdef hsize_t size
         H5Gget_num_objs(self.id, &size)
@@ -323,12 +333,12 @@ cdef class GroupID(ObjectID):
 
     @sync
     def get_objname_by_idx(self, hsize_t idx):
-        """ (INT idx) => STRING object_name
+        """(INT idx) => STRING
 
-            Get the name of a group member given its zero-based index.
+        Get the name of a group member given its zero-based index.
 
-            Due to a limitation of the HDF5 library, the generic exception
-            H5Error is raised if the idx parameter is out-of-range.
+        Due to a limitation of the HDF5 library, the generic exception
+        H5Error is raised if the idx parameter is out-of-range.
         """
         cdef int size
         cdef char* buf
@@ -350,17 +360,18 @@ cdef class GroupID(ObjectID):
 
     @sync
     def get_objtype_by_idx(self, hsize_t idx):
-        """ (INT idx) => INT object_type_code
+        """(INT idx) => INT object_type_code
+
+        Get the type of an object attached to a group, given its zero-based
+        index.  Possible return values are:
 
-            Get the type of an object attached to a group, given its zero-based
-            index.  Possible return values are:
-                - LINK
-                - GROUP
-                - DATASET
-                - DATATYPE
+        - LINK
+        - GROUP
+        - DATASET
+        - TYPE
 
-            Due to a limitation of the HDF5 library, the generic exception
-            H5Error is raised if the idx parameter is out-of-range.
+        Due to a limitation of the HDF5 library, the generic exception
+        H5Error is raised if the idx parameter is out-of-range.
         """
         # This function does not properly raise an exception
         cdef herr_t retval
@@ -372,10 +383,10 @@ cdef class GroupID(ObjectID):
 
     @sync
     def get_linkval(self, char* name):
-        """ (STRING name) => STRING link_value
+        """(STRING name) => STRING link_value
 
-            Retrieve the value (target name) of a symbolic link.
-            Limited to 2048 characters on Windows.
+        Retrieve the value (target name) of a symbolic link.
+        Limited to 2048 characters on Windows.
         """
         cdef char* value
         cdef H5G_stat_t statbuf
@@ -401,17 +412,17 @@ cdef class GroupID(ObjectID):
 
     @sync
     def set_comment(self, char* name, char* comment):
-        """ (STRING name, STRING comment)
+        """(STRING name, STRING comment)
 
-            Set the comment on a group member.
+        Set the comment on a group member.
         """
         H5Gset_comment(self.id, name, comment)
 
     @sync
     def get_comment(self, char* name):
-        """ (STRING name) => STRING comment
+        """(STRING name) => STRING comment
 
-            Retrieve the comment for a group member.
+        Retrieve the comment for a group member.
         """
         cdef int cmnt_len
         cdef char* cmnt
@@ -432,9 +443,9 @@ cdef class GroupID(ObjectID):
 
     @sync
     def __contains__(self, char* name):
-        """ (STRING name)
+        """(STRING name)
 
-            Determine if a group member of the given name is present
+        Determine if a group member of the given name is present
         """
         IF H5PY_18API:
             return <bint>H5Lexists(self.id, name, H5P_DEFAULT)
diff --git a/h5py/h5l.pyx b/h5py/h5l.pyx
index 41687b2..867c3b1 100644
--- a/h5py/h5l.pyx
+++ b/h5py/h5l.pyx
@@ -17,7 +17,7 @@ __doc__ = \
 include "config.pxi"
 include "sync.pxi"
 
-from h5 cimport init_hdf5
+from h5 cimport init_hdf5, SmartStruct
 from h5p cimport PropID, pdefault
 from h5g cimport GroupID
 from utils cimport emalloc, efree
@@ -31,10 +31,9 @@ TYPE_HARD = H5L_TYPE_HARD
 TYPE_SOFT = H5L_TYPE_SOFT      
 TYPE_EXTERNAL = H5L_TYPE_EXTERNAL     
 
-cdef class LinkInfo:
+cdef class LinkInfo(SmartStruct):
 
     cdef H5L_info_t infostruct
-    cdef object __weakref__
 
     property type:
         """ Integer type code for link (h5l.TYPE_*) """
@@ -60,14 +59,6 @@ cdef class LinkInfo:
             else:
                 return self.infostruct.u.val_size
 
-    def __repr__(self):
-        typenames = {H5L_TYPE_HARD: "HARD", H5L_TYPE_SOFT: "SOFT",
-                     H5L_TYPE_EXTERNAL: "EXTERNAL"}
-        cset_names = {H5T_CSET_ASCII: "ASCII", H5T_CSET_UTF8: "UTF8"}
-        return "LinkInfo (%s, element %d, cset %s)" % \
-            (typenames.get(self.type, "UNKNOWN"), self.corder,
-            cset_names.get(self.cset, "UNKNOWN"))
-
 cdef class _LinkVisitor:
 
     """ Helper class for iteration callback """
@@ -86,13 +77,21 @@ cdef herr_t cb_link_iterate(hid_t grp, char* name, H5L_info_t *istruct, void* da
 
     cdef _LinkVisitor it = <_LinkVisitor?>data
     it.info.infostruct = istruct[0]
-
     it.retval = it.func(name, it.info)
+    if (it.retval is None) or (not it.retval):
+        return 0
+    return 1
+
+cdef herr_t cb_link_simple(hid_t grp, char* name, H5L_info_t *istruct, void* data) except 2:
+    # Simplified iteration callback which only provides the name
 
+    cdef _LinkVisitor it = <_LinkVisitor?>data
+    it.retval = it.func(name)
     if (it.retval is None) or (not it.retval):
         return 0
     return 1
 
+
 cdef class LinkProxy(ObjectID):
 
     """
@@ -100,7 +99,7 @@ cdef class LinkProxy(ObjectID):
 
         These come attached to GroupID objects as "obj.links".  Since every
         H5L function operates on at least one group, the methods provided
-        operate on their parent group identifier.  For example:
+        operate on their parent group identifier.  For example::
 
         >>> g = h5g.open(fid, '/')
         >>> g.links.exists("MyGroup")
@@ -216,27 +215,39 @@ cdef class LinkProxy(ObjectID):
     @sync
     def visit(self, object func, *,
               int idx_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
-              char* obj_name='.', PropID lapl=None):
+              char* obj_name='.', PropID lapl=None, bint info=0):
         """(CALLABLE func, **kwds) => <Return value from func>
 
         Iterate a function or callable object over all groups below this
         one.  Your callable should conform to the signature:
 
+            func(STRING name) => Result
+
+        or if the keyword argument "info" is True:
+
             func(STRING name, LinkInfo info) => Result
 
         Returning None or a logical False continues iteration; returning
         anything else aborts iteration and returns that value.
 
         Keyword-only arguments:
+
+        * BOOL info (False)              Provide a LinkInfo instance to callback
         * STRING obj_name ("."):         Visit a subgroup instead
         * PropLAID lapl (None):          Controls how "obj_name" is interpreted
         * INT idx_type (h5.INDEX_NAME):  What indexing strategy to use
         * INT order (h5.ITER_NATIVE):    Order in which iteration occurs
         """
         cdef _LinkVisitor it = _LinkVisitor(func)
+        cdef H5L_iterate_t cfunc
+
+        if info:
+            cfunc = cb_link_iterate
+        else:
+            cfunc = cb_link_simple
 
         H5Lvisit_by_name(self.id, obj_name, <H5_index_t>idx_type,
-            <H5_iter_order_t>order, cb_link_iterate, <void*>it, pdefault(lapl))
+            <H5_iter_order_t>order, cfunc, <void*>it, pdefault(lapl))
 
         return it.retval
 
diff --git a/h5py/h5o.pyx b/h5py/h5o.pyx
index 00096c7..fc6e215 100644
--- a/h5py/h5o.pyx
+++ b/h5py/h5o.pyx
@@ -17,30 +17,103 @@ include "sync.pxi"
 # built with API compatibility level below 1.8.
 
 # Pyrex compile-time imports
-from h5 cimport init_hdf5, ObjectID
+from h5 cimport init_hdf5, ObjectID, SmartStruct
+from h5g cimport GroupID
 from h5i cimport wrap_identifier
 from h5p cimport PropID, pdefault
 
 # Initialization
 init_hdf5()
 
-cdef class ObjInfo:
+# === Giant H5O_info_t structure ==============================================
 
-    cdef H5O_info_t infostruct
-    cdef object __weakref__
+cdef class _ObjInfoBase(SmartStruct):
+
+    cdef H5O_info_t *istr
+
+cdef class _OHdrMesg(_ObjInfoBase):
+
+    property present:
+        def __get__(self):
+            return self.istr[0].hdr.mesg.present
+    property shared:
+        def __get__(self):
+            return self.istr[0].hdr.mesg.shared
+
+    def _hash(self):
+        return hash((self.present, self.shared))
+
+cdef class _OHdrSpace(_ObjInfoBase):
+
+    property total:
+        def __get__(self):
+            return self.istr[0].hdr.space.total
+    property meta:
+        def __get__(self):
+            return self.istr[0].hdr.space.meta
+    property mesg:
+        def __get__(self):
+            return self.istr[0].hdr.space.mesg
+    property free:
+        def __get__(self):
+            return self.istr[0].hdr.space.free
+
+    def _hash(self):
+        return hash((self.total, self.meta, self.mesg, self.free))
+
+cdef class _OHdr(_ObjInfoBase):
+
+    cdef public _OHdrSpace space
+    cdef public _OHdrMesg mesg
+
+    property version:
+        def __get__(self):
+            return self.istr[0].hdr.version
+    property nmesgs:
+        def __get__(self):
+            return self.istr[0].hdr.nmesgs
+
+    def __init__(self):
+        self.space = _OHdrSpace()
+        self.mesg = _OHdrMesg()
+
+    def _hash(self):
+        return hash((self.version, self.nmesgs, self.space, self.mesg))
+
+cdef class _ObjInfo(_ObjInfoBase):
 
     property fileno:
         def __get__(self):
-            return self.infostruct.fileno
+            return self.istr[0].fileno
     property addr:
         def __get__(self):
-            return self.infostruct.addr
+            return self.istr[0].addr
     property type:
         def __get__(self):
-            return <int>self.infostruct.type
+            return <int>self.istr[0].type
     property rc:
         def __get__(self):
-            return self.infostruct.rc
+            return self.istr[0].rc
+
+    def _hash(self):
+        return hash((self.fileno, self.addr, self.type, self.rc))
+
+cdef class ObjInfo(_ObjInfo):
+
+    """
+        Represents the H5O_info_t structure
+    """
+
+    cdef H5O_info_t infostruct
+    cdef public _OHdr hdr
+
+    def __init__(self):
+        self.hdr = _OHdr()
+
+        self.istr = &self.infostruct
+        self.hdr.istr = &self.infostruct
+        self.hdr.space.istr = &self.infostruct
+        self.hdr.mesg.istr = &self.infostruct
 
     def __copy__(self):
         cdef ObjInfo newcopy
@@ -59,6 +132,42 @@ def get_info(ObjectID obj not None):
     return info
 
 
+# === General object operations ===============================================
+
+ at sync
+def open(ObjectID loc not None, char* name, PropID lapl=None):
+    """(ObjectID loc, STRING name, PropID lapl=None) => ObjectID
+
+    Open a group, dataset, or named datatype attached to an existing group.
+    """
+    return wrap_identifier(H5Oopen(loc.id, name, pdefault(lapl)))
+
+ at sync
+def link(ObjectID obj not None, GroupID loc not None, char* name,
+    PropID lcpl=None, PropID lapl=None):
+    """(ObjectID obj, GroupID loc, STRING name, PropID lcpl=None,
+    PropID lapl=None)
+
+    Create a new hard link to an object.  Useful for objects created with
+    h5g.create_anon or h5d.create_anon.
+    """
+    H5Olink(obj.id, loc.id, name, pdefault(lcpl), pdefault(lapl))
+
+ at sync
+def copy(GroupID src_loc not None, char* src_name, GroupID dst_loc not None,
+    char* dst_name, PropID copypl=None, PropID lcpl=None):
+    """(GroupID src_loc, STRING src_name, GroupID dst_loc, STRING dst_name,
+    PropID copypl=None, PropID lcpl=None)
+    
+    Copy a group, dataset or named datatype from one location to another.  The
+    source and destination need not be in the same file.
+
+    The default behavior is a recursive copy of the object and all objects
+    below it.  This behavior is modified via the "copypl" property list.
+    """
+    H5Ocopy(src_loc.id, src_name, dst_loc.id, dst_name, pdefault(copypl),
+        pdefault(lcpl))
+
 # === Visit routines ==========================================================
 
 cdef class _ObjectVisitor:
@@ -84,31 +193,54 @@ cdef herr_t cb_obj_iterate(hid_t obj, char* name, H5O_info_t *info, void* data)
     if (visit.retval is None) or (not visit.retval):
         return 0
     return 1
- 
+
+cdef herr_t cb_obj_simple(hid_t obj, char* name, H5O_info_t *info, void* data) except 2:
+
+    cdef _ObjectVisitor visit
+    visit = <_ObjectVisitor>data
+
+    visit.retval = visit.func(name)
+
+    if (visit.retval is None) or (not visit.retval):
+        return 0
+    return 1
+
 @sync
 def visit(ObjectID loc not None, object func, *,
           int idx_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
-          char* name=".", PropID lapl=None):
+          char* obj_name=".", PropID lapl=None, bint info=0):
     """(ObjectID loc, CALLABLE func, **kwds) => <Return value from func>
 
     Iterate a function or callable object over all objects below the
-    specified one.  Your callable should conform to the signature:
+    specified one.  Your callable should conform to the signature::
 
+        func(STRING name) => Result
+
+    or if the keyword argument "info" is True::
+    
         func(STRING name, ObjInfo info) => Result
 
     Returning None or a logical False continues iteration; returning
     anything else aborts iteration and returns that value.
 
     Keyword-only arguments:
-    * STRING name ("."):            Visit a subgroup of "loc" instead
-    * PropLAID lapl (None):          Control how "name" is interpreted
+
+    * BOOL info (False)              Callbask is func(STRING, Objinfo)
+    * STRING obj_name ("."):         Visit a subgroup of "loc" instead
+    * PropLAID lapl (None):          Control how "obj_name" is interpreted
     * INT idx_type (h5.INDEX_NAME):  What indexing strategy to use
     * INT order (h5.ITER_NATIVE):    Order in which iteration occurs
     """
     cdef _ObjectVisitor visit = _ObjectVisitor(func)
+    cdef H5O_iterate_t cfunc
+
+    if info:
+        cfunc = cb_obj_iterate
+    else:
+        cfunc = cb_obj_simple
 
-    H5Ovisit_by_name(loc.id, name, <H5_index_t>idx_type,
-        <H5_iter_order_t>order, cb_obj_iterate, <void*>visit, pdefault(lapl))
+    H5Ovisit_by_name(loc.id, obj_name, <H5_index_t>idx_type,
+        <H5_iter_order_t>order, cfunc, <void*>visit, pdefault(lapl))
 
     return visit.retval
 
diff --git a/h5py/h5r.pyx b/h5py/h5r.pyx
index 90dd227..d5a8256 100644
--- a/h5py/h5r.pyx
+++ b/h5py/h5r.pyx
@@ -12,8 +12,6 @@
 __doc__ = \
 """
     H5R API for object and region references.
-
-    Functions in this module are not well tested.
 """
 
 include "config.pxi"
@@ -38,20 +36,20 @@ DATASET_REGION = H5R_DATASET_REGION
 
 @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
+    """(ObjectID loc, STRING name, INT ref_type, SpaceID space=None)
+    => ReferenceObject ref
 
-        Create a new reference. The value of ref_type detemines the kind
-        of reference created:
+    Create a new reference. The value of ref_type detemines the kind
+    of reference created:
 
-        - OBJECT
-            Reference to an object in an HDF5 file.  Parameters "loc"
-            and "name" identify the object; "space" is unused.
+    OBJECT
+        Reference to an object in an HDF5 file.  Parameters "loc"
+        and "name" identify the object; "space" is unused.
 
-        - DATASET_REGION    
-            Reference to a dataset region.  Parameters "loc" and
-            "name" identify the dataset; the selection on "space"
-            identifies the region.
+    DATASET_REGION    
+        Reference to a dataset region.  Parameters "loc" and
+        "name" identify the dataset; the selection on "space"
+        identifies the region.
     """
     cdef hid_t space_id
     cdef Reference ref
@@ -79,44 +77,45 @@ cdef class Reference:
 
     @sync
     def dereference(self, ObjectID id not None):
-        """ (ObjectID id) => ObjectID obj_id
+        """(ObjectID id) => ObjectID
 
-            Open the object pointed to by this reference and return its
-            identifier.  The file identifier (or the identifier for any object
-            in the file) must also be provided.
+        Open the object pointed to by this reference and return its
+        identifier.  The file identifier (or the identifier for any object
+        in the file) must also be provided.
 
-            The reference type may be either OBJECT or DATASET_REGION.
+        The reference type may be either OBJECT or DATASET_REGION.
         """
         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
+        """(ObjectID id) => SpaceID
 
-            Retrieve the dataspace selection pointed to by this reference.
-            Returns a copy of the dataset's dataspace, with the appropriate
-            elements selected.  The file identifier or the identifier of any
-            object in the file (including the dataset itself) must also be
-            provided.
+        Retrieve the dataspace selection pointed to by this reference.
+        Returns a copy of the dataset's dataspace, with the appropriate
+        elements selected.  The file identifier or the identifier of any
+        object in the file (including the dataset itself) must also be
+        provided.
 
-            The reference object must be of type DATASET_REGION.
+        The reference object must be of type DATASET_REGION.
         """
         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
-
-            Determine what type of object this eference points to.  The
-            reference may be either type OBJECT or DATASET_REGION.  The file
-            identifier or the identifier of any object in the file must also
-            be provided.
-
-            The return value is one of:
-            h5g.LINK        Symbolic link
-            h5g.GROUP       Group
-            h5g.DATASET     Dataset
-            h5g.TYPE        Named datatype
+        """(ObjectID id) => INT obj_code
+
+        Determine what type of object this eference points to.  The
+        reference may be either type OBJECT or DATASET_REGION.  The file
+        identifier or the identifier of any object in the file must also
+        be provided.
+
+        The return value is one of:
+
+        - h5g.LINK
+        - h5g.GROUP
+        - h5g.DATASET
+        - h5g.TYPE
         """
         return <int>H5Rget_obj_type(id.id, <H5R_type_t>self.typecode, &self.ref)
 
diff --git a/h5py/h5s.pyx b/h5py/h5s.pyx
index ff09013..5417681 100644
--- a/h5py/h5s.pyx
+++ b/h5py/h5s.pyx
@@ -67,23 +67,23 @@ SEL_ALL         = H5S_SEL_ALL
 
 @sync
 def create(int class_code):
-    """ (INT class_code) => SpaceID
+    """(INT class_code) => SpaceID
 
-        Create a new HDF5 dataspace object, of the given class.
-        Legal values are SCALAR and SIMPLE.
+    Create a new HDF5 dataspace object, of the given class.
+    Legal values are SCALAR and SIMPLE.
     """
     return SpaceID(H5Screate(<H5S_class_t>class_code))
 
 @sync
 def create_simple(object dims_tpl, object max_dims_tpl=None):
-    """ (TUPLE dims_tpl, TUPLE max_dims_tpl) => INT new_space_id
+    """(TUPLE dims_tpl, TUPLE max_dims_tpl) => SpaceID
 
-        Create a simple (slab) dataspace from a tuple of dimensions.  
-        Every element of dims_tpl must be a positive integer.  
+    Create a simple (slab) dataspace from a tuple of dimensions.  
+    Every element of dims_tpl must be a positive integer.  
 
-        You can optionally specify the maximum dataspace size. The 
-        special value UNLIMITED, as an element of max_dims, indicates 
-        an unlimited dimension.
+    You can optionally specify the maximum dataspace size. The 
+    special value UNLIMITED, as an element of max_dims, indicates 
+    an unlimited dimension.
     """
     cdef int rank
     cdef hsize_t* dims = NULL
@@ -110,10 +110,10 @@ def create_simple(object dims_tpl, object max_dims_tpl=None):
 IF H5PY_18API:
     @sync
     def decode(buf):
-        """ (STRING buf) => SpaceID
+        """(STRING buf) => SpaceID
 
-            Unserialize a dataspace.  Bear in mind you can also use the native
-            Python pickling machinery to do this.
+        Unserialize a dataspace.  Bear in mind you can also use the native
+        Python pickling machinery to do this.
         """
         cdef char* buf_ = buf
         return SpaceID(H5Sdecode(buf_))
@@ -126,10 +126,12 @@ cdef class SpaceID(ObjectID):
         Represents a dataspace identifier.
 
         Properties:
-        shape:  Numpy-style shape tuple with dimensions.
 
-        Hashable: No
-        Equality: Unimplemented
+        shape
+            Numpy-style shape tuple with dimensions.
+
+        * Hashable: No
+        * Equality: Unimplemented
     """
 
     property shape:
@@ -140,29 +142,29 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def _close(self):
-        """ ()
+        """()
 
-            Terminate access through this identifier.  You shouldn't have to
-            call this manually; dataspace objects are automatically destroyed
-            when their Python wrappers are freed.
+        Terminate access through this identifier.  You shouldn't have to
+        call this manually; dataspace objects are automatically destroyed
+        when their Python wrappers are freed.
         """
         H5Sclose(self.id)
 
     @sync
     def copy(self):
-        """ () => SpaceID
+        """() => SpaceID
 
-            Create a new copy of this dataspace.
+        Create a new copy of this dataspace.
         """
         return SpaceID(H5Scopy(self.id))
 
     IF H5PY_18API:    
         @sync
         def encode(self):
-            """ () => STRING
+            """() => STRING
 
-                Serialize a dataspace, including its selection.  Bear in mind you
-                can also use the native Python pickling machinery to do this.
+            Serialize a dataspace, including its selection.  Bear in mind you
+            can also use the native Python pickling machinery to do this.
             """
             cdef void* buf = NULL
             cdef size_t nalloc = 0
@@ -193,20 +195,20 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def is_simple(self):
-        """ () => BOOL is_simple
+        """() => BOOL is_simple
 
-            Determine if an existing dataspace is "simple" (including scalar
-            dataspaces). Currently all HDF5 dataspaces are simple.
+        Determine if an existing dataspace is "simple" (including scalar
+        dataspaces). Currently all HDF5 dataspaces are simple.
         """
         return <bint>(H5Sis_simple(self.id))
 
     @sync
     def offset_simple(self, object offset=None):
-        """ (TUPLE offset=None)
+        """(TUPLE offset=None)
 
-            Set the offset of a dataspace.  The length of the given tuple must
-            match the rank of the dataspace. If None is provided (default), 
-            the offsets on all axes will be set to 0.
+        Set the offset of a dataspace.  The length of the given tuple must
+        match the rank of the dataspace. If None is provided (default), 
+        the offsets on all axes will be set to 0.
         """
         cdef int rank
         cdef int i
@@ -236,18 +238,18 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def get_simple_extent_ndims(self):
-        """ () => INT rank
-            
-            Determine the rank of a "simple" (slab) dataspace.
+        """() => INT rank
+        
+        Determine the rank of a "simple" (slab) dataspace.
         """
         return H5Sget_simple_extent_ndims(self.id)
 
     @sync
     def get_simple_extent_dims(self, int maxdims=0):
-        """ (BOOL maxdims=False) => TUPLE shape
+        """(BOOL maxdims=False) => TUPLE shape
 
-            Determine the shape of a "simple" (slab) dataspace.  If "maxdims" 
-            is True, retrieve the maximum dataspace size instead.
+        Determine the shape of a "simple" (slab) dataspace.  If "maxdims" 
+        is True, retrieve the maximum dataspace size instead.
         """
         cdef int rank
         cdef hsize_t* dims = NULL
@@ -268,17 +270,17 @@ cdef class SpaceID(ObjectID):
     
     @sync
     def get_simple_extent_npoints(self):
-        """ () => LONG npoints
+        """() => LONG npoints
 
-            Determine the total number of elements in a dataspace.
+        Determine the total number of elements in a dataspace.
         """
         return H5Sget_simple_extent_npoints(self.id)
 
     @sync
     def get_simple_extent_type(self):
-        """ () => INT class_code
+        """() => INT class_code
 
-            Class code is either SCALAR or SIMPLE.
+        Class code is either SCALAR or SIMPLE.
         """
         return <int>H5Sget_simple_extent_type(self.id)
 
@@ -286,23 +288,23 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def extent_copy(self, SpaceID source not None):
-        """ (SpaceID source)
+        """(SpaceID source)
 
-            Replace this dataspace's extent with another's, changing its
-            typecode if necessary.
+        Replace this dataspace's extent with another's, changing its
+        typecode if necessary.
         """
         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)
+        """(TUPLE dims_tpl, TUPLE max_dims_tpl=None)
 
-            Reset the dataspace extent via a tuple of dimensions.  
-            Every element of dims_tpl must be a positive integer.  
+        Reset the dataspace extent via a tuple of dimensions.  
+        Every element of dims_tpl must be a positive integer.  
 
-            You can optionally specify the maximum dataspace size. The 
-            special value UNLIMITED, as an element of max_dims, indicates 
-            an unlimited dimension.
+        You can optionally specify the maximum dataspace size. The 
+        special value UNLIMITED, as an element of max_dims, indicates 
+        an unlimited dimension.
         """
         cdef int rank
         cdef hsize_t* dims = NULL
@@ -328,9 +330,9 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def set_extent_none(self):
-        """ ()
+        """()
 
-            Remove the dataspace extent; typecode changes to NO_CLASS.
+        Remove the dataspace extent; typecode changes to NO_CLASS.
         """
         H5Sset_extent_none(self.id)
 
@@ -341,28 +343,29 @@ cdef class SpaceID(ObjectID):
         """ () => INT select_code
 
             Determine selection type.  Return values are:
-            SEL_NONE:       No selection.
-            SEL_ALL:        All points selected
-            SEL_POINTS:     Point-by-point element selection in use
-            SEL_HYPERSLABS: Hyperslab selection in use
+
+            - SEL_NONE
+            - SEL_ALL
+            - SEL_POINTS
+            - SEL_HYPERSLABS
         """
         return <int>H5Sget_select_type(self.id)
 
     @sync
     def get_select_npoints(self):
-        """ () => LONG npoints
+        """() => LONG npoints
 
-            Determine the total number of points currently selected.  
-            Works for all selection techniques.
+        Determine the total number of points currently selected.  
+        Works for all selection techniques.
         """
         return H5Sget_select_npoints(self.id)
 
     @sync
     def get_select_bounds(self):
-        """ () => (TUPLE start, TUPLE end)
+        """() => (TUPLE start, TUPLE end)
 
-            Determine the bounding box which exactly contains 
-            the current selection.
+        Determine the bounding box which exactly contains 
+        the current selection.
         """
         cdef int rank
         cdef hsize_t *start = NULL
@@ -386,26 +389,26 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def select_all(self):
-        """ ()
+        """()
 
-            Select all points in the dataspace.
+        Select all points in the dataspace.
         """
         H5Sselect_all(self.id)
 
     @sync
     def select_none(self):
-        """ ()
+        """()
 
-            Deselect entire dataspace.
+        Deselect entire dataspace.
         """
         H5Sselect_none(self.id)
 
     @sync
     def select_valid(self):
-        """ () => BOOL select_valid
-            
-            Determine if the current selection falls within
-            the dataspace extent.
+        """() => BOOL
+        
+        Determine if the current selection falls within
+        the dataspace extent.
         """
         return <bint>(H5Sselect_valid(self.id))
 
@@ -413,18 +416,18 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def get_select_elem_npoints(self):
-        """ () => LONG npoints
+        """() => LONG npoints
 
-            Determine the number of elements selected in point-selection mode.
+        Determine the number of elements selected in point-selection mode.
         """
         return H5Sget_select_elem_npoints(self.id)
 
     @sync
     def get_select_elem_pointlist(self):
-        """ () => NDARRAY elements_list
+        """() => NDARRAY
 
-            Get a list of all selected elements.  Return is a Numpy array of
-            unsigned ints, with shape (<npoints>, <space rank).
+        Get a list of all selected elements.  Return is a Numpy array of
+        unsigned ints, with shape ``(<npoints>, <space rank)``.
         """
         cdef hsize_t dims[2]
         cdef ndarray buf
@@ -440,21 +443,22 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def select_elements(self, object coords, int op=H5S_SELECT_SET):
-        """ (SEQUENCE coords, INT op=SELECT_SET)
+        """(SEQUENCE coords, INT op=SELECT_SET)
 
-            Select elements by specifying coordinates points.  The argument
-            "coords" may be an ndarray or any nested sequence which can be
-            converted to an array of uints with the shape:
+        Select elements by specifying coordinates points.  The argument
+        "coords" may be an ndarray or any nested sequence which can be
+        converted to an array of uints with the shape::
 
-                (<npoints>, <space rank>)
-            
-            Examples:
-                >>> obj.shape
-                (10, 10)
-                >>> obj.select_elements([(1,2), (3,4), (5,9)])
+            (<npoints>, <space rank>)
+        
+        Examples::
+
+            >>> obj.shape
+            (10, 10)
+            >>> obj.select_elements([(1,2), (3,4), (5,9)])
 
-            A zero-length selection (i.e. shape (0, <rank>)) is not allowed by
-            the HDF5 library.  
+        A zero-length selection (i.e. shape ``(0, <rank>)``) is not allowed
+        by the HDF5 library.  
         """
         cdef ndarray hcoords
         cdef size_t nelements
@@ -477,25 +481,25 @@ cdef class SpaceID(ObjectID):
 
     @sync
     def get_select_hyper_nblocks(self):
-        """ () => LONG nblocks
+        """() => LONG nblocks
 
-            Get the number of hyperslab blocks currently selected.
+        Get the number of hyperslab blocks currently selected.
         """
         return H5Sget_select_hyper_nblocks(self.id)
 
     @sync
     def get_select_hyper_blocklist(self):
-        """ () => NDARRAY hyperslab_blocks
+        """() => NDARRAY
 
-            Get the current hyperslab selection.  The returned array has shape
+        Get the current hyperslab selection.  The returned array has shape::
 
-                (<npoints>, 2, <rank>)
+            (<npoints>, 2, <rank>)
 
-            and can be interpreted as a nested sequence:
+        and can be interpreted as a nested sequence::
 
-                [ (corner_coordinate_1, opposite_coordinate_1), ... ]
+            [ (corner_coordinate_1, opposite_coordinate_1), ... ]
 
-            with length equal to the total number of blocks.
+        with length equal to the total number of blocks.
         """
         cdef hsize_t dims[3]  # 0=nblocks 1=(#2), 2=rank
         cdef ndarray buf
@@ -513,11 +517,11 @@ cdef class SpaceID(ObjectID):
     @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, 
+        """(TUPLE start, TUPLE count, TUPLE stride=None, TUPLE block=None, 
              INT op=SELECT_SET)
-         
-            Select a block region from an existing dataspace.  See the HDF5
-            documentation for the meaning of the "block" and "op" keywords.
+     
+        Select a block region from an existing dataspace.  See the HDF5
+        documentation for the meaning of the "block" and "op" keywords.
         """
         cdef int rank
         cdef hsize_t* start_array = NULL
diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index a3ecaa6..5b8f097 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -51,8 +51,8 @@ __doc__ = \
 
     4. Variable-length types
 
-       VLEN datatype objects can be manipulated, but reading and writing data
-       in VLEN format is not supported.  This applies to VLEN strings as well.
+       "VLEN" datatype objects can be manipulated, but reading and writing data
+       in vlen format is not supported.  This applies to vlen strings as well.
 
     5. Datatypes can be pickled if HDF5 1.8.X is available.
 """
@@ -238,10 +238,10 @@ cdef dict _sign_map  = { H5T_SGN_NONE: 'u', H5T_SGN_2: 'i' }
 
 @sync
 def create(int classtype, size_t size):
-    """ (INT classtype, UINT size) => TypeID
+    """(INT classtype, UINT size) => TypeID
         
-        Create a new HDF5 type object.  Legal class values are 
-        COMPOUND and OPAQUE.  Use enum_create for enums.
+    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
@@ -252,19 +252,19 @@ def create(int classtype, size_t size):
 
 @sync
 def open(ObjectID group not None, char* name):
-    """ (ObjectID group, STRING name) => TypeID
+    """(ObjectID group, STRING name) => TypeID
 
-        Open a named datatype from a file.
+    Open a named datatype from a file.
     """
     return typewrap(H5Topen(group.id, name))
 
 @sync
 def array_create(TypeID base not None, object dims_tpl):
-    """ (TypeID base, TUPLE dimensions) => TypeArrayID
+    """(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.
+    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
@@ -281,30 +281,30 @@ def array_create(TypeID base not None, object dims_tpl):
 
 @sync
 def enum_create(TypeID base not None):
-    """ (TypeID base) => TypeID
+    """(TypeID base) => TypeID
 
-        Create a new enumerated type based on an (integer) parent type.
+    Create a new enumerated type based on an (integer) parent type.
     """
     return typewrap(H5Tenum_create(base.id))
 
 @sync
 def vlen_create(TypeID base not None):
-    """ (TypeID base) => TypeID
+    """(TypeID base) => TypeID
 
-        Create a new variable-length datatype, using any HDF5 type as a base.
+    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.
+    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
+        """(STRING buf) => TypeID
 
-            Unserialize an HDF5 type.  You can also do this with the native
-            Python pickling machinery.
+        Unserialize an HDF5 type.  You can also do this with the native
+        Python pickling machinery.
         """
         return typewrap(H5Tdecode(<unsigned char*>buf))
 
@@ -315,8 +315,8 @@ 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
+        * Hashable: If committed; in HDF5 1.8.X, also if locked
+        * Equality: Logical H5T comparison
     """
 
     def __hash__(self):
@@ -370,60 +370,60 @@ cdef class TypeID(ObjectID):
 
     @sync
     def commit(self, ObjectID group not None, char* name):
-        """ (ObjectID group, STRING name)
+        """(ObjectID group, STRING name)
 
-            Commit this (transient) datatype to a named datatype in a file.
+        Commit this (transient) datatype to a named datatype in a file.
         """
         H5Tcommit(group.id, name, self.id)
 
     @sync
     def committed(self):
-        """ () => BOOL is_comitted
+        """() => BOOL is_comitted
 
-            Determine if a given type object is named (T) or transient (F).
+        Determine if a given type object is named (T) or transient (F).
         """
         return <bint>(H5Tcommitted(self.id))
 
     @sync
     def copy(self):
-        """ () => TypeID
+        """() => TypeID
 
-            Create a copy of this type object.
+        Create a copy of this type object.
         """
         return typewrap(H5Tcopy(self.id))
 
     @sync
     def equal(self, TypeID typeid):
-        """ (TypeID typeid) => BOOL
+        """(TypeID typeid) => BOOL
 
-            Logical comparison between datatypes.  Also called by
-            Python's "==" operator.
+        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.
+        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
+        """() => INT classcode
 
-            Determine the datatype's class code.
+        Determine the datatype's class code.
         """
         return <int>H5Tget_class(self.id)
 
     @sync
     def set_size(self, size_t size):
-        """ (UINT size)
+        """(UINT size)
 
-            Set the total size of the datatype, in bytes.
+        Set the total size of the datatype, in bytes.
         """
         H5Tset_size(self.id, size)
 
@@ -437,27 +437,29 @@ cdef class TypeID(ObjectID):
 
     @sync
     def get_super(self):
-        """ () => TypeID
+        """() => TypeID
 
-            Determine the parent type of an array, enumeration or vlen datatype.
+        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
+        """(INT classtype) => BOOL class_is_present
 
-            Determine if a member of the given class exists in a compound
-            datatype.  The search is recursive.
+        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.
+        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)
@@ -465,11 +467,11 @@ cdef class TypeID(ObjectID):
     IF H5PY_18API:
         @sync
         def encode(self):
-            """ () => STRING
+            """() => 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.
+            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
@@ -505,18 +507,18 @@ cdef class TypeArrayID(TypeID):
 
     @sync
     def get_array_ndims(self):
-        """ () => INT rank
+        """() => INT rank
 
-            Get the rank of the given array datatype.
+        Get the rank of the given array datatype.
         """
         return H5Tget_array_ndims(self.id)
 
     @sync
     def get_array_dims(self):
-        """ () => TUPLE dimensions
+        """() => TUPLE dimensions
 
-            Get the dimensions of the given array datatype as
-            a tuple of integers.
+        Get the dimensions of the given array datatype as
+        a tuple of integers.
         """
         cdef hsize_t rank   
         cdef hsize_t* dims = NULL
@@ -548,18 +550,18 @@ cdef class TypeOpaqueID(TypeID):
 
     @sync
     def set_tag(self, char* tag):
-        """ (STRING tag)
+        """(STRING tag)
 
-            Set a string describing the contents of an opaque datatype.
-            Limited to 256 characters.
+        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
+        """() => STRING tag
 
-            Get the tag associated with an opaque datatype.
+        Get the tag associated with an opaque datatype.
         """
         cdef char* buf = NULL
 
@@ -583,49 +585,61 @@ cdef class TypeStringID(TypeID):
 
     @sync
     def is_variable_str(self):
-        """ () => BOOL is_variable
+        """() => BOOL is_variable
 
-            Determine if the given string datatype is a variable-length string.
-            Please note that reading/writing data in this format is impossible;
-            only fixed-length strings are currently supported.
+        Determine if the given string datatype is a variable-length string.
+        Please note that reading/writing data in this format is impossible;
+        only fixed-length strings are currently supported.
         """
         return <bint>(H5Tis_variable_str(self.id))
 
     @sync
     def get_cset(self):
-        """ () => INT character_set
+        """() => INT character_set
 
-            Retrieve the character set used for a string.
+        Retrieve the character set used for a string.
         """
         return <int>H5Tget_cset(self.id)
 
     @sync
     def set_cset(self, int cset):
-        """ (INT character_set)
+        """(INT character_set)
 
-            Set the character set used for a string.
+        Set the character set used for a string.
         """
         H5Tset_cset(self.id, <H5T_cset_t>cset)
 
     @sync
     def get_strpad(self):
-        """ () => INT padding_type
+        """() => INT padding_type
+
+        Get the padding type.  Legal values are:
+
+        STR_NULLTERM
+            NULL termination only (C style)
 
-            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)
+        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)
+        """(INT pad)
+
+        Set the padding type.  Legal values are:
+
+        STR_NULLTERM
+            NULL termination only (C style)
 
-            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)
+        STR_NULLPAD
+            Pad buffer with NULLs
+
+        STR_SPACEPAD
+            Pad buffer with spaces (FORTRAN style)
         """
         H5Tset_strpad(self.id, <H5T_str_t>pad)
 
@@ -675,64 +689,67 @@ cdef class TypeAtomicID(TypeID):
 
     @sync
     def get_order(self):
-        """ () => INT order
+        """() => INT order
+
+        Obtain the byte order of the datatype; one of:
 
-            Obtain the byte order of the datatype; one of:
-             ORDER_LE
-             ORDER_BE
+        - ORDER_LE
+        - ORDER_BE
         """
         return <int>H5Tget_order(self.id)
 
     @sync
     def set_order(self, int order):
-        """ (INT order)
+        """(INT order)
+
+        Set the byte order of the datatype; one of:
 
-            Set the byte order of the datatype; must be one of
-             ORDER_LE
-             ORDER_BE
+        - ORDER_LE
+        - ORDER_BE
         """
         H5Tset_order(self.id, <H5T_order_t>order)
 
     @sync
     def get_precision(self):
-        """ () => UINT precision
+        """() => UINT precision
 
-            Get the number of significant bits (excludes padding).
+        Get the number of significant bits (excludes padding).
         """
         return H5Tget_precision(self.id)
 
     @sync
     def set_precision(self, size_t precision):
-        """ (UINT precision)
+        """(UINT precision)
             
-            Set the number of significant bits (excludes padding).
+        Set the number of significant bits (excludes padding).
         """
         H5Tset_precision(self.id, precision)
 
     @sync
     def get_offset(self):
-        """ () => INT offset
+        """() => INT offset
 
-            Get the offset of the first significant bit.
+        Get the offset of the first significant bit.
         """
         return H5Tget_offset(self.id)
 
     @sync
     def set_offset(self, size_t offset):
-        """ (UINT offset)
+        """(UINT offset)
 
-            Set the offset of the first significant bit.
+        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)
+        """() => (INT lsb_pad_code, INT msb_pad_code)
 
-            Determine the padding type.  Possible values are:
-             PAD_ZERO
-             PAD_ONE
-             PAD_BACKGROUND
+        Determine the padding type.  Possible values are:
+
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
         """
         cdef H5T_pad_t lsb
         cdef H5T_pad_t msb
@@ -741,12 +758,13 @@ cdef class TypeAtomicID(TypeID):
 
     @sync
     def set_pad(self, int lsb, int msb):
-        """ (INT lsb_pad_code, INT msb_pad_code)
+        """(INT lsb_pad_code, INT msb_pad_code)
+
+        Set the padding type.  Possible values are:
 
-            Set the padding type.  Possible values are:
-             PAD_ZERO
-             PAD_ONE
-             PAD_BACKGROUND
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
         """
         H5Tset_pad(self.id, <H5T_pad_t>lsb, <H5T_pad_t>msb)
 
@@ -759,21 +777,29 @@ cdef class TypeIntegerID(TypeAtomicID):
 
     @sync
     def get_sign(self):
-        """ () => INT sign
+        """() => INT sign
 
-            Get the "signedness" of the datatype; one of:
-              SGN_NONE:  Unsigned
-              SGN_2:     Signed 2's complement
+        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)
+        """(INT sign)
+
+        Set the "signedness" of the datatype; one of:
 
-            Set the "signedness" of the datatype; one of:
-              SGN_NONE:  Unsigned
-              SGN_2:     Signed 2's complement
+        SGN_NONE
+            Unsigned
+
+        SGN_2
+            Signed 2's complement
         """
         H5Tset_sign(self.id, <H5T_sign_t>sign)
 
@@ -791,15 +817,16 @@ cdef class TypeFloatID(TypeAtomicID):
 
     @sync
     def get_fields(self):
-        """ () => TUPLE field_info
-
-            Get information about floating-point bit fields.  See the HDF5
-            docs for a better description.  Tuple has to following members:
-             0: UINT spos
-             1: UINT epos
-             2: UINT esize
-             3: UINT mpos
-             4: UINT msize
+        """() => 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)
@@ -808,70 +835,74 @@ cdef class TypeFloatID(TypeAtomicID):
     @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)
+        """(UINT spos, UINT epos, UINT esize, UINT mpos, UINT msize)
 
-            Set floating-point bit fields.  Refer to the HDF5 docs for
-            argument definitions.
+        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
+        """() => UINT ebias
 
-            Get the exponent bias.
+        Get the exponent bias.
         """
         return H5Tget_ebias(self.id)
 
     @sync
     def set_ebias(self, size_t ebias):
-        """ (UINT ebias)
+        """(UINT ebias)
 
-            Set the exponent bias.
+        Set the exponent bias.
         """
         H5Tset_ebias(self.id, ebias)
 
     @sync
     def get_norm(self):
-        """ () => INT normalization_code
+        """() => INT normalization_code
+
+        Get the normalization strategy.  Legal values are:
 
-            Get the normalization strategy.  Legal values are:
-             NORM_IMPLIED
-             NORM_MSBSET
-             NORM_NONE
+        - NORM_IMPLIED
+        - NORM_MSBSET
+        - NORM_NONE
         """
         return <int>H5Tget_norm(self.id)
 
     @sync
     def set_norm(self, int norm):
-        """ (INT normalization_code)
+        """(INT normalization_code)
+
+        Set the normalization strategy.  Legal values are:
 
-            Set the normalization strategy.  Legal values are:
-             NORM_IMPLIED
-             NORM_MSBSET
-             NORM_NONE
+        - NORM_IMPLIED
+        - NORM_MSBSET
+        - NORM_NONE
         """
         H5Tset_norm(self.id, <H5T_norm_t>norm)
 
     @sync
     def get_inpad(self):
-        """ () => INT pad_code
+        """() => INT pad_code
 
-            Determine the internal padding strategy.  Legal values are:
-             PAD_ZERO
-             PAD_ONE
-             PAD_BACKGROUND
+        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)
+        """(INT pad_code)
+
+        Set the internal padding strategy.  Legal values are:
 
-            Set the internal padding strategy.  Legal values are:
-             PAD_ZERO
-             PAD_ONE
-             PAD_BACKGROUND
+        - PAD_ZERO
+        - PAD_ONE
+        - PAD_BACKGROUND
         """
         H5Tset_inpad(self.id, <H5T_pad_t>pad_code)
 
@@ -891,18 +922,18 @@ cdef class TypeCompositeID(TypeID):
 
     @sync
     def get_nmembers(self):
-        """ () => INT number_of_members
+        """() => INT number_of_members
 
-            Determine the number of members in a compound or enumerated type.
+        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
+        """(INT member) => STRING name
         
-            Determine the name of a member of a compound or enumerated type,
-            identified by its index (0 <= member < nmembers).
+        Determine the name of a member of a compound or enumerated type,
+        identified by its index (0 <= member < nmembers).
         """
         cdef char* name
         name = NULL
@@ -921,10 +952,10 @@ cdef class TypeCompositeID(TypeID):
 
     @sync
     def get_member_index(self, char* name):
-        """ (STRING name) => INT index
+        """(STRING name) => INT index
 
-            Determine the index of a member of a compound or enumerated datatype
-            identified by a string name.
+        Determine the index of a member of a compound or enumerated datatype
+        identified by a string name.
         """
         return H5Tget_member_index(self.id, name)
 
@@ -938,10 +969,10 @@ cdef class TypeCompoundID(TypeCompositeID):
 
     @sync
     def get_member_class(self, int member):
-        """ (INT member) => INT class
+        """(INT member) => INT class
 
-            Determine the datatype class of the member of a compound type,
-            identified by its index (0 <= member < nmembers).
+        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.")
@@ -950,10 +981,10 @@ cdef class TypeCompoundID(TypeCompositeID):
 
     @sync
     def get_member_offset(self, int member):
-        """ (INT member) => INT offset
+        """(INT member) => INT offset
 
-            Determine the offset, in bytes, of the beginning of the specified
-            member of a compound datatype.
+        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.")
@@ -961,10 +992,10 @@ cdef class TypeCompoundID(TypeCompositeID):
 
     @sync
     def get_member_type(self, int member):
-        """ (INT member) => TypeID
+        """(INT member) => TypeID
 
-            Create a copy of a member of a compound datatype, identified by its
-            index.
+        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.")
@@ -972,20 +1003,20 @@ cdef class TypeCompoundID(TypeCompositeID):
 
     @sync
     def insert(self, char* name, size_t offset, TypeID field not None):
-        """ (STRING name, UINT offset, TypeID field)
+        """(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.
+        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.
+        Recursively removes padding (introduced on account of e.g. compiler
+        alignment rules) from a compound datatype.
         """
         H5Tpack(self.id)
 
@@ -1055,12 +1086,12 @@ cdef class TypeEnumID(TypeCompositeID):
 
     @sync
     def enum_insert(self, char* name, long long value):
-        """ (STRING name, INT/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.
+        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
 
@@ -1070,11 +1101,11 @@ cdef class TypeEnumID(TypeCompositeID):
 
     @sync
     def enum_nameof(self, long long value):
-        """ (LLONG value) => STRING name
+        """(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.
+        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]
@@ -1089,9 +1120,9 @@ cdef class TypeEnumID(TypeCompositeID):
 
     @sync
     def enum_valueof(self, char* name):
-        """ (STRING name) => LONG value
+        """(STRING name) => LONG value
 
-            Get the value associated with an enum name.
+        Get the value associated with an enum name.
         """
         cdef long long buf
 
@@ -1101,9 +1132,9 @@ cdef class TypeEnumID(TypeCompositeID):
 
     @sync
     def get_member_value(self, int idx):
-        """ (UINT index) => LONG value
+        """(UINT index) => LONG value
 
-            Determine the value for the member at the given zero-based index.
+        Determine the value for the member at the given zero-based index.
         """
         cdef herr_t retval
         cdef hid_t ptype
@@ -1274,20 +1305,20 @@ cdef TypeCompoundID _c_compound(dtype dt):
 
 
 cpdef TypeID py_create(object dtype_in, dict enum_vals=None):
-    """ (OBJECT dtype_in, DICT enum_vals=None) => TypeID
+    """(OBJECT dtype_in, DICT enum_vals=None) => 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.
+    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'.
+    Argument dtype_in may be a dtype object, or anything which can be
+    converted to a dtype, including strings like '<i4'.
 
-        enum_vals:
-            A optional dictionary mapping names to integer values.  If the
-            type being converted is an integer (Numpy kind i/u), the resulting 
-            HDF5 type will be an enumeration with that base type, and the 
-            given values. Ignored for all other types.
+    enum_vals
+        A optional dictionary mapping names to integer values.  If the
+        type being converted is an integer (Numpy kind i/u), the resulting 
+        HDF5 type will be an enumeration with that base type, and the 
+        given values. Ignored for all other types.
     """
     cdef dtype dt = dtype(dtype_in)
     cdef char kind = dt.kind
diff --git a/h5py/h5z.pyx b/h5py/h5z.pyx
index 22b6388..656c335 100644
--- a/h5py/h5z.pyx
+++ b/h5py/h5z.pyx
@@ -63,33 +63,34 @@ NO_EDC      = H5Z_NO_EDC
 
 @sync
 def filter_avail(int filter_code):
-    """ (INT filter_code) => BOOL available
+    """(INT filter_code) => BOOL
 
-        Determine if the given filter is available to the library.
+    Determine if the given filter is available to the library. The
+    filter code should be one of:
 
-        The filter code should be one of:
-         FILTER_DEFLATE
-         FILTER_SHUFFLE
-         FILTER_FLETCHER32
-         FILTER_SZIP
+    - FILTER_DEFLATE
+    - FILTER_SHUFFLE
+    - FILTER_FLETCHER32
+    - FILTER_SZIP
     """
     return <bint>H5Zfilter_avail(<H5Z_filter_t>filter_code)
 
 @sync
 def get_filter_info(int filter_code):
-    """ (INT filter_code) => INT filter_flags
+    """(INT filter_code) => INT filter_flags
 
-        Retrieve a bitfield with information about the given filter.
+    Retrieve a bitfield with information about the given filter. The
+    filter code should be one of:
 
-        The filter code should be one of:
-         FILTER_DEFLATE
-         FILTER_SHUFFLE
-         FILTER_FLETCHER32
-         FILTER_SZIP
+    - FILTER_DEFLATE
+    - FILTER_SHUFFLE
+    - FILTER_FLETCHER32
+    - FILTER_SZIP
 
-        Valid bitmasks for use with the returned bitfield are:
-         FILTER_CONFIG_ENCODE_ENABLED
-         FILTER_CONFIG_DECODE_ENABLED
+    Valid bitmasks for use with the returned bitfield are:
+
+    - FILTER_CONFIG_ENCODE_ENABLED
+    - FILTER_CONFIG_DECODE_ENABLED
     """
     cdef unsigned int flags
     H5Zget_filter_info(<H5Z_filter_t>filter_code, &flags)
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index d7a1645..fe51aeb 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -849,7 +849,12 @@ class AttributeManager(LockableObject):
     def __iter__(self):
         """ Iterate over the names of attributes. """
         with self._lock:
-            for name in h5a.py_listattrs(self.id):
+            attrlist = []
+            def iter_cb(name, *args):
+                attrlist.append(name)
+            h5a.iterate(self.id, iter_cb)
+
+            for name in attrlist:
                 yield name
 
     def iteritems(self):
diff --git a/h5py/tests/test_h5a.py b/h5py/tests/test_h5a.py
index b69afea..b11e4cd 100644
--- a/h5py/tests/test_h5a.py
+++ b/h5py/tests/test_h5a.py
@@ -179,12 +179,12 @@ class TestH5A(HDF5TestCase):
     def test_iterate(self):
 
         namelist = []
-        result = h5a.iterate(self.obj, namelist.append)
+        result = h5a.iterate(self.obj, lambda name, *args: namelist.append(name))
         self.assertEqual(namelist, ATTRIBUTES_ORDER)
         self.assert_(result is None)
 
         namelist = []
-        def iterate_two(name):
+        def iterate_two(name, *args):
             if len(namelist) >= 2:
                 return True
             namelist.append(name)
@@ -192,7 +192,7 @@ class TestH5A(HDF5TestCase):
         self.assertEqual(namelist, ATTRIBUTES_ORDER[0:2])
         self.assert_(result is True)
 
-        def iter_fault(name):
+        def iter_fault(name, *args):
             raise RuntimeError
         self.assertRaises(RuntimeError, h5a.iterate, self.obj, iter_fault)
 
@@ -214,12 +214,6 @@ class TestH5A(HDF5TestCase):
             attr = h5a.open(self.obj, name)
             self.assertEqual(attr.dtype, dt)
 
-    def test_py_listattrs(self):
-
-        attrlist = h5a.py_listattrs(self.obj)
-
-        self.assertEqual(attrlist, ATTRIBUTES_ORDER)
-
     def test_exists(self):
 
         self.assert_(h5a.exists(self.obj, ATTRIBUTES_ORDER[0]))
diff --git a/h5py/tests/test_utils.py b/h5py/tests/test_utils.py
index 1636a0f..0ef759f 100644
--- a/h5py/tests/test_utils.py
+++ b/h5py/tests/test_utils.py
@@ -68,11 +68,6 @@ class TestUtils(HDF5TestCase):
         carr.flags['WRITEABLE'] = False
         self.assertRaises(TypeError, utils.check_numpy_write, carr)
 
-    def test_emalloc(self):
-        
-        utils._test_emalloc(1024)
-        utils._test_emalloc(0)
-        self.assertRaises(MemoryError, utils._test_emalloc, sys.maxint)
 
 
 

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