[h5py] 63/455: More unit tests, new highlevel classes

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:18 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 3a3c9866cb97a12c558d865bf2f8c4bd82f0642e
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Thu Jul 3 01:14:32 2008 +0000

    More unit tests, new highlevel classes
---
 h5py/__init__.py       |   3 +-
 h5py/h5.pyx            |   7 +-
 h5py/h5a.pyx           |  20 ++
 h5py/h5f.pyx           |  20 +-
 h5py/h5g.pyx           |  34 +++
 h5py/h5s.pyx           |   2 +-
 h5py/h5z.pyx           |  20 --
 h5py/highlevel.py      | 584 +++++++++++++++----------------------------------
 h5py/tests/__init__.py |   8 +-
 h5py/tests/test_h5.py  |   5 +-
 h5py/tests/test_h5a.py |  22 ++
 h5py/tests/test_h5f.py |   2 +
 h5py/tests/test_h5g.py |   5 +-
 h5py/tests/test_h5s.py | 167 +++++---------
 h5py/utils_hl.py       | 108 +++++++++
 15 files changed, 449 insertions(+), 558 deletions(-)

diff --git a/h5py/__init__.py b/h5py/__init__.py
index a398ff4..cfb9ece 100644
--- a/h5py/__init__.py
+++ b/h5py/__init__.py
@@ -22,7 +22,8 @@ __doc__ = \
     See the docstring for the "version" module for a longer introduction.
 """
 
-import utils, h5, h5f, h5g, h5s, h5t, h5d, h5a, h5p, h5z, h5i
+import utils, h5, h5f, h5g, h5s, h5t, h5d, h5a, h5p, h5z, h5i, highlevel
 import version
 
 __doc__ = __doc__ % version.version
+
diff --git a/h5py/h5.pyx b/h5py/h5.pyx
index 92c7b7d..3add6ad 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -61,11 +61,16 @@ cdef class ObjectID:
 
     def __dealloc__(self):
         """ Automatically decrefs the ID, if it's valid. """
+        print "Dealloc"
         if (not self._locked) and (H5Iget_type(self.id) != H5I_BADID):
             H5Idec_ref(self.id)
 
     def __copy__(self):
-        """ Create another object wrapper which points to the same id. """
+        """ Create another object wrapper which points to the same id. 
+
+            WARNING: Locks (i.e. datatype lock() methods) do NOT work correctly
+            across copies.
+        """
         cdef ObjectID copy
         copy = type(self)(self.id)
         assert typecheck(copy, ObjectID), "ObjectID copy encountered invalid type"
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index f89de2a..765aa25 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -112,6 +112,26 @@ def iterate(ObjectID loc not None, object func, object data=None, int startidx=0
 
     H5Aiterate(loc.id, &i, <H5A_operator_t>iter_cb, int_tpl)
 
+cdef herr_t list_cb(hid_t loc_id, char *attr_name, object listin):
+    
+    cdef list thelist
+    thelist = listin
+
+    thelist.append(attr_name)
+    return 0
+
+def py_listattrs(ObjectID loc not None):
+    """ (ObjectID loc) => LIST attr_names
+
+        Get a list of the names of the attributes attached to an object.
+    """
+    cdef list retlist
+    cdef unsigned int i
+    i = 0
+    retlist = []
+    H5Aiterate(loc.id, &i, <H5A_operator_t>list_cb, retlist)
+    return retlist
+
 # === Attribute class & methods ===============================================
 
 cdef class AttrID(ObjectID):
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index 7765eb9..3c25fda 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -77,14 +77,6 @@ def create(char* name, int flags=H5F_ACC_TRUNC, PropFCID createlist=None,
     access_id = pdefault(accesslist)
     return FileID(H5Fcreate(name, flags, create_id, access_id))
 
-def is_hdf5(char* name):
-    """ (STRING name) => BOOL is_hdf5
-
-        Determine if a given file is an HDF5 file.  Note this raises an 
-        exception if the file doesn't exist.
-    """
-    return pybool(H5Fis_hdf5(name))
-
 def flush(ObjectID obj not None, int scope=H5F_SCOPE_LOCAL):
     """ (ObjectID obj, INT scope=SCOPE_LOCAL)
 
@@ -96,6 +88,14 @@ def flush(ObjectID obj not None, int scope=H5F_SCOPE_LOCAL):
     """
     H5Fflush(obj.id, <H5F_scope_t>scope)
 
+def is_hdf5(char* name):
+    """ (STRING name) => BOOL is_hdf5
+
+        Determine if a given file is an HDF5 file.  Note this raises an 
+        exception if the file doesn't exist.
+    """
+    return pybool(H5Fis_hdf5(name))
+
 def mount(ObjectID loc not None, char* name, FileID fid not None, 
           PropMID mountlist=None):
     """ (ObjectID loc, STRING name, FileID fid, PropMID mountlist=None)
@@ -207,6 +207,10 @@ cdef class FileID(ObjectID):
     """ 
         Represents an HDF5 file identifier.
     """
+    property name:
+        """ File name on disk (according to h5f.get_name()) """
+        def __get__(self):
+            return get_name(self)
 
     def close(self):
         """ ()
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 6a8a0a8..c12768a 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -55,6 +55,33 @@ cdef class GroupStat:
     cdef readonly time_t mtime
     cdef readonly size_t linklen
 
+cdef class GroupIter:
+
+    """
+        Iterator over the names of group members.  After this iterator is
+        exhausted, it releases its reference to the group ID.
+    """
+
+    cdef unsigned long idx
+    cdef unsigned long nobjs
+    cdef GroupID grp
+
+    def __init__(self, GroupID grp not None):
+        self.idx = 0
+        self.grp = grp
+        self.nobjs = grp.get_num_objs()
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if self.idx == self.nobjs:
+            self.grp = None
+            raise StopIteration
+        
+        retval = self.grp.get_objname_by_idx(self.idx)
+        self.idx = self.idx + 1
+        return retval
 
 # === Basic group management ==================================================
 
@@ -315,4 +342,11 @@ cdef class GroupID(ObjectID):
             return False    
         return True
 
+    def py_iter(self):
+        """ () => ITERATOR
+
+            Return an iterator over the names of group members.
+        """
+        return GroupIter(self)
+
 
diff --git a/h5py/h5s.pyx b/h5py/h5s.pyx
index 2deb75f..e3944a8 100644
--- a/h5py/h5s.pyx
+++ b/h5py/h5s.pyx
@@ -63,7 +63,7 @@ SEL_ALL         = H5S_SEL_ALL
 def create(int class_code):
     """ (INT class_code) => SpaceID
 
-        Create a new HDF5 dataspace object, of the given class.  
+        Create a new HDF5 dataspace object, of the given class.
         Legal values are SCALAR and SIMPLE.
     """
     return SpaceID(H5Screate(<H5S_class_t>class_code))
diff --git a/h5py/h5z.pyx b/h5py/h5z.pyx
index d662da3..39a6938 100644
--- a/h5py/h5z.pyx
+++ b/h5py/h5z.pyx
@@ -88,26 +88,6 @@ def get_filter_info(int filter_code):
     H5Zget_filter_info(<H5Z_filter_t>filter_id, &flags)
     return flags
 
-# === Python extensions =======================================================
-
-PY_FILTER = DDict({ H5Z_FILTER_ERROR: 'ERROR', H5Z_FILTER_NONE: 'NONE',
-            H5Z_FILTER_ALL: 'ALL', H5Z_FILTER_DEFLATE: 'DEFLATE',
-            H5Z_FILTER_SHUFFLE: 'SHUFFLE', H5Z_FILTER_FLETCHER32: 'FLETCHER32',
-            H5Z_FILTER_SZIP: 'SZIP', H5Z_FILTER_RESERVED: 'RESERVED'})
-
-PY_FLAG = DDict({ H5Z_FLAG_DEFMASK: 'DEFMASK', H5Z_FLAG_MANDATORY: 'MANDATORY',
-            H5Z_FLAG_OPTIONAL: 'OPTIONAL', H5Z_FLAG_INVMASK: 'INVMASK',
-            H5Z_FLAG_REVERSE: 'REVERSE', H5Z_FLAG_SKIP_EDC: 'SKIP EDC' })
-
-PY_FILTER_CONFIG = DDict({H5Z_FILTER_CONFIG_ENCODE_ENABLED: 'ENCODE ENABLED',
-                        H5Z_FILTER_CONFIG_DECODE_ENABLED: 'ENCODE DISABLED'})
-
-PY_EDC   = DDict({H5Z_ERROR_EDC: 'ERROR', H5Z_DISABLE_EDC: 'DISABLE EDC',
-                    H5Z_ENABLE_EDC: 'ENABLE EDC', H5Z_NO_EDC: 'NO EDC' })
-
-
-
-
 
 
 
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index 975a9c5..dcd5327 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -10,63 +10,164 @@
 # 
 #-
 
-"""
-    Provides high-level Python objects for HDF5 files, groups, and datasets.  
+import copy
+import numpy
+
+from h5py import h5, h5f, h5g, h5s, h5t, h5d, h5a, h5p, h5z, h5i
+from utils_hl import slicer
 
-    Highlights:
 
-    - Groups provide dictionary-like __getitem__ access to their members, and 
-      allow iteration over member names.  File objects also perform these
-      operations, implicitly on the root ('/') group.
+class Group(object):
+
+    #: Provides access to HDF5 attributes. See AttributeManager docstring.
+    attrs = property(lambda self: self._attrs)
+
+    def __init__(self, parent_object, name, create=False):
+        """ Create a new Group object, from a parent object and a name.
 
-    - Datasets support Numpy dtype and shape access, along with read/write 
-      access to the underlying HDF5 dataset (including slicing for partial I/0),
-      and reading/writing specified fields of a compound type object.
+            If "create" is False (default), try to open the given group,
+            raising an exception if it doesn't exist.  If "create" is True,
+            create a new HDF5 group and link it into the parent group.
+        """
+        if create:
+            self.id = h5g.create(parent_object.id, name)
+        else:
+            self.id = h5g.open(parent_object.id, name)
 
-    - Both group and dataset attributes can be accessed via a dictionary-style
-      attribute manager (group_obj.attrs and dataset_obj.attrs).  See the
-      highlevel.AttributeManager docstring for more information.
+        self._attrs = AttributeManager(self)
 
-    - Named datatypes are reached through the NamedType class, which allows
-      attribute access like Group and Dataset objects.
+    def __setitem__(self, name, obj):
+        """ Add the given object to the group.  Here are the rules:
 
-    - An interactive command-line utility "browse(filename)" allows access to 
-      HDF5 datasets, with commands like "cd, ls", etc.  Also allows you to
-      import groups and datasets directly into Python as highlevel.Group and
-      highlevel.Dataset objects.
+            1. If "obj" is a Dataset or Group object, a hard link is created
+                in this group which points to the given object.
 
-    - There are no "h5py.highlevel" exceptions; classes defined here raise 
-      native Python exceptions.  However, they will happily propagate 
-      exceptions from the underlying h5py.h5* modules, which are (mostly) 
-      subclasses of h5py.errors.H5Error.
-"""
+            2. If "obj" is a Numpy ndarray, it is converted to a dataset
+                object, with default settings (contiguous storage, etc.).
 
-__revision__ = "$Id$"
+            3. If "obj" is anything else, attempt to convert it to an ndarray
+                and store it.  Scalar values are stored as scalar datasets.
+                Raise ValueError if we can't understand the resulting array 
+                dtype.
+        """
+        if isinstance(obj, Group) or isinstance(obj, Dataset):
+            self.id.link(name, h5i.get_name(obj.id), link_type=h5g.LINK_HARD)
+        else:
+            if not isinstance(obj, numpy.ndarray):
+                obj = numpy.array(obj)
+            dset = Dataset(self, name, data=obj)
+            dset.close()
 
-import os
-import cmd
-import random
-import string
-import numpy
+    def __getitem__(self, name):
+        """ Open an object attached to this group. """
+
+        info = self.id.get_objinfo(name)
+
+        if info.type == h5g.DATASET:
+            dset = Dataset(self, name)
+            if dset.shape == ():
+                return dset[...]
+            return dset
+
+        elif info.type == h5g.GROUP:
+            return Group(self, name)
+
+        elif info.type == h5g.TYPE:
+            return Datatype(self, name)
+
+        raise ValueError("Don't know how to open object of type %d" % info.type)
+
+    def __delitem__(self, name):
+        """ Delete (unlink) an item from this group. """
+        self.id.unlink(name)
+
+    def __len__(self):
+        return self.id.get_num_objs()
+
+    def __iter__(self):
+        return self.id.py_iter()
+
+    def __str__(self):
+        return 'Group (%d members): ' % len(self) + ', '.join(['"%s"' % name for name in self])
+
+    def __repr__(self):
+        return str(self)
+
+    def iteritems(self):
+        for name in self:
+            return (name, self[name])
 
-import h5f
-import h5g
-import h5i
-import h5d
-import h5t
-import h5a
-import h5p
-from h5e import H5Error
+class File(Group):
 
-# === Main classes (Dataset/Group/File) =======================================
+    """ Represents an HDF5 file on disk.
+
+        Created with standard Python syntax File(name, mode), where mode may be
+        one of r, r+, w, w+, a.
+
+        File objects inherit from Group objects; Group-like methods all
+        operate on the HDF5 root group ('/').  Like Python file objects, you
+        must close the file ("obj.close()") when you're done with it.
+    """
+    name = property(lambda self: self._name)
+    mode = property(lambda self: self._mode)
+
+    _modes = ('r','r+','w','w+','a')
+
+    # --- Public interface (File) ---------------------------------------------
+
+    def __init__(self, name, mode, noclobber=False):
+        """ Create a new file object.  
+
+            Valid modes (like Python's file() modes) are: 
+            - 'r'   Readonly, file must exist
+            - 'r+'  Read/write, file must exist
+            - 'w'   Write, create/truncate file
+            - 'w+'  Read/write, create/truncate file
+            - 'a'   Read/write, file must exist (='r+')
+
+            If "noclobber" is specified, file truncation (w/w+) will fail if 
+            the file already exists.  Note this is NOT the default.
+        """
+        if not mode in self._modes:
+            raise ValueError("Invalid mode; must be one of %s" % ', '.join(self._modes))
+
+        plist = h5p.create(h5p.FILE_ACCESS)
+        plist.set_fclose_degree(h5f.CLOSE_STRONG)
+        if mode == 'r':
+            self.fid = h5f.open(name, h5f.ACC_RDONLY, accesslist=plist)
+        elif 'r' in mode or 'a' in mode:
+            self.fid = h5f.open(name, h5f.ACC_RDWR, accesslist=plist)
+        elif noclobber:
+            self.fid = h5f.create(name, h5f.ACC_EXCL, accesslist=plist)
+        else:
+            self.fid = h5f.create(name, h5f.ACC_TRUNC, accesslist=plist)
+
+        self.id = self.fid  # So the Group constructor can find it.
+        Group.__init__(self, self, '/')
+    
+        self._name = name
+        self._mode = mode
+
+    def close(self):
+        """ Close this HDF5 file.  All open identifiers will become invalid.
+        """
+        self.id.close()
+        self.fid.close()
+
+    def flush(self):
+        h5f.flush(self.fid)
+
+    def __str__(self):
+        return 'File "%s", root members: %s' % (self.name, ', '.join(['"%s"' % name for name in self]))
+
+    def __repr_(self):
+        return str(self)
 
 class Dataset(object):
 
     """ High-level interface to an HDF5 dataset
     """
 
-    # --- Properties (Dataset) ------------------------------------------------
-
     shape = property(lambda self: self.id.shape,
         doc = "Numpy-style shape tuple giving dataset dimensions")
 
@@ -76,8 +177,6 @@ class Dataset(object):
     attrs = property(lambda self: self._attrs,
         doc = "Provides access to HDF5 attributes")
 
-    # --- Public interface (Dataset) ------------------------------------------
-
     def __init__(self, group, name,
                     data=None, dtype=None, shape=None, 
                     chunks=None, compression=None, shuffle=False, fletcher32=False):
@@ -175,11 +274,11 @@ class Dataset(object):
         fspace.select_hyperslab(start, count, stride)
         mspace = h5s.create_simple(count)
 
-        arr = ndarray(count, mtype.dtype)
+        arr = numpy.ndarray(count, mtype.dtype)
 
         self.id.read(mspace, fspace, arr)
 
-        if len(names) == 1
+        if len(names) == 1:
             # Match Numpy convention for recarray indexing
             return arr[names[0]]
         return arr
@@ -191,225 +290,26 @@ class Dataset(object):
             array's datatype.
         """
         val = args[-1]
-        start, count, stride, names = slicer(val.shape, args[:-1])
-        if len(names) > 0:
-            raise ValueError("Field names are not allowed for write.")
-
-        self.id.
-        h5d.py_write_slab(self.id, args[-1], start, stride)
-
-
-    def __str__(self):
-        return 'Dataset: '+str(self.shape)+'  '+repr(self.dtype)
-
-    def __repr__(self):
-        return self.__str__()
-
-class Group(object):
-    """ Represents an HDF5 group object
-
-        Group members are accessed through dictionary-style syntax.  Iterating
-        over a group yields the names of its members, while the method
-        iteritems() yields (name, value) pairs. Examples:
-
-            highlevel_obj = group_obj["member_name"]
-            member_list = list(group_obj)
-            member_dict = dict(group_obj.iteritems())
-
-        - Accessing items: generally a Group or Dataset object is returned. In
-          the special case of a scalar dataset, a Numpy array scalar is
-          returned.
-
-        - Setting items:
-            1. Existing Group or Dataset: create a hard link in this group
-            2. Numpy array: create a new dataset here, overwriting any old one
-            3. Anything else: try to create a Numpy array.  Also works with
-               Python scalars which have Numpy type equivalents.
-
-        - Deleting items: unlinks the object from this group.
-
-        - Attribute access: through the property obj.attrs.  See the 
-          AttributeManager class documentation for more information.
-
-        - len(obj) returns the number of group members
-    """
-
-    #: Provides access to HDF5 attributes. See AttributeManager docstring.
-    attrs = property(lambda self: self._attrs)
-
-    # --- Public interface (Group) --------------------------------------------
-
-    def __init__(self, parent_object, name, create=False):
-        """ Create a new Group object, from a parent object and a name.
-
-            If "create" is False (default), try to open the given group,
-            raising an exception if it doesn't exist.  If "create" is True,
-            create a new HDF5 group and link it into the parent group.
-        """
-        if create:
-            self.id = h5g.create(parent_object.id, name)
-        else:
-            self.id = h5g.open(parent_object.id, name)
-        
-        #: Group attribute access (dictionary-style)
-        self._attrs = AttributeManager(self)
-
-    def __delitem__(self, name):
-        """ Unlink a member from the HDF5 group.
-        """
-        h5g.unlink(self.id, name)
-
-    def __setitem__(self, name, obj):
-        """ Add the given object to the group.  Here are the rules:
-
-            1. If "obj" is a Dataset or Group object, a hard link is created
-                in this group which points to the given object.
-            2. If "obj" is a Numpy ndarray, it is converted to a dataset
-                object, with default settings (contiguous storage, etc.).
-            3. If "obj" is anything else, attempt to convert it to an ndarray
-                and store it.  Scalar values are stored as scalar datasets.
-                Raise ValueError if we can't understand the resulting array 
-                dtype.
-        """
-        if isinstance(obj, Group) or isinstance(obj, Dataset):
-            h5g.link(self.id, name, h5i.get_name(obj.id), link_type=h5g.LINK_HARD)
+        args = args[0:-1]
 
-        else:
-            if not isinstance(obj, numpy.ndarray):
-                obj = numpy.array(obj)
-            if h5t.py_can_convert_dtype(obj.dtype):
-                dset = Dataset(self, name, data=obj)
-                dset.close()
-            else:
-                raise ValueError("Don't know how to store data of this type in a dataset: " + repr(obj.dtype))
-
-
-    def __getitem__(self, name):
-        """ Retrive the Group or Dataset object.  If the Dataset is scalar,
-            returns its value instead.
-        """
-        retval = _open_arbitrary(self, name)
-        if isinstance(retval, Dataset) and retval.shape == ():
-            value = h5d.py_read_slab(retval.id, (), ())
-            value = value.astype(value.dtype.type)
-            retval.close()
-            return value
-        return retval
-
-    def __iter__(self):
-        """ Yield the names of group members.
-        """
-        return h5g.py_iternames(self.id)
-
-    def iteritems(self):
-        """ Yield 2-tuples of (member_name, member_value).
-        """
-        for name in self:
-            yield (name, self[name])
+        start, count, stride, names = slicer(self.shape, args)
+        if len(names) != 0:
+            raise ValueError("Field name selections are not allowed for write.")
 
-    def __len__(self):
-        return h5g.get_num_objs(self.id)
+        if count != val.shape:
+            raise ValueError("Selection shape (%s) must match target shape (%s)" % (str(count), str(val.shape)))
 
-    def close(self):
-        """ Immediately close the underlying HDF5 object.  Further operations
-            on this Group object will raise an exception.  You don't typically
-            have to use this, as these objects are automatically closed when
-            their Python equivalents are deallocated.
-        """
-        h5g.close(self.id)
+        fspace = self.id.get_space()
+        fspace.select_hyperslab(start, count, stride)
+        mspace = h5s.create_simple(val.shape)
 
-    def __del__(self):
-        if h5i.get_type(self.id) == h5i.GROUP:
-            h5g.close(self.id)
+        self.id.write(mspace, fspace, array(val))
 
     def __str__(self):
-        return 'Group (%d members): ' % self.nmembers + ', '.join(['"%s"' % name for name in self])
+        return 'Dataset: '+str(self.shape)+'  '+repr(self.dtype)
 
     def __repr__(self):
-        return self.__str__()
-
-class File(Group):
-
-    """ Represents an HDF5 file on disk.
-
-        Created with standard Python syntax File(name, mode), where mode may be
-        one of r, r+, w, w+, a.
-
-        File objects inherit from Group objects; Group-like methods all
-        operate on the HDF5 root group ('/').  Like Python file objects, you
-        must close the file ("obj.close()") when you're done with it.
-    """
-
-    _modes = ('r','r+','w','w+','a')
-
-    # --- Public interface (File) ---------------------------------------------
-
-    def __init__(self, name, mode, noclobber=False):
-        """ Create a new file object.  
-
-            Valid modes (like Python's file() modes) are: 
-            - 'r'   Readonly, file must exist
-            - 'r+'  Read/write, file must exist
-            - 'w'   Write, create/truncate file
-            - 'w+'  Read/write, create/truncate file
-            - 'a'   Read/write, file must exist (='r+')
-
-            If "noclobber" is specified, file truncation (w/w+) will fail if 
-            the file already exists.  Note this is NOT the default.
-        """
-        if not mode in self._modes:
-            raise ValueError("Invalid mode; must be one of %s" % ', '.join(self._modes))
-              
-        plist = h5p.create(h5p.FILE_ACCESS)
-        try:
-            h5p.set_fclose_degree(plist, h5f.CLOSE_STRONG)
-            if mode == 'r':
-                self.fid = h5f.open(name, h5f.ACC_RDONLY, access_id=plist)
-            elif 'r' in mode or 'a' in mode:
-                self.fid = h5f.open(name, h5f.ACC_RDWR, access_id=plist)
-            elif noclobber:
-                self.fid = h5f.create(name, h5f.ACC_EXCL, access_id=plist)
-            else:
-                self.fid = h5f.create(name, h5f.ACC_TRUNC, access_id=plist)
-        finally:
-            h5p.close(plist)
-
-        self.id = self.fid  # So the Group constructor can find it.
-        Group.__init__(self, self, '/')
-
-        # For __str__ and __repr__
-        self.filename = name
-        self.mode = mode
-        self.noclobber = noclobber
-
-    def close(self):
-        """ Close this HDF5 object.  Note that any further access to objects
-            defined in this file will raise an exception.
-        """
-        if h5i.get_type(self.fid) != h5i.FILE:
-            raise IOError("File is already closed.")
-
-        Group.close(self)
-        h5f.close(self.fid)
-
-    def flush(self):
-        """ Instruct the HDF5 library to flush disk buffers for this file.
-        """
-        h5f.flush(self.fid)
-
-    def __del__(self):
-        """ This docstring is here to remind you that THE HDF5 FILE IS NOT 
-            AUTOMATICALLY CLOSED WHEN IT'S GARBAGE COLLECTED.  YOU MUST
-            CALL close() WHEN YOU'RE DONE WITH THE FILE.
-        """
-        pass
-
-    def __str__(self):
-        return 'File "%s", root members: %s' % (self.filename, ', '.join(['"%s"' % name for name in self]))
-
-    def __repr_(self):
-        return 'File("%s", "%s", noclobber=%s)' % (self.filename, self.mode, str(self.noclobber))
-
+        return str(self)
 
 class AttributeManager(object):
 
@@ -431,21 +331,34 @@ class AttributeManager(object):
         
         - len(obj.attrs) returns the number of attributes.
     """
-    def __init__(self, parent_object):
-        self.id = parent_object.id
+    def __init__(self, parent):
+
+        self.id = parent.id
 
     def __getitem__(self, name):
-        obj = h5a.py_get(self.id, name)
-        if len(obj.shape) == 0:
-            return obj.dtype.type(obj)
-        return obj
+        attr = h5a.open_name(self.id, name)
+
+        arr = numpy.ndarray(attr.shape, dtype=attr.dtype)
+        attr.read(arr)
+
+        if len(arr.shape) == 0:
+            return numpy.asscalar(arr)
+        return arr
 
     def __setitem__(self, name, value):
         if not isinstance(value, numpy.ndarray):
             value = numpy.array(value)
-        if h5a.py_exists(self.id, name):
+
+        space = h5s.create_simple(value.shape)
+        htype = h5t.py_create(value.dtype)
+
+        # TODO: some kind of transaction safeguard here
+        try:
             h5a.delete(self.id, name)
-        h5a.py_set(self.id, name, value)
+        except H5Error:
+            pass
+        attr = h5a.py_create(self.id, name, htype, space)
+        attr.write(value)
 
     def __delitem__(self, name):
         h5a.delete(self.id, name)
@@ -464,155 +377,10 @@ class AttributeManager(object):
     def __str__(self):
         return "Attributes: "+', '.join(['"%s"' % x for x in self])
 
-class NamedType(object):
-
-    """ Represents a named datatype, stored in a file.  
-
-        HDF5 datatypes are typically represented by their Numpy dtype
-        equivalents; this class exists only to provide access to attributes
-        stored on HDF5 named types.  Properties:
 
-        dtype:   Equivalent Numpy dtype for this HDF5 type
-        attrs:   AttributeManager instance for attribute access
-
-        Like dtype objects, these are immutable; the worst you can do it
-        unlink them from their parent group.
-    """ 
-        
-    def _get_dtype(self):
-        if self._dtype is None:
-            self._dtype = h5t.py_translate_h5t(self.id)
-        return self._dtype
-
-    dtype = property(_get_dtype)
-
-    def __init__(self, group, name, dtype=None):
-        """ Open an existing HDF5 named type, or create one.
-
-            If no value is provided for "dtype", try to open a named type
-            called "name" under the given group.  If "dtype" is anything
-            which can be converted to a Numpy dtype, create a new datatype
-            based on it and store it in the group.
-        """
-        self.id = None
-        self._dtype = None  # Defer initialization; even if the named type 
-                            # isn't Numpy-compatible, we can still get at the
-                            # attributes.
-
-        if dtype is not None:
-            dtype = numpy.dtype(dtype)
-            tid = h5t.py_translate_dtype(dtype)
-            try:
-                h5t.commit(group.id, name, tid)
-            finally:
-                h5t.close(tid)
-
-        self.id = h5t.open(group.id, name)
-        self.attrs = AttributeManager(self)
-
-    def close(self):
-        """ Force the library to close this object.  It will still exist
-            in the file.
-        """
-        if self.id is not None:
-            h5t.close(self.id)
-            self.id = None
-
-    def __del__(self):
-        if self.id is not None:
-            h5t.close(self.id)
-
-# === Utility functions =======================================================
-
-def slicer(shape, args):
-    """
-        Parse Numpy-style extended slices.  Correctly handle:
-        1. Recarray-style field strings (more than one!)
-        2. Slice objects
-        3. Ellipsis objects
-    """
-    rank = len(shape)
 
-    if not isinstance(args, tuple):
-        args = (args,)
-    args = list(args)
 
-    slices = []
-    names = []
-
-    # Sort arguments
-    for entry in args[:]:
-        if isinstance(entry, str):
-            names.append(entry)
-        else:
-            slices.append(entry)
-
-    start = []
-    count = []
-    stride = []
-
-    # Hack to allow Numpy-style row indexing
-    if len(slices) == 1:
-        args.append(Ellipsis)
-
-    # Expand integers and ellipsis arguments to slices
-    for dim, arg in enumerate(slices):
-
-        if isinstance(arg, int) or isinstance(arg, long):
-            if arg < 0:
-                raise ValueError("Negative indices are not allowed.")
-            start.append(arg)
-            count.append(1)
-            stride.append(1)
-
-        elif isinstance(arg, slice):
-
-            # slice.indices() method clips, so do it the hard way...
-
-            # Start
-            if arg.start is None:
-                ss=0
-            else:
-                if arg.start < 0:
-                    raise ValueError("Negative dimensions are not allowed")
-                ss=arg.start
-
-            # Stride
-            if arg.step is None:
-                st = 1
-            else:
-                if arg.step <= 0:
-                    raise ValueError("Only positive step sizes allowed")
-                st = arg.step
-
-            # Count
-            if arg.stop is None:
-                cc = shape[dim]/st
-            else:
-                if arg.stop < 0:
-                    raise ValueError("Negative dimensions are not allowed")
-                cc = (arg.stop-ss)/st
-            if cc == 0:
-                raise ValueError("Zero-length selections are not allowed")
-
-            start.append(ss)
-            stride.append(st)
-            count.append(cc)
-
-        elif arg == Ellipsis:
-            nslices = rank-(len(slices)-1)
-            if nslices <= 0:
-                continue
-            for x in range(nslices):
-                idx = dim+x
-                start.append(0)
-                count.append(shape[dim+x])
-                stride.append(1)
-
-        else:
-            raise ValueError("Bad slice type %s" % repr(arg))
 
-    return (start, count, stride, names)
 
 
 
diff --git a/h5py/tests/__init__.py b/h5py/tests/__init__.py
index 9650cfa..01372de 100644
--- a/h5py/tests/__init__.py
+++ b/h5py/tests/__init__.py
@@ -12,13 +12,15 @@
 
 import unittest
 import sys
-import test_h5a, test_h5d, test_h5f, test_h5g, test_h5i, test_h5p
+import test_h5a, test_h5d, test_h5f, \
+       test_h5g, test_h5i, test_h5p, \
+       test_h5s, test_h5
 
 from h5py import h5a, h5f, h5g, h5d, h5s, h5i, h5z, h5p
 
 TEST_CASES = (test_h5a.TestH5A, test_h5d.TestH5D, test_h5f.TestH5F, 
-              test_h5g.TestH5G, test_h5i.TestH5I, test_h5p.TestH5P)#, test_h5.TestH5,
-              #test_h5s.TestH5S, test_highlevel.TestHighlevel)
+              test_h5g.TestH5G, test_h5i.TestH5I, test_h5p.TestH5P,
+              test_h5s.TestH5S, test_h5.TestH5)
 
 def buildsuite(cases):
 
diff --git a/h5py/tests/test_h5.py b/h5py/tests/test_h5.py
index 1e47990..9908bea 100644
--- a/h5py/tests/test_h5.py
+++ b/h5py/tests/test_h5.py
@@ -21,6 +21,5 @@ class TestH5(unittest.TestCase):
 
         self.assertEqual(tpl, h5.HDF5_VERS_TPL)
         self.assertEqual("%d.%d.%d" % tpl, h5.HDF5_VERS)
-        self.assertEqual(h5.API_VERS, '1.6')
-        self.assertEqual(h5.API_VERS_TPL, (1,6))
-
+        h5.API_VERS
+        h5.API_VERS_TPL
diff --git a/h5py/tests/test_h5a.py b/h5py/tests/test_h5a.py
index d55333d..6b43d2e 100644
--- a/h5py/tests/test_h5a.py
+++ b/h5py/tests/test_h5a.py
@@ -181,7 +181,29 @@ class TestH5A(unittest.TestCase):
         h5a.iterate(self.obj, iterate_two, namelist, 1)
         self.assertEqual(namelist, ATTRIBUTES_ORDER[1:3])
 
+    def test_prop_name(self):
+        
+        for name in ATTRIBUTES:
+            attr = h5a.open_name(self.obj, name)
+            self.assertEqual(attr.name, name)
+
+    def test_prop_shape(self):
+
+        for name, (val, dt, shape) in ATTRIBUTES.iteritems():
+            attr = h5a.open_name(self.obj, name)
+            self.assertEqual(attr.shape, shape)
+
+    def test_prop_dtype(self):
+
+        for name, (val, dt, shape) in ATTRIBUTES.iteritems():
+            attr = h5a.open_name(self.obj, name)
+            self.assertEqual(attr.dtype, dt)
+
+    def test_py_listattrs(self):
+
+        attrlist = h5a.py_listattrs(self.obj)
 
+        self.assertEqual(attrlist, ATTRIBUTES_ORDER)
 
 
 
diff --git a/h5py/tests/test_h5f.py b/h5py/tests/test_h5f.py
index 8c9c63f..cb2d1c4 100644
--- a/h5py/tests/test_h5f.py
+++ b/h5py/tests/test_h5f.py
@@ -91,6 +91,8 @@ class TestH5F(unittest.TestCase):
         self.assert_(isinstance(idlist, list))
         self.assertRaises(H5Error, h5f.get_obj_ids, -1, h5f.OBJ_ALL)
 
+    def test_py(self):
+        self.assertEqual(self.fid.name, HDFNAME)
 
 
 
diff --git a/h5py/tests/test_h5g.py b/h5py/tests/test_h5g.py
index 62fd9d5..e280dcb 100644
--- a/h5py/tests/test_h5g.py
+++ b/h5py/tests/test_h5g.py
@@ -163,7 +163,10 @@ class TestH5G(unittest.TestCase):
         self.assert_(self.obj.py_exists(TEST_GROUPS[0]))
         self.assert_(not self.obj.py_exists('Something else'))
 
-
+    def test_py_iter(self):
+        
+        namelist = list(self.obj.py_iter())
+        self.assertEqual(namelist, TEST_GROUPS)
 
     
 
diff --git a/h5py/tests/test_h5s.py b/h5py/tests/test_h5s.py
index 4aebbd7..a9cb5b5 100644
--- a/h5py/tests/test_h5s.py
+++ b/h5py/tests/test_h5s.py
@@ -14,7 +14,7 @@ import unittest
 
 import h5py
 from h5py import h5s, h5i
-from h5py.h5e import H5Error
+from h5py.h5 import H5Error
 
 spaces = [(10,10), (1,1), (1,), ()]
 max_spaces = [(10,10), (3,4), (h5s.UNLIMITED,), ()]
@@ -25,174 +25,118 @@ class TestH5S(unittest.TestCase):
     def test_create_close(self):
         sid = h5s.create(h5s.SCALAR)
         self.assertEqual(h5i.get_type(sid), h5i.DATASPACE)
-        h5s.close(sid)
+        sid.close()
         self.assertEqual(h5i.get_type(sid), h5i.BADID)
 
         self.assertRaises(H5Error, h5s.create, -1)
-        self.assertRaises(H5Error, h5s.close, -1)
 
     def test_copy(self):
         sid = h5s.create(h5s.SCALAR)
-        sid2 = h5s.copy(sid)
+        sid2 = sid.copy()
         self.assertEqual(h5i.get_type(sid2), h5i.DATASPACE)
-        h5s.close(sid2)
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.copy, -1)
 
     def test_simple(self):
         # Tests create_simple, get_simple_extent_dims, get_simple_extent_ndims
 
         for space, max_space in zip(spaces, max_spaces):
             sid = h5s.create_simple(space,max_space)
-            self.assertEqual(h5s.get_simple_extent_dims(sid), space)
-            self.assertEqual(h5s.get_simple_extent_dims(sid, True), max_space)
-            self.assertEqual(h5s.get_simple_extent_ndims(sid), len(space))
-            h5s.close(sid)
+            self.assertEqual(sid.get_simple_extent_dims(), space)
+            self.assertEqual(sid.get_simple_extent_dims(maxdims=True), max_space)
+            self.assertEqual(sid.get_simple_extent_ndims(), len(space))
 
-        # Bad input
         self.assertRaises(ValueError, h5s.create_simple, None)
-        self.assertRaises(H5Error, h5s.get_simple_extent_dims, -1)
-        self.assertRaises(H5Error, h5s.get_simple_extent_ndims, -1)
-
-        # Illegal input
         self.assertRaises(H5Error, h5s.create_simple, (10,10), (10,9))
         self.assertRaises(ValueError, h5s.create_simple, (10,10), (10,))
 
     def test_is_simple(self):
         # According to HDF5 docs, all dataspaces are "simple," even scalar ones.
         sid = h5s.create(h5s.SCALAR)
-        self.assert_(h5s.is_simple(sid))
-        h5s.close(sid)
+        self.assert_(sid.is_simple())
         sid = h5s.create(h5s.SIMPLE)    
-        self.assert_(h5s.is_simple(sid))
-        h5s.close(sid)
-
-        # I think this should be H5Error but the library disagrees.
-        self.assertRaises(H5Error, h5s.is_simple, -1)
+        self.assert_(sid.is_simple())
 
     def test_offset_simple(self):
         
         sid = h5s.create_simple((100,100))
-        h5s.select_hyperslab(sid, (0,0), (10,10))
-        self.assertEqual(h5s.get_select_bounds(sid), ((0,0),(9,9)))
-        h5s.offset_simple(sid,(2,2))
-        self.assertEqual(h5s.get_select_bounds(sid), ((2,2),(11,11)))
-        h5s.offset_simple(sid, None)
-        self.assertEqual(h5s.get_select_bounds(sid), ((0,0),(9,9)))
-
-        self.assertRaises(H5Error, h5s.offset_simple, -1, (10,10))
-        self.assertRaises(ValueError, h5s.offset_simple, sid, (10,))
-
-        h5s.close(sid)
+        sid.select_hyperslab((0,0), (10,10))
+        self.assertEqual(sid.get_select_bounds(), ((0,0),(9,9)))
+        sid.offset_simple((2,2))
+        self.assertEqual(sid.get_select_bounds(), ((2,2),(11,11)))
+        sid.offset_simple(None)
+        self.assertEqual(sid.get_select_bounds(), ((0,0),(9,9)))
 
     def test_get_simple_extent_npoints(self):
         
         sid = h5s.create_simple((100,100))
-        self.assertEqual(h5s.get_simple_extent_npoints(sid), 100*100)
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.get_simple_extent_npoints, -1)
+        self.assertEqual(sid.get_simple_extent_npoints(), 100*100)
 
     def test_get_simple_extent_type(self):
 
         sid = h5s.create(h5s.SIMPLE)
         sid2 = h5s.create(h5s.SCALAR)
-        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.SIMPLE)
-        self.assertEqual(h5s.get_simple_extent_type(sid2), h5s.SCALAR)
-        h5s.close(sid)
-        h5s.close(sid2)
-
-        self.assertRaises(H5Error, h5s.get_simple_extent_type, -1)
+        self.assertEqual(sid.get_simple_extent_type(), h5s.SIMPLE)
+        self.assertEqual(sid2.get_simple_extent_type(), h5s.SCALAR)
 
     def test_extent_copy(self):
 
         sid = h5s.create(h5s.SIMPLE)
         sid2 = h5s.create_simple((35,42))
-        h5s.extent_copy(sid, sid2)
-        self.assertEqual(h5s.get_simple_extent_dims(sid2), (35,42))
-        h5s.close(sid)
-        h5s.close(sid2)
-
-        self.assertRaises(H5Error, h5s.extent_copy, -1, -1)
+        sid.extent_copy(sid2)
+        self.assertEqual(sid.get_simple_extent_dims(), (35,42))
 
     def test_set_extent_simple(self):
 
         for space, max_space in zip(spaces, max_spaces):
             sid = h5s.create_simple((10,10))
-            h5s.set_extent_simple(sid, space, max_space)
-            self.assertEqual(h5s.get_simple_extent_dims(sid), space)
-            self.assertEqual(h5s.get_simple_extent_dims(sid, True), max_space)
-            h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.set_extent_simple, -1, (10,10))
+            sid.set_extent_simple(space, max_space)
+            self.assertEqual(sid.get_simple_extent_dims(), space)
+            self.assertEqual(sid.get_simple_extent_dims(True), max_space)
 
     def test_set_extent_none(self):
 
         sid = h5s.create_simple((10,10))
-        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.SIMPLE)
-        h5s.set_extent_none(sid)
-        self.assertEqual(h5s.get_simple_extent_type(sid), h5s.NO_CLASS)
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.set_extent_none, -1)
-
+        sid.set_extent_none()
+        self.assertEqual(sid.get_simple_extent_type(), h5s.NO_CLASS)
 
     def test_get_select_type_npoints(self):
 
         sid = h5s.create_simple((10,10))
-        h5s.select_hyperslab(sid, (0,0), (5,5))
-        self.assertEqual(h5s.get_select_type(sid), h5s.SEL_HYPERSLABS)
-        self.assertEqual(h5s.get_select_npoints(sid), 25)
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.get_select_type, -1)
-        self.assertRaises(H5Error, h5s.get_select_npoints, -1)
+        sid.select_hyperslab((0,0), (5,5))
+        self.assertEqual(sid.get_select_type(), h5s.SEL_HYPERSLABS)
+        self.assertEqual(sid.get_select_npoints(), 25)
 
     def test_get_select_bounds(self):
 
         sid = h5s.create_simple((100,100))
-        h5s.select_all(sid)
-        self.assertEqual(h5s.get_select_bounds(sid), ((0,0), (99,99)))
-        h5s.select_hyperslab(sid, (10,10), (13,17))
-        self.assertEqual(h5s.get_select_bounds(sid), ((10,10), (22,26)))
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.get_select_bounds, -1)
+        sid.select_all()
+        self.assertEqual(sid.get_select_bounds(), ((0,0), (99,99)))
+        sid.select_hyperslab((10,10), (13,17))
+        self.assertEqual(sid.get_select_bounds(), ((10,10), (22,26)))
 
     def test_select(self):
+        # all, none, valid
 
         sid = h5s.create_simple((100,100))
-        h5s.select_none(sid)
-        self.assertEqual(h5s.get_select_npoints(sid), 0)
-        h5s.select_all(sid)
-        self.assertEqual(h5s.get_select_npoints(sid), 100*100)
-        h5s.select_none(sid)
-        self.assertEqual(h5s.get_select_npoints(sid), 0)
-
-        h5s.select_hyperslab(sid, (0,0), (10,10))
-        self.assert_(h5s.select_valid(sid))
-        h5s.select_hyperslab(sid, (0,0), (200,200))
-        self.assert_(not h5s.select_valid(sid))
-        
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.select_none, -1)
-        self.assertRaises(H5Error, h5s.select_all, -1)
-        self.assertRaises(H5Error, h5s.select_valid, -1)
+        sid.select_none()
+        self.assertEqual(sid.get_select_npoints(), 0)
+        sid.select_all()
+        self.assertEqual(sid.get_select_npoints(), 100*100)
+        sid.select_none()
+        self.assertEqual(sid.get_select_npoints(), 0)
+
+        sid.select_hyperslab((0,0), (10,10))
+        self.assert_(sid.select_valid())
+        sid.select_hyperslab((0,0), (200,200))
+        self.assert_(not sid.select_valid())
 
     def test_elements(self):
 
         pointlist= [(0,0), (15,98), (4,17), (67,32)] 
         sid = h5s.create_simple((100,100))
 
-        h5s.select_elements(sid, pointlist)
-        self.assertEqual(h5s.get_select_elem_npoints(sid), len(pointlist))
-        self.assertEqual(h5s.get_select_elem_pointlist(sid), pointlist)
-
-        self.assertRaises(H5Error, h5s.select_elements, -1, [])
-        self.assertRaises(H5Error, h5s.get_select_elem_npoints, -1)
-        self.assertRaises(H5Error, h5s.get_select_elem_pointlist, -1)
+        sid.select_elements(pointlist)
+        self.assertEqual(sid.get_select_elem_npoints(), len(pointlist))
+        self.assertEqual(sid.get_select_elem_pointlist(), pointlist)
 
     def test_get_blocks(self):
 
@@ -200,19 +144,18 @@ class TestH5S(unittest.TestCase):
         count = [ (5,5), (13,17) ]
 
         sid = h5s.create_simple((100,100))
-        h5s.select_hyperslab(sid, start[0], count[0], op=h5s.SELECT_SET)
-        h5s.select_hyperslab(sid, start[1], count[1], op=h5s.SELECT_OR)
+        sid.select_hyperslab(start[0], count[0], op=h5s.SELECT_SET)
+        sid.select_hyperslab(start[1], count[1], op=h5s.SELECT_OR)
 
-        self.assertEqual(h5s.get_select_hyper_nblocks(sid), 2)
-        blocklist = h5s.get_select_hyper_blocklist(sid)
+        self.assertEqual(sid.get_select_hyper_nblocks(), 2)
+        blocklist = sid.get_select_hyper_blocklist()
         self.assertEqual(blocklist, [( (0,0), (4,4) ), ( (50,60), (62,76) )])
 
-        h5s.close(sid)
-
-        self.assertRaises(H5Error, h5s.get_select_hyper_nblocks, -1)
-        self.assertRaises(H5Error, h5s.get_select_hyper_blocklist, -1)
-
-
+    def test_py(self):
+    
+        for space in spaces:
+            sid = h5s.create_simple(space)
+            self.assertEqual(sid.shape, sid.get_simple_extent_dims())
 
 
 
diff --git a/h5py/utils_hl.py b/h5py/utils_hl.py
new file mode 100644
index 0000000..3ae00b9
--- /dev/null
+++ b/h5py/utils_hl.py
@@ -0,0 +1,108 @@
+
+"""
+    Utility functions for high-level modules.
+"""
+
+def slicer(shape, args):
+    """ Parse a tuple containing Numpy-style extended slices.
+        Shape should be a Numpy-style shape tuple.
+
+        Arguments may contain:
+
+        1. Integer/long indices
+        2. Slice objects
+        3. Exactly one ellipsis object
+        4. Strings representing field names (zero or more, in any order)
+
+        Return is a 4-tuple containing sub-tuples:
+        (start, count, stride, names)
+
+        start:  tuple with starting indices
+        count:  how many elements to select along each axis
+        stride: selection pitch for each axis
+        names:  field names (i.e. for compound types)
+    """
+
+    rank = len(shape)
+
+    if not isinstance(args, tuple):
+        args = (args,)
+    args = list(args)
+
+    slices = []
+    names = []
+
+    # Sort arguments
+    for entry in args[:]:
+        if isinstance(entry, str):
+            names.append(entry)
+        else:
+            slices.append(entry)
+
+    start = []
+    count = []
+    stride = []
+
+    # Hack to allow Numpy-style row indexing
+    if len(slices) == 1 and slices[0] != Ellipsis:
+        args.append(Ellipsis)
+
+    # Expand integers and ellipsis arguments to slices
+    for dim, arg in enumerate(slices):
+
+        if isinstance(arg, int) or isinstance(arg, long):
+            if arg < 0:
+                raise ValueError("Negative indices are not allowed.")
+            start.append(arg)
+            count.append(1)
+            stride.append(1)
+
+        elif isinstance(arg, slice):
+
+            # slice.indices() method clips, so do it the hard way...
+
+            # Start
+            if arg.start is None:
+                ss=0
+            else:
+                if arg.start < 0:
+                    raise ValueError("Negative dimensions are not allowed")
+                ss=arg.start
+
+            # Stride
+            if arg.step is None:
+                st = 1
+            else:
+                if arg.step <= 0:
+                    raise ValueError("Only positive step sizes allowed")
+                st = arg.step
+
+            # Count
+            if arg.stop is None:
+                cc = shape[dim]/st
+            else:
+                if arg.stop < 0:
+                    raise ValueError("Negative dimensions are not allowed")
+                cc = (arg.stop-ss)/st
+            if cc == 0:
+                raise ValueError("Zero-length selections are not allowed")
+
+            start.append(ss)
+            stride.append(st)
+            count.append(cc)
+
+        elif arg == Ellipsis:
+            nslices = rank-(len(slices)-1)
+            if nslices <= 0:
+                continue
+            for x in range(nslices):
+                idx = dim+x
+                start.append(0)
+                count.append(shape[dim+x])
+                stride.append(1)
+
+        else:
+            raise ValueError("Bad slice type %s" % repr(arg))
+
+    return (tuple(start), tuple(count), tuple(stride), tuple(names))
+

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