Repository: jjhelmus/pyfive

Issue:
Access values with path
One thing that is not yet possible and that would help a lot. For example, with version 0.2.0:
Using Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2

> > > import h5py
> > > import pyfive
> > > 
> > > f5 = h5py.File('tests/latest.hdf5')
> > > f5["group1/subgroup1/dataset3"].value
> > > array([ 0.,  1.,  2.,  3.], dtype=float32)
> > > ffive = pyfive.File('tests/latest.hdf5')
> > > ffive["group1/subgroup1/dataset3"].value
> > > Traceback (most recent call last):
> > >   File "<stdin>", line 1, in <module>
> > >   File "pyfive/high_level.py", line 48, in **getitem**
> > >     raise KeyError('%s not found in group' % (y))
> > > KeyError: 'group1/subgroup1/dataset3 not found in group'


Discussion:

Patch:
diff --git a/pyfive/high_level.py b/pyfive/high_level.py
index 11c90ff..973f49d 100644
--- a/pyfive/high_level.py
+++ b/pyfive/high_level.py
@@ -3,6 +3,7 @@
 from collections import Mapping, deque, Sequence
 import os
 from io import open     # Python 2.7 requires for a Buffered Reader
+import posixpath
 
 import numpy as np
 
@@ -49,33 +50,45 @@ class Group(Mapping):
         """ Number of links in the group. """
         return len(self._links)
 
+    def _dereference(self, ref):
+        """ Deference a Reference object. """
+        if not ref:
+            raise ValueError('cannot deference null reference')
+        obj = self.file._get_object_by_address(ref.address_of_reference)
+        if obj is None:
+            dataobjects = DataObjects(self.file._fh, ref.address_of_reference)
+            if dataobjects.is_dataset:
+                return Dataset(None, dataobjects, None, alt_file=self.file)
+            return Group(None, dataobjects, None, alt_file=self.file)
+        return obj
+
     def __getitem__(self, y):
         """ x.__getitem__(y) <==> x[y] """
         if isinstance(y, Reference):
-            if not y:
-                raise ValueError('cannot deference null reference')
-            obj = self.file._get_object_by_address(y.address_of_reference)
-            if obj is None:
-                dataobjs = DataObjects(self.file._fh, y.address_of_reference)
-                if dataobjs.is_dataset:
-                    return Dataset(None, dataobjs, None, alt_file=self.file)
-                return Group(None, dataobjs, None, alt_file=self.file)
-            return obj
-
-        y = y.strip('/')
-
-        if y not in self._links:
-            raise KeyError('%s not found in group' % (y))
-
-        if self.name == '/':
-            sep = ''
+            return self._dereference(y)
+
+        path = posixpath.normpath(y)
+        if path == '.':
+            return self
+        if path.startswith('/'):
+            return self.file[path[1:]]
+
+        if posixpath.dirname(path) != '':
+            next_obj, additional_obj = path.split('/', 1)
         else:
-            sep = '/'
+            next_obj = path
+            additional_obj = '.'
+
+        if next_obj not in self._links:
+            raise KeyError('%s not found in group' % (next_obj))
 
-        dataobjs = DataObjects(self.file._fh, self._links[y])
+        obj_name = posixpath.join(self.name, next_obj)
+        dataobjs = DataObjects(self.file._fh, self._links[next_obj])
         if dataobjs.is_dataset:
-            return Dataset(self.name + sep + y, dataobjs, self)
-        return Group(self.name + sep + y, dataobjs, self)
+            if additional_obj != '.':
+                raise KeyError('%s is a dataset, not a group' % (obj_name))
+            return Dataset(obj_name, dataobjs, self)
+        return Group(obj_name, dataobjs, self)[additional_obj]
 
     def __iter__(self):
         for k in self._links.keys():


Test patch:
diff --git a/tests/test_high_level.py b/tests/test_high_level.py
index 593ad24..9e14af3 100644
--- a/tests/test_high_level.py
+++ b/tests/test_high_level.py
@@ -138,3 +138,20 @@ def test_dataset_class():
 
         assert dset1.parent.name == '/'
         assert dset2.parent.name == '/group1'
+
+
+def test_get_objects_by_path():
+    # gh-15
+
+    with pyfive.File(EARLIEST_HDF5_FILE) as hfile:
+        grp = hfile['/group1']
+
+        assert hfile['/group1/subgroup1'].name == '/group1/subgroup1'
+        assert grp['/group1/subgroup1'].name == '/group1/subgroup1'
+
+        dset2 = hfile['group1/dataset2/']
+        assert dset2.name == '/group1/dataset2'
+
+        assert_raises(KeyError, hfile.__getitem__, 'group1/fake')
+        assert_raises(KeyError, hfile.__getitem__, 'group1/subgroup1/fake')
+        assert_raises(KeyError, hfile.__getitem__, 'group1/dataset2/fake')