Ran update-copyright.py.
[h5config.git] / h5config / storage / hdf5.py
index 34f4faea4f55423ab0ccdad97aa2b85632d99762..6b8a0bcf1fa16e378de5ce05d1bfaa6ca3d1c72d 100644 (file)
@@ -1,24 +1,24 @@
-# Copyright (C) 2011 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
 #
 # This file is part of h5config.
 #
-# h5config is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
+# h5config is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
 #
-# h5config is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
+# h5config is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 #
-# You should have received a copy of the GNU General Public License
-# along with h5config.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU General Public License along with
+# h5config.  If not, see <http://www.gnu.org/licenses/>.
 
 """HDF5 backend implementation
 """
 
-import types as _types
+import os.path as _os_path
+import sys as _sys
 
 import h5py as _h5py
 import numpy as _numpy
@@ -26,22 +26,30 @@ import numpy as _numpy
 from .. import LOG as _LOG
 from .. import config as _config
 from . import FileStorage as _FileStorage
+from . import is_string as _is_string
 
 
 def pprint_HDF5(*args, **kwargs):
-    print pformat_HDF5(*args, **kwargs)
+    print(pformat_HDF5(*args, **kwargs))
 
 def pformat_HDF5(filename, group='/'):
-    with _h5py.File(filename, 'r') as f:
-        cwg = f[group]
-        ret = '\n'.join(_pformat_hdf5(cwg))
+    try:
+        with _h5py.File(filename, 'r') as f:
+            cwg = f[group]
+            ret = '\n'.join(_pformat_hdf5(cwg))
+    except IOError as e:
+        if 'unable to open' in e.message:
+            if _os_path.getsize(filename) == 0:
+                return 'EMPTY'
+            return None
+        raise
     return ret
 
 def _pformat_hdf5(cwg, depth=0):
     lines = []
     lines.append('  '*depth + cwg.name)
     depth += 1
-    for key,value in cwg.iteritems():
+    for key,value in cwg.items():
         if isinstance(value, _h5py.Group):
             lines.extend(_pformat_hdf5(value, depth))
         elif isinstance(value, _h5py.Dataset):
@@ -196,7 +204,7 @@ class HDF5_Storage (_FileStorage):
                 else:
                     try:
                         v = group[s.name][...]
-                    except Exception, e:
+                    except Exception as e:
                         _LOG.error('Could not access {}/{}: {}'.format(
                                 group.name, s.name, e))
                         raise 
@@ -209,8 +217,15 @@ class HDF5_Storage (_FileStorage):
                                     v = list(v)
                                 except TypeError:
                                     v = []
-                            else:
-                                v = str(v) # array('abc', dtype='|S3') -> 'abc'
+                                if _sys.version_info >= (3,):
+                                    for i,v_ in enumerate(v):
+                                        if isinstance(v_, bytes):
+                                            v[i] = str(v_, 'utf-8')
+                            else:  # array('abc', dtype='|S3') -> 'abc'
+                                if _sys.version_info >= (3,):
+                                    v = str(v, 'utf-8')
+                                else:
+                                    v = str(v)
                         elif isinstance(s, _config.IntegerSetting):
                             v = int(v)  # array(3, dtpe='int32') -> 3
                         elif isinstance(s, _config.FloatSetting):
@@ -219,7 +234,7 @@ class HDF5_Storage (_FileStorage):
                             raise NotImplementedError(type(s))
                         elif isinstance(s, _config.ListSetting):
                             v = list(v)  # convert from numpy array
-                    if isinstance(v, _types.StringTypes):
+                    if _is_string(v):
                         # convert back from None, etc.
                         v = s.convert_from_text(v)
                     config[s.name] = v
@@ -261,11 +276,22 @@ class HDF5_Storage (_FileStorage):
                         continue
                 if value is None:  # not set yet, or invalid
                     value = s.convert_to_text(config[s.name])
+                if _sys.version_info >= (3,):  # convert strings to bytes/
+                    if isinstance(value, str):
+                        value = value.encode('utf-8')
+                    elif isinstance(value, list):
+                        value = list(value)  # shallow copy
+                        for i,v in enumerate(value):
+                            if isinstance(v, str):
+                                value[i] = v.encode('utf-8')
                 try:
                     del group[s.name]
                 except KeyError:
                     pass
-                group[s.name] = value
+                try:
+                    group[s.name] = value
+                except TypeError:
+                    raise ValueError((value, type(value)))
         finally:
             if f:
                 f.close()