-# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2010-2012 W. Trevor King <wking@tremily.us>
#
# This file is part of Hooke.
#
-# Hooke is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
+# Hooke is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
#
-# Hooke 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 Lesser General
-# Public License for more details.
+# Hooke 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 Lesser General Public License for more
+# details.
#
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke. If not, see
-# <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Lesser General Public License
+# along with Hooke. If not, see <http://www.gnu.org/licenses/>.
"""Configuration defaults, read/write, and template file creation for
Hooke.
"""
import ConfigParser as configparser
+import logging
import os.path
import textwrap
import unittest
from .compat.odict import odict as OrderedDict
+from .util.convert import to_string, from_string
DEFAULT_PATHS = [
in turn overrides the developer defaults.
"""
-CONVERT_FROM_STRING = {
- 'string': lambda x: x,
- 'bool': lambda x: x == 'True',
- 'int': lambda x: int(x),
- 'float': lambda x: float(x),
- }
-"""Functions converting strings to values, keyed by type.
-"""
-
-CONVERT_TO_STRING = {
- 'string': lambda x: x,
- 'bool': lambda x: str(x),
- 'int': lambda x: str(x),
- 'float': lambda x: str(x),
- }
-"""Functions converting values to strings, keyed by type.
-"""
-
class Setting (object):
"""An entry (section or option) in HookeConfigParser.
"""
def __init__(self, section, option=None, value=None, type='string',
- help=None, wrap=True):
+ count=1, help=None, wrap=True):
self.section = section
self.option = option
- self.value = CONVERT_TO_STRING[type](value)
+ self.value = value
self.type = type
+ self.count = count
self.help = help
self.wrap = wrap
str(value).replace('\n', '\n\t')))
DEFAULT_SETTINGS = [
- Setting('conditions', help='Default environmental conditions in case they are not specified in the force curve data.'),
+ Setting('conditions', help='Default environmental conditions in case they are not specified in the force curve data. Configuration options in this section are available to every plugin.'),
Setting('conditions', 'temperature', value='301', type='float', help='Temperature in Kelvin'),
# Logging settings
Setting('loggers', help='Configure loggers, see\nhttp://docs.python.org/library/logging.html#configuration-file-format', wrap=False),
Setting('logger_hooke', 'qualname', 'hooke'),
Setting('handler_hand1', help='Configure the default log handler, see\nhttp://docs.python.org/library/logging.html#configuration-file-format', wrap=False),
Setting('handler_hand1', 'class', 'StreamHandler'),
- Setting('handler_hand1', 'level', 'NOTSET'),
+ Setting('handler_hand1', 'level', 'WARN'),
Setting('handler_hand1', 'formatter', 'form1'),
Setting('handler_hand1', 'args', '(sys.stderr,)'),
Setting('formatter_form1', help='Configure the default log formatter, see\nhttp://docs.python.org/library/logging.html#configuration-file-format', wrap=False),
>>> c = HookeConfigParser(default_settings=DEFAULT_SETTINGS)
>>> c.write(sys.stdout) # doctest: +ELLIPSIS
# Default environmental conditions in case they are not specified in
- # the force curve data.
+ # the force curve data. Configuration options in this section are
+ # available to every plugin.
[conditions]
# Temperature in Kelvin
temperature = 301
... Setting(section, option='my float', value=3.14159, type='float'),
... ])
>>> pprint.pprint(c.items(section)) # doctest: +ELLIPSIS
- [('my string', 'Lorem ipsum'),
+ [('my string', u'Lorem ipsum'),
('my bool', True),
('my int', 13),
('my float', 3.1415...)]
to use the standard `.get*()` methods.
>>> c.get('test conversion', 'my bool')
- 'True'
+ u'True'
>>> c.getboolean('test conversion', 'my bool')
True
"""
self._config_paths.append(filename)
# Can't use super() because RawConfigParser is a classic class
#return super(HookeConfigParser, self).read(filenames)
- return configparser.RawConfigParser.read(self, filenames)
+ return configparser.RawConfigParser.read(self, self._config_paths)
def _write_setting(self, fp, section=None, option=None, value=None,
**kwargs):
self, section, *args, **kwargs)
for i,kv in enumerate(items):
key,value = kv
- setting = self._default_settings_dict[(section, key)]
- items[i] = (key, CONVERT_FROM_STRING[setting.type](value))
+ log = logging.getLogger('hooke')
+ try:
+ setting = self._default_settings_dict[(section, key)]
+ except KeyError, e:
+ log.error('unknown setting %s/%s: %s' % (section, key, e))
+ raise
+ try:
+ items[i] = (key, from_string(value=value, type=setting.type,
+ count=setting.count))
+ except ValueError, e:
+ log.error("could not convert '%s' (%s) for %s/%s: %s"
+ % (value, type(value), section, key, e))
+ raise
return items
def set(self, section, option, value):
"""Set an option."""
setting = self._default_settings_dict[(section, option)]
- value = CONVERT_TO_STRING[setting.type](value)
+ value = to_string(value=value, type=setting.type, count=setting.count)
# Can't use super() because RawConfigParser is a classic class
#return super(HookeConfigParser, self).set(section, option, value)
configparser.RawConfigParser.set(self, section, option, value)