Ran update-copyright.py
[hooke.git] / hooke / config.py
index c1776c8eee6367056490269c1e54a0dc0d6b8fe7..141cf5757520c4e7f74de4d1963e4db0e8792991 100644 (file)
@@ -1,31 +1,32 @@
-# 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 = [
@@ -39,33 +40,16 @@ specific user files, so the user can override the sysadmin who
 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
 
@@ -102,7 +86,7 @@ class Setting (object):
                                     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),
@@ -121,7 +105,7 @@ DEFAULT_SETTINGS = [
     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),
@@ -152,7 +136,8 @@ class HookeConfigParser (configparser.RawConfigParser):
     >>> 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
@@ -176,7 +161,7 @@ class HookeConfigParser (configparser.RawConfigParser):
     ...         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...)]
@@ -185,7 +170,7 @@ class HookeConfigParser (configparser.RawConfigParser):
     to use the standard `.get*()` methods.
 
     >>> c.get('test conversion', 'my bool')
-    'True'
+    u'True'
     >>> c.getboolean('test conversion', 'my bool')
     True
     """
@@ -248,7 +233,7 @@ class HookeConfigParser (configparser.RawConfigParser):
                     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):
@@ -315,14 +300,25 @@ class HookeConfigParser (configparser.RawConfigParser):
             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)