Convert to use new h5config package.
authorW. Trevor King <wking@drexel.edu>
Thu, 28 Jul 2011 17:30:53 +0000 (13:30 -0400)
committerW. Trevor King <wking@drexel.edu>
Thu, 28 Jul 2011 17:40:05 +0000 (13:40 -0400)
README
pypiezo/__init__.py
pypiezo/afm.py
pypiezo/base.py
pypiezo/config.py
pypiezo/surface.py

diff --git a/README b/README
index eedd8c5db6d88e27905ad55c833274c605e2970c..acf6f19669df16f1275ef837c8af7f42c7a66c64 100644 (file)
--- a/README
+++ b/README
@@ -33,17 +33,19 @@ Dependencies
 If you're installing by hand or packaging pypiezo for another
 distribution, you'll need the following dependencies:
 
-===========  =================  =====================
-Package      Debian_            Gentoo_
-===========  =================  =====================
-Numpy_       python-numpy       dev-python/numpy
-Scipy_       python-scipy       sci-libs/scipy
-H5Py_        python-h5py        dev-python/h5py
-Matplotlib_  python-matplotlib  dev-python/matplotlib
-Nose_        python-nose        dev-python/nose
-Pycomedi_                       dev-python/pycomedi
-PyYAML_      python-pyyaml      dev-python/pyyaml
-===========  =================  =====================
+==========================  =================  =============================================
+Package                     Debian_            Gentoo_
+==========================  =================  =============================================
+Numpy_                      python-numpy       dev-python/numpy
+Scipy_                      python-scipy       sci-libs/scipy
+Matplotlib_                 python-matplotlib  dev-python/matplotlib
+H5config_                                      dev-python/h5config [#wtk]_
+Curses-check-for-keypress_                     dev-python/curses-check-for-keypress [#wtk]_
+Nose_                       python-nose        dev-python/nose
+Pycomedi_                                      dev-python/pycomedi [#wtk]_
+==========================  =================  =============================================
+
+.. [#wtk] In the `wtk overlay`_.
 
 
 Installing by hand
@@ -95,12 +97,15 @@ Copyright 2007-2011
 .. _Gentoo: http://www.gentoo.org/
 .. _NumPy: http://numpy.scipy.org/
 .. _SciPy: http://www.scipy.org/
-.. _H5Py: http://code.google.com/p/h5py/
 .. _Matplotlib: http://matplotlib.sourceforge.net/
+.. _H5config:
+    http://physics.drexel.edu/~wking/unfolding-disasters/posts/h5config/
+.. _Curses-ckeck-for-keypress:
+    http://physics.drexel.edu/~wking/unfolding-disasters/posts/curses-check-for-keypress/
 .. _Nose: http://somethingaboutorange.com/mrl/projects/nose/
-.. _Pycomedi: http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/pycomedi/
-.. _PyYAML: http://pyyaml.org/wiki/PyYAML
+.. _Pycomedi:
+    http://physics.drexel.edu/~wking/unfolding-disasters/posts/pycomedi/
 .. _Git: http://git-scm.com/
 .. _homepage:
-     http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/pypiezo/
+    http://www.physics.drexel.edu/~wking/unfolding-disasters/posts/pypiezo/
 .. _GNU General Public License Version 3: http://www.gnu.org/licenses/gpl.txt
index 30fe5020e741204077a606cb89b7b673bce75fbe..e1f8221c6acc79103acfecec3bf8ba35309a733c 100644 (file)
 import logging as _logging
 import logging.handlers as _logging_handlers
 
+from .config import PackageConfig as _PackageConfig
 
-__version__ = '0.4'
 
+__version__ = '0.5'
 
-LOG = _logging.getLogger('pypiezo')
-"Pypiezo logger"
-
-LOG.setLevel(_logging.WARN)
-_formatter = _logging.Formatter(
-    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-
-_stream_handler = _logging.StreamHandler()
-_stream_handler.setLevel(_logging.DEBUG)
-_stream_handler.setFormatter(_formatter)
-LOG.addHandler(_stream_handler)
-
-_syslog_handler = None
-
-
-from .config import _BaseConfig
-from .config import find_base_config as _find_base_config
-
-
-def setup_base_config(config):
-    global base_config, _syslog_handler
-    base_config = config
-
-    LOG.setLevel(base_config['log-level']) 
-
-    if base_config['syslog']:
-        if not _syslog_handler:
-            _syslog_handler = _logging_handlers.SysLogHandler()
-            _syslog_handler.setLevel(_logging.DEBUG)
-        LOG.handlers = [_syslog_handler]
-    else:
-        LOG.handlers = [_stream_handler]
-
-    LOG.info('setup base_config:\n%s' % base_config.dump())
-
-def clear_base_config():
-    setup_base_config(_BaseConfig())
-
-base_config = _find_base_config()
-setup_base_config(base_config)
+package_config = _PackageConfig(package_name=__name__)
+package_config.load_system()
index 49adb25fa4e34b7ba093d83f669db9eedf4efe1e..5a9a6e6736589581eee7e9ca1c29dc0c518c558d 100644 (file)
@@ -30,8 +30,8 @@ except (ImportError, RuntimeError), e:
 from curses_check_for_keypress import CheckForKeypress as _CheckForKeypress
 
 from . import LOG as _LOG
-from . import base_config as _base_config
 from . import base as _base
+from . import package_config as _package_config
 from . import surface as _surface
 
 
@@ -175,7 +175,7 @@ class AFMPiezo (_base.Piezo):
             number of 'null' steps to take before moving (confirming a
             stable input deflection).
         """
-        if return_data or _base_config['matplotlib']:
+        if return_data or _package_config['matplotlib']:
             aquire_data = True
         else:
             aquire_data = False
@@ -230,7 +230,7 @@ class AFMPiezo (_base.Piezo):
         log_string = 'current position %d and deflection %g' % (
             self.last_output[axis_name], current_deflection)
         _LOG.debug(log_string)
-        if _base_config['matplotlib']:
+        if _package_config['matplotlib']:
             if not _matplotlib:
                 raise _matplotlib_import_error
             figure = _matplotlib_pyplot.figure()
@@ -270,7 +270,7 @@ class AFMPiezo (_base.Piezo):
         Modern commercial AFMs with computer-aligned lasers must do
         something like this automatically.
         """
-        if _base_config['matplotlib']:
+        if _package_config['matplotlib']:
             plot = True
         if laser_wavelength and amplitude:
             log_string = \
index b80d727704e73cfc5e0df3f4ec788a21c69b89e8..b648a9d79202f5855cf6462cd0da3ed0ec7c0ccb 100644 (file)
@@ -35,8 +35,8 @@ from pycomedi.constant import TRIG_SRC, SDF
 from pycomedi.utility import inttrig_insn, Reader, Writer
 
 from . import LOG as _LOG
-from . import base_config as _base_config
 from . import config as _config
+from . import package_config as _package_config
 
 
 def convert_bits_to_volts(config, data):
@@ -443,7 +443,7 @@ class Piezo (object):
 
     >>> d.close()
     """
-    def __init__(self, axes, input_channels, base_config=None):
+    def __init__(self, axes, input_channels):
         self.axes = axes
         self.input_channels = input_channels
         self.last_output = {}
@@ -635,7 +635,7 @@ class Piezo (object):
         for i,name in enumerate(output_names):
             self.last_output[name] = data[-1,i]
 
-        if _base_config['matplotlib']:
+        if _package_config['matplotlib']:
             if not _matplotlib:
                 raise _matplotlib_import_error
             figure = _matplotlib_pyplot.figure()
index 6df2460dbda02c57bd57c09eb066ab058e2c6838..791c2e8d256dfced2c32b04afe446f72dc44cea1 100644 (file)
-"""Piezo configuration
+# Copyright (C) 2011 W. Trevor King <wking@drexel.edu>
+#
+# This file is part of pypiezo.
+#
+# pypiezo 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.
+#
+# pypiezo 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 pypiezo.  If not, see <http://www.gnu.org/licenses/>.
+
+"Piezo configuration"
 
-Broken out from the main modules to make it easy to override if you
-wish to use a different configuration file format.
-
-The HDF5- and YAML-backed config file classes are created dynamically:
-
->>> print '\\n'.join([obj for obj in sorted(locals().keys())
-...                   if obj.endswith('Config')
-...                   and not obj.startswith('_')])
-HDF5_AxisConfig
-HDF5_BaseConfig
-HDF5_ChannelConfig
-HDF5_InputChannelConfig
-HDF5_OutputChannelConfig
-YAML_AxisConfig
-YAML_BaseConfig
-YAML_ChannelConfig
-YAML_InputChannelConfig
-YAML_OutputChannelConfig
-
-The first time you use them, the file they create will probably be
-empty or not exist.
-
->>> import os
->>> import tempfile
->>> fd,filename = tempfile.mkstemp(suffix='.h5', prefix='pypiezo-')
->>> os.close(fd)
-
->>> c = HDF5_BaseConfig(filename=filename, group='/base')
->>> c.load()
-
-Loading will create a stub group group if it hadn't existed before.
-
->>> pprint_HDF5(filename)
-/
-  /base
->>> print c.dump(from_file=True)
-<BLANKLINE>
-
-Saving fills in all the config values.
-
->>> c['syslog'] = True
->>> c.save()
->>> pprint_HDF5(filename)  # doctest: +REPORT_UDIFF
-/
-  /base
-    <HDF5 dataset "log-level": shape (), type "|S4">
-      warn
-    <HDF5 dataset "matplotlib": shape (), type "|S2">
-      no
-    <HDF5 dataset "syslog": shape (), type "|S3">
-      yes
->>> print c.dump(from_file=True)
-log-level: warn
-matplotlib: no
-syslog: yes
-
-If you want more details, you can dump with help strings.
-
->>> print c.dump(help=True, from_file=True)  # doctest: +NORMALIZE_WHITESPACE
-log-level: warn\t(Module logging level.  Default: warn.  Choices:
-               \t critical, error, warn, info, debug)
-matplotlib: no\t(Plot piezo motion using `matplotlib`.  Default: no.
-              \t Choices: yes, no)
-syslog: yes\t(Log to syslog (otherwise log to stderr).  Default: no.
-           \t Choices: yes, no)
-
-Settings also support `None`, even if they have numeric types.
-
->>> c = HDF5_AxisConfig(filename=filename, group='/z-axis')
->>> c.load()
->>> c.save()
->>> c.load()
->>> print c.dump(from_file=True)
-gain: 1.0
-maximum: None
-minimum: None
-sensitivity: 1.0
->>> print (c['minimum'] == None)
-True
-
-Cleanup our temporary config file.
-
->>> os.remove(filename)
-"""
-
-import logging as _logging
-import os.path as _os_path
 import sys as _sys
 
-import h5py as _h5py
-import yaml as _yaml
-
-from . import LOG as _LOG
-
-
-class _Setting (object):
-    "A named setting with arbitrart text values."
-    def __init__(self, name, help='', default=None):
-        self.name = name
-        self._help = help
-        self.default = default
-
-    def __str__(self):
-        return '<%s %s>' % (self.__class__.__name__, self.name)
-
-    def __repr__(self):
-        return self.__str__()
-
-    def help(self):
-        ret = '%s  Default: %s.' % (
-            self._help, self.convert_to_text(self.default))
-        return ret.strip()
-
-    def convert_from_text(self, value):
-        return value
-
-    def convert_to_text(self, value):
-        return value
-
-
-class _ChoiceSetting (_Setting):
-    """A named setting with a limited number of possible values.
-
-    `choices` should be a list of `(config_file_value, Python value)`
-    pairs.  For example
-
-    >>> s = _ChoiceSetting(name='bool',
-    ...                    choices=[('yes', True), ('no', False)])
-    >>> s.convert_from_text('yes')
-    True
-    >>> s.convert_to_text(True)
-    'yes'
-    >>> s.convert_to_text('invalid')
-    Traceback (most recent call last):
-      ...
-    ValueError: invalid
-    >>> s.help()
-    'Default: yes.  Choices: yes, no'
-    """
-    def __init__(self, choices=None, **kwargs):
-        if 'default' not in kwargs:
-            if None not in [keyval[1] for keyval in choices]:
-                kwargs['default'] = choices[0][1]
-        super(_ChoiceSetting, self).__init__(**kwargs)
-        if choices == None:
-            choices = []
-        self.choices = choices
-
-    def help(self):
-        ret = '%s  Choices: %s' % (
-            super(_ChoiceSetting, self).help(),
-            ', '.join([key for key,value in self.choices]))
-        return ret.strip()
-
-    def convert_from_text(self, value):
-        return dict(self.choices)[value]
-
-    def convert_to_text(self, value):
-        for keyval in self.choices:
-            key,val = keyval
-            if val == value:
-                return key
-        raise ValueError(value)
-
-
-class _BooleanSetting (_ChoiceSetting):
-    """A named settubg that can be either true or false.
-
-    >>> s = _BooleanSetting(name='bool')
-
-    >>> s.convert_from_text('yes')
-    True
-    >>> s.convert_to_text(True)
-    'yes'
-    >>> s.convert_to_text('invalid')
-    Traceback (most recent call last):
-      ...
-    ValueError: invalid
-    >>> s.help()
-    'Default: no.  Choices: yes, no'
-    """
-    def __init__(self, **kwargs):
-        assert 'choices' not in kwargs
-        if 'default' not in kwargs:
-            kwargs['default'] = False
-        super(_BooleanSetting, self).__init__(
-            choices=[('yes', True), ('no', False)], **kwargs)
-
-
-class _NumericSetting (_Setting):
-    """A named setting with numeric values.
-
-    >>> s = _NumericSetting(name='float')
-    >>> s.default
-    0
-    >>> s.convert_to_text(13)
-    '13'
-    """
-    _default_value = 0
-
-    def __init__(self, **kwargs):
-        if 'default' not in kwargs:
-            kwargs['default'] = self._default_value
-        super(_NumericSetting, self).__init__(**kwargs)
-
-    def convert_to_text(self, value):
-        return str(value)
-
-    def convert_from_text(self, value):
-        if value in [None, 'None']:
-            return None
-        return self._convert_from_text(value)
-
-    def _convert_from_text(self, value):
-        raise NotImplementedError()
-
-
-class _IntegerSetting (_NumericSetting):
-    """A named setting with integer values.
-
-    >>> s = _IntegerSetting(name='int')
-    >>> s.default
-    1
-    >>> s.convert_from_text('8')
-    8
-    """
-    _default_value = 1
-
-    def _convert_from_text(self, value):
-        return int(value)
-
-
-class _FloatSetting (_NumericSetting):
-    """A named setting with floating point values.
-
-    >>> s = _FloatSetting(name='float')
-    >>> s.default
-    1.0
-    >>> s.convert_from_text('8')
-    8.0
-    >>> s.convert_from_text('invalid')
-    Traceback (most recent call last):
-      ...
-    ValueError: invalid literal for float(): invalid
-    """
-    _default_value = 1.0
-
-    def _convert_from_text(self, value):
-        return float(value)
-
-
-class _FloatListSetting (_Setting):
-    """A named setting with a list of floating point values.
+import h5config.config as _config
+import h5config.tools as _h5config_tools
+import h5config.util as _util
 
-    >>> s = _FloatListSetting(name='floatlist')
-    >>> s.default
-    []
-    >>> s.convert_to_text([1, 2.3])
-    '1, 2.3'
-    >>> s.convert_from_text('4.5, -6.7')  # doctest: +ELLIPSIS
-    [4.5, -6.700...]
-    >>> s.convert_to_text([])
-    ''
-    >>> s.convert_from_text('')
-    []
-    """
-    def __init__(self, **kwargs):
-        if 'default' not in kwargs:
-            kwargs['default'] = []
-        super(_FloatListSetting, self).__init__(**kwargs)
 
-    def _convert_from_text(self, value):
-        if value is None:
-            return value
-        return float(value)
-
-    def convert_from_text(self, value):
-        if value is None:
-            return None
-        elif value == '':
-            return []
-        return [self._convert_from_text(x) for x in value.split(',')]
-
-    def convert_to_text(self, value):
-        if value is None:
-            return None
-        return ', '.join([str(x) for x in value])
-
-
-class _Config (dict):
-    "A class with a list `._keys` of `_Setting`\s."
-    settings = []
-
-    def __init__(self):
-        for s in self.settings:
-            self[s.name] = s.default
-
-    def dump(self, help=False):
-        """Return all settings and their values as a string
-
-        >>> b = _BaseConfig()
-        >>> print b.dump()
-        syslog: no
-        matplotlib: no
-        log-level: warn
-        >>> print b.dump(help=True)  # doctest: +NORMALIZE_WHITESPACE
-        syslog: no          (Log to syslog (otherwise log to stderr).
-                             Default: no.  Choices: yes, no)
-        matplotlib: no      (Plot piezo motion using `matplotlib`.
-                             Default: no.  Choices: yes, no)
-        log-level: warn     (Module logging level.  Default: warn.
-                             Choices: critical, error, warn, info, debug)
-        """
-        lines = []
-        settings = dict([(s.name, s) for s in self.settings])
-        for key,value in self.iteritems():
-            if key in settings:
-                setting = settings[key]
-                value_string = setting.convert_to_text(value)
-                if help:
-                    help_string = '\t(%s)' % setting.help()
-                else:
-                    help_string = ''
-                lines.append('%s: %s%s' % (key, value_string, help_string))
-        return '\n'.join(lines)
-
-
-class _BackedConfig (_Config):
-    "A `_Config` instance with some kind of storage interface"
-    def load(self):
-        raise NotImplementedError()
-
-    def save(self):
-        raise NotImplementedError()
-
-
-class _BaseConfig (_Config):
-    """Configure `pypiezo` module operation
-
-    >>> b = _BaseConfig()
-    >>> b.settings  # doctest: +NORMALIZE_WHITESPACE
-    [<_ChoiceSetting log-level>, <_BooleanSetting syslog>,
-     <_BooleanSetting matplotlib>]
-    >>> print b['log-level'] == _logging.WARN
-    True
-    """
-    settings = [
-        _ChoiceSetting(
-            name='log-level',
-            help='Module logging level.',
-            default=_logging.WARN,
-            choices=[
-                ('critical', _logging.CRITICAL),
-                ('error', _logging.ERROR),
-                ('warn', _logging.WARN),
-                ('info', _logging.INFO),
-                ('debug', _logging.DEBUG),
-                ]),
-        _BooleanSetting(
-            name='syslog',
-            help='Log to syslog (otherwise log to stderr).',
-            default=False),
-        _BooleanSetting(
+class PackageConfig (_h5config_tools.PackageConfig):
+    "Configure `pypiezo` module operation"
+    settings = _h5config_tools.PackageConfig.settings + [
+        _config.BooleanSetting(
             name='matplotlib',
             help='Plot piezo motion using `matplotlib`.',
             default=False),
         ]
 
 
-class _AxisConfig (_Config):
+class AxisConfig (_config.Config):
     "Configure a single piezo axis"
     settings = [
-        _FloatSetting(
+        _config.FloatSetting(
             name='gain',
             help=(
                 'Volts applied at piezo per volt output from the DAQ card '
                 '(e.g. if your DAQ output is amplified before driving the '
                 'piezo),')),
-        _FloatSetting(
+        _config.FloatSetting(
             name='sensitivity',
             help='Meters of piezo deflection per volt applied to the piezo.'),
-        _FloatSetting(
+        _config.FloatSetting(
             name='minimum',
             help='Set a lower limit on allowed output voltage',
             default=None),
-        _FloatSetting(
+        _config.FloatSetting(
             name='maximum',
             help='Set an upper limit on allowed output voltage',
             default=None),
         ]
 
 
-class _ChannelConfig (_Config):
+class ChannelConfig (_config.Config):
     settings = [
-        _Setting(
+        _config.Setting(
             name='device',
             help='Comedi device.',
             default='/dev/comedi0'),
-        _IntegerSetting(
+        _config.IntegerSetting(
             name='subdevice',
             help='Comedi subdevice index.  -1 for automatic detection.',
             default=-1),
-        _IntegerSetting(
+        _config.IntegerSetting(
             name='channel',
             help='Subdevice channel index.',
             default=0),
-        _IntegerSetting(
+        _config.IntegerSetting(
             name='maxdata',
             help="Channel's maximum bit value."),
-        _IntegerSetting(
+        _config.IntegerSetting(
             name='range',
             help="Channel's selected range index."),
-        _FloatListSetting(
+        _config.FloatListSetting(
             name='conversion-coefficients',
             help=('Bit to physical unit conversion coefficients starting with '
                   'the constant coefficient.')),
-        _FloatSetting(
+        _config.FloatSetting(
             name='conversion-origin',
             help=('Origin (bit offset) of bit to physical polynomial '
                   'expansion.')),
-        _FloatListSetting(
+        _config.FloatListSetting(
             name='inverse-conversion-coefficients',
             help=('Physical unit to bit conversion coefficients starting with '
                   'the constant coefficient.')),
-        _FloatSetting(
+        _config.FloatSetting(
             name='inverse-conversion-origin',
             help=('Origin (physical unit offset) of physical to bit '
                   'polynomial expansion.')),
         ]
 
 
-class _OutputChannelConfig (_ChannelConfig):
+class OutputChannelConfig (ChannelConfig):
     pass
 
 
-class _InputChannelConfig (_ChannelConfig):
+class InputChannelConfig (ChannelConfig):
     pass
 
 
-def pprint_HDF5(*args, **kwargs):
-    print pformat_HDF5(*args, **kwargs)
-
-def pformat_HDF5(filename, group='/'):
-    f = _h5py.File(filename, 'r')
-    cwg = f[group]
-    return '\n'.join(_pformat_hdf5(cwg))
-
-def _pformat_hdf5(cwg, depth=0):
-    lines = []
-    lines.append('  '*depth + cwg.name)
-    depth += 1 
-    for key,value in cwg.iteritems():
-        if isinstance(value, _h5py.Group):
-            lines.extend(_pformat_hdf5(value, depth))
-        elif isinstance(value, _h5py.Dataset):
-            lines.append('  '*depth + str(value))
-            lines.append('  '*(depth+1) + str(value[...]))
-        else:
-            lines.append('  '*depth + str(value))
-    return lines
-                         
-def h5_create_group(cwg, path):
-    "Create the group where the settings are stored (if necessary)."
-    if path == '/':
-        return cwg
-    gpath = ['']
-    for group in path.strip('/').split('/'):
-        gpath.append(group)
-        if group not in cwg.keys():
-            _LOG.debug('creating group %s in %s'
-                       % ('/'.join(gpath), cwg.file))
-            cwg.create_group(group)
-        cwg = cwg[group]
-    return cwg
-
-class _HDF5Config (_BackedConfig):
-    """Mixin to back a `_Config` class with an HDF5 file.
-
-    TODO: Special handling for Choice (enums), FloatList (arrays), etc.?
-
-    The `.save` and `.load` methods have an optional `group` argument
-    that allows you to save and load settings from an externally
-    opened HDF5 file.  This can make it easier to stash several
-    related `_Config` classes in a single file.  For example
-
-    >>> import os
-    >>> import tempfile
-    >>> fd,filename = tempfile.mkstemp(suffix='.h5', prefix='pypiezo-')
-    >>> os.close(fd)
-
-    >>> f = _h5py.File(filename, 'a')
-    >>> c = HDF5_BaseConfig(filename='untouched_file.h5',
-    ...                     group='/untouched/group')
-    >>> c['syslog'] = True
-    >>> group = f.create_group('base')
-    >>> c.save(group)
-    >>> pprint_HDF5(filename)
-    /
-      /base
-        <HDF5 dataset "log-level": shape (), type "|S4">
-          warn
-        <HDF5 dataset "matplotlib": shape (), type "|S2">
-          no
-        <HDF5 dataset "syslog": shape (), type "|S3">
-          yes
-    >>> d = HDF5_BaseConfig(filename='untouched_file.h5',
-    ...                     group='/untouched/group')
-    >>> d.load(group)
-    >>> d['syslog']
-    True
-
-    >>> f.close()
-    >>> os.remove(filename)
-    """
-    def __init__(self, filename, group='/', **kwargs):
-        super(_HDF5Config, self).__init__(**kwargs)
-        self.filename = filename
-        assert group.startswith('/'), group
-        if not group.endswith('/'):
-            group += '/'
-        self.group = group
-        self._file_checked = False
-
-    def _check_file(self):
-        if self._file_checked:
-            return
-        self._setup_file()
-        self._file_checked = True
-
-    def _setup_file(self):
-        f = _h5py.File(self.filename, 'a')
-        cwg = f  # current working group
-        h5_create_group(cwg, self.group)
-        f.close()
-
-    def dump(self, help=False, from_file=False):
-        """Return the relevant group in `self.filename` as a string
-
-        Extends the base :meth:`dump` by adding the `from_file`
-        option.  If `from_file` is true, dump all entries that
-        currently exist in the relevant group, rather than listing all
-        settings defined in the instance dictionary.
-        """
-        if from_file:
-            self._check_file()
-            f = _h5py.File(self.filename, 'r')
-            cwg = f[self.group]
-            lines = []
-            settings = dict([(s.name, s) for s in self.settings])
-            for key,value in cwg.iteritems():
-                if help and key in settings:
-                    help_string = '\t(%s)' % settings[key].help()
-                else:
-                    help_string = ''
-                lines.append('%s: %s%s' % (key, value[...], help_string))
-            return '\n'.join(lines)
-        return super(_HDF5Config, self).dump(help=help)
-
-    def load(self, group=None):
-        if group is None:
-            self._check_file()
-            f = _h5py.File(self.filename, 'r')
-            group = f[self.group]
-        else:
-            f = None
-        for s in self.settings:
-            if s.name not in group.keys():
-                continue
-            self[s.name] = s.convert_from_text(group[s.name][...])
-        if f:
-            f.close()
-
-    def save(self, group=None):
-        if group is None:
-            self._check_file()
-            f = _h5py.File(self.filename, 'a')
-            group = f[self.group]
-        else:
-            f = None
-        for s in self.settings:
-            value = s.convert_to_text(self[s.name])
-            try:
-                del group[s.name]
-            except KeyError:
-                pass
-            group[s.name] = value
-        if f:
-            f.close()
-
-
-class _YAMLDumper (_yaml.SafeDumper):
-    def represent_bool(self, data):
-        "Use yes/no instead of the default true/false"
-        if data:
-            value = u'yes'
-        else:
-            value = u'no'
-        return self.represent_scalar(u'tag:yaml.org,2002:bool', value)
-
-
-_YAMLDumper.add_representer(bool, _YAMLDumper.represent_bool)
-
-
-class _YAMLConfig (_BackedConfig):
-    """Mixin to back a `_Config` class with a YAML file.
-
-    TODO: Special handling for Choice (enums), FloatList (arrays), etc.?
-
-    >>> import os
-    >>> import os.path
-    >>> import tempfile
-    >>> fd,filename = tempfile.mkstemp(suffix='.yaml', prefix='pypiezo-')
-    >>> os.close(fd)
-
-    >>> c = YAML_BaseConfig(filename=filename)
-    >>> c.load()
-
-    Saving writes all the config values to disk.
-
-    >>> c['syslog'] = True
-    >>> c.save()
-    >>> print open(c.filename, 'r').read()
-    log-level: warn
-    matplotlib: no
-    syslog: yes
-    <BLANKLINE>
-
-    Loading reads the config files from disk.
-
-    >>> c = YAML_BaseConfig(filename=filename)
-    >>> c.load()
-    >>> print c.dump()
-    syslog: yes
-    matplotlib: no
-    log-level: warn
-
-    Cleanup our temporary config file.
-
-    >>> os.remove(filename)
-    """
-    dumper = _YAMLDumper
-
-    def __init__(self, filename, **kwargs):
-        super(_YAMLConfig, self).__init__(**kwargs)
-        self.filename = filename
-
-    def load(self):
-        if not _os_path.exists(self.filename):
-            open(self.filename, 'a').close()
-        with open(self.filename, 'r') as f:
-            data = _yaml.safe_load(f)
-        if data == None:
-            return  # empty file
-        settings = dict([(s.name, s) for s in self.settings])
-        for key,value in data.iteritems():
-            setting = settings[key]
-            if isinstance(setting, _BooleanSetting):
-                v = value
-            else:
-                v = setting.convert_from_text(value)
-            self[key] = v
-
-    def save(self):
-        data = {}
-        settings = dict([(s.name, s) for s in self.settings])
-        for key,value in self.iteritems():
-            if key in settings:
-                setting = settings[key]
-                if isinstance(setting, _BooleanSetting):
-                    v = value
-                else:
-                    v = setting.convert_to_text(value)
-                data[key] = v
-        with open(self.filename, 'w') as f:
-            _yaml.dump(data, stream=f, Dumper=self.dumper,
-                       default_flow_style=False)
-
-
-# Define HDF5- and YAML-backed subclasses of the basic _Config types.
-for name,obj in locals().items():
-    if (obj != _Config and
-        type(obj) == type and
-        issubclass(obj, _Config) and
-        not issubclass(obj, _BackedConfig)):
-        for prefix,base in [('HDF5', _HDF5Config), ('YAML', _YAMLConfig)]:
-            _name = '%s%s' % (prefix, name)
-            _bases = (base, obj)
-            _dict = {}
-            _class = type(_name, _bases, _dict)
-            setattr(_sys.modules[__name__], _name, _class)
-
-del name, obj, prefix, base, _name, _bases, _dict, _class
-
-
-def find_base_config():
-    "Return the best `_BaseConfig` match after scanning the filesystem"
-    _LOG.info('looking for base_config file')
-    user_basepath = _os_path.join(_os_path.expanduser('~'), '.pypiezorc')
-    system_basepath = _os_path.join('/etc', 'pypiezo', 'config')
-    distributed_basepath =  _os_path.join('/usr', 'share', 'pypiezo', 'config')
-    for basepath in [user_basepath, system_basepath, distributed_basepath]:
-        for (extension, config) in [('.h5', HDF5_BaseConfig),
-                                    ('.yaml', YAML_BaseConfig)]:
-            filename = basepath + extension
-            if _os_path.exists(filename):
-                _LOG.info('base_config file found at %s' % filename)
-                base_config = config(filename)
-                base_config.load()
-                return base_config
-            else:
-                _LOG.debug('no base_config file at %s' % filename)
-    _LOG.info('new base_config file at %s' % filename)
-    basepath = user_basepath
-    filename = basepath + extension
-    return config(filename)
+_util.build_backend_classes(_sys.modules[__name__])
index ec7f4e84c8e42fd9fa8f197f23e3c18c3155b3ae..0145b23eff333d08db07fb3f5cfb1a696b1d488e 100644 (file)
@@ -35,7 +35,6 @@ except (ImportError, RuntimeError), e:
     _matplotlib_import_error = e
 
 from . import LOG as _LOG
-from . import base_config as _base_config
 from . import base as _base