1 # Copyright (C) 2011 W. Trevor King <wking@drexel.edu>
3 # This file is part of h5config.
5 # h5config is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
10 # h5config is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with h5config. If not, see <http://www.gnu.org/licenses/>.
18 """HDF5 backend implementation
23 from . import LOG as _LOG
24 from . import config as _config
27 def pprint_HDF5(*args, **kwargs):
28 print pformat_HDF5(*args, **kwargs)
30 def pformat_HDF5(filename, group='/'):
31 f = _h5py.File(filename, 'r')
33 return '\n'.join(_pformat_hdf5(cwg))
35 def _pformat_hdf5(cwg, depth=0):
37 lines.append(' '*depth + cwg.name)
39 for key,value in cwg.iteritems():
40 if isinstance(value, _h5py.Group):
41 lines.extend(_pformat_hdf5(value, depth))
42 elif isinstance(value, _h5py.Dataset):
43 lines.append(' '*depth + str(value))
44 lines.append(' '*(depth+1) + str(value[...]))
46 lines.append(' '*depth + str(value))
50 class _HDF5Config (_config.BackedConfig):
51 """Mixin to back a `_Config` class with an HDF5 file.
53 TODO: Special handling for Choice (enums), FloatList (arrays), etc.?
55 The `.save` and `.load` methods have an optional `group` argument
56 that allows you to save and load settings from an externally
57 opened HDF5 file. This can make it easier to stash several
58 related `_Config` classes in a single file. For example
62 >>> from .test import HDF5_TestConfig
63 >>> fd,filename = tempfile.mkstemp(suffix='.h5', prefix='pypiezo-')
66 >>> f = _h5py.File(filename, 'a')
67 >>> c = HDF5_TestConfig(filename='untouched_file.h5',
68 ... group='/untouched/group')
69 >>> c['syslog'] = True
70 >>> group = f.create_group('base')
72 >>> pprint_HDF5(filename)
75 <HDF5 dataset "age": shape (), type "|S3">
77 <HDF5 dataset "alive": shape (), type "|S2">
79 <HDF5 dataset "bids": shape (), type "|S11">
81 <HDF5 dataset "daisies": shape (), type "|S2">
83 <HDF5 dataset "species": shape (), type "|S14">
85 >>> d = HDF5_TestConfig(filename='untouched_file.h5',
86 ... group='/untouched/group')
92 >>> os.remove(filename)
94 def __init__(self, filename=None, group='/', **kwargs):
95 super(_HDF5Config, self).__init__(**kwargs)
96 self.filename = filename
97 assert group.startswith('/'), group
98 if not group.endswith('/'):
101 self._file_checked = False
103 def _check_file(self):
104 if self._file_checked:
107 self._file_checked = True
109 def _setup_file(self):
110 f = _h5py.File(self.filename, 'a')
111 cwg = f # current working group
113 # Create the group where the settings are stored (if necessary)
115 for group in self.group.strip('/').split('/'):
119 if group not in cwg.keys():
120 _LOG.debug('creating group %s in %s'
121 % ('/'.join(gpath), self.filename))
122 cwg.create_group(group)
126 def dump(self, help=False, from_file=False):
127 """Return the relevant group in `self.filename` as a string
129 Extends the base :meth:`dump` by adding the `from_file`
130 option. If `from_file` is true, dump all entries that
131 currently exist in the relevant group, rather than listing all
132 settings defined in the instance dictionary.
136 f = _h5py.File(self.filename, 'r')
139 settings = dict([(s.name, s) for s in self.settings])
140 for key,value in cwg.iteritems():
141 if help and key in settings:
142 help_string = '\t(%s)' % settings[key].help()
145 lines.append('%s: %s%s' % (key, value[...], help_string))
146 return '\n'.join(lines)
147 return super(_HDF5Config, self).dump(help=help)
149 def load(self, group=None):
152 f = _h5py.File(self.filename, 'r')
153 group = f[self.group]
156 for s in self.settings:
157 if s.name not in group.keys():
159 self[s.name] = s.convert_from_text(group[s.name][...])
163 def save(self, group=None):
166 f = _h5py.File(self.filename, 'a')
167 group = f[self.group]
170 for s in self.settings:
171 value = s.convert_to_text(self[s.name])
176 group[s.name] = value