"""
import ConfigParser as configparser
+import logging
import os.path
import textwrap
import unittest
"""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 = to_string(value=value, type=type)
+ self.value = value
self.type = type
+ self.count = count
self.help = help
self.wrap = wrap
for i,kv in enumerate(items):
key,value = kv
setting = self._default_settings_dict[(section, key)]
- items[i] = (key, from_string(value=value, type=setting.type))
+ try:
+ items[i] = (key, from_string(value=value, type=setting.type,
+ count=setting.count))
+ except ValueError, e:
+ log = logging.getLogger('hooke')
+ 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 = to_string(value=value, type=setting.type)
+ 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)
# size=(200, 250),
# style=wx.DIRCTRL_SHOW_FILTERS,
# filter=self.gui.config['folders-filters'],
-# defaultFilter=int(self.gui.config['folders-filter-index'])), 'left'), #HACK: config should convert
+# defaultFilter=self.gui.config['folders-filter-index']), 'left'),
(panel.PANELS['playlist'](
callbacks={
'delete_playlist':self._on_user_delete_playlist,
def _file_name(self, name):
"""Cleanup names according to configured preferences.
"""
- if self.gui.config['hide extensions'] == 'True': # HACK: config should decode
+ if self.gui.config['hide extensions'] == True:
name,ext = os.path.splitext(name)
return name
self.SetVendorName('')
self._setup_splash_screen()
- height = int(self.gui.config['main height']) # HACK: config should convert
- width = int(self.gui.config['main width'])
- top = int(self.gui.config['main top'])
- left = int(self.gui.config['main left'])
+ height = self.gui.config['main height']
+ width = self.gui.config['main width']
+ top = self.gui.config['main top']
+ left = self.gui.config['main left']
# Sometimes, the ini file gets confused and sets 'left' and
# 'top' to large negative numbers. Here we catch and fix
return True
def _setup_splash_screen(self):
- if self.gui.config['show splash screen'] == 'True': # HACK: config should decode
+ if self.gui.config['show splash screen'] == True:
path = self.gui.config['splash screen image']
if os.path.isfile(path):
- duration = int(self.gui.config['splash screen duration']) # HACK: config should decode types
+ duration = self.gui.config['splash screen duration']
wx.SplashScreen(
bitmap=wx.Image(path).ConvertToBitmap(),
splashStyle=wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT,
Setting(section=self.setting_section, help=self.__doc__),
Setting(section=self.setting_section, option='icon image',
value=os.path.join('doc', 'img', 'microscope.ico'),
+ type='file',
help='Path to the hooke icon image.'),
Setting(section=self.setting_section, option='show splash screen',
- value=True,
+ value=True, type='bool',
help='Enable/disable the splash screen'),
Setting(section=self.setting_section, option='splash screen image',
value=os.path.join('doc', 'img', 'hooke.jpg'),
+ type='file',
help='Path to the Hooke splash screen image.'),
- Setting(section=self.setting_section, option='splash screen duration',
- value=1000,
+ Setting(section=self.setting_section,
+ option='splash screen duration',
+ value=1000, type='int',
help='Duration of the splash screen in milliseconds.'),
Setting(section=self.setting_section, option='perspective path',
value=os.path.join('resources', 'gui', 'perspective'),
value='.txt',
help='Extension for perspective files.'),
Setting(section=self.setting_section, option='hide extensions',
- value=False,
+ value=False, type='bool',
help='Hide file extensions when displaying names.'),
Setting(section=self.setting_section, option='plot legend',
- value=True,
+ value=True, type='bool',
help='Enable/disable the plot legend.'),
Setting(section=self.setting_section, option='plot SI format',
- value='True',
+ value='True', type='bool',
help='Enable/disable SI plot axes numbering.'),
Setting(section=self.setting_section, option='plot decimals',
- value=2,
+ value=2, type='int',
help='Number of decimal places to show if "plot SI format" is enabled.'),
Setting(section=self.setting_section, option='folders-workdir',
- value='.',
+ value='.', type='path',
help='This should probably go...'),
Setting(section=self.setting_section, option='folders-filters',
- value='.',
+ value='.', type='path',
help='This should probably go...'),
Setting(section=self.setting_section, option='active perspective',
value='Default',
help='Name of active perspective file (or "Default").'),
- Setting(section=self.setting_section, option='folders-filter-index',
- value='0',
+ Setting(section=self.setting_section,
+ option='folders-filter-index',
+ value=0, type='int',
help='This should probably go...'),
Setting(section=self.setting_section, option='main height',
- value=450,
+ value=450, type='int',
help='Height of main window in pixels.'),
Setting(section=self.setting_section, option='main width',
- value=800,
+ value=800, type='int',
help='Width of main window in pixels.'),
Setting(section=self.setting_section, option='main top',
- value=0,
+ value=0, type='int',
help='Pixels from screen top to top of main window.'),
Setting(section=self.setting_section, option='main left',
- value=0,
- help='Pixels from screen left to left of main window.'),
+ value=0, type='int',
+ help='Pixels from screen left to left of main window.'),
Setting(section=self.setting_section, option='selected command',
value='load playlist',
help='Name of the initially selected command.'),
ANALOGS = {
'file': 'string',
+ 'path': 'string',
'point': 'int',
}
"""Types that may be treated as other types.
"""List of types that should not be converted.
"""
-def to_string(value, type):
+def to_string(value, type, count=1):
"""Convert `value` from `type` to a unicode string.
"""
type = ANALOGS.get(type, type)
if type in RAW_TYPES:
return value
+ if count != 1:
+ values = [to_string(v, type) for v in value]
+ return '[%s]' % ', '.join(values)
return unicode(value)
-def from_string(value, type):
+def from_string(value, type, count=1):
"""Convert `value` from a string to `type`.
"""
type = ANALOGS.get(type, type)
if type in RAW_TYPES:
return value
fn = globals()['_string_to_%s' % type]
+ if count != 1:
+ assert value.startswith('[') and value.endswith(']'), value
+ value = value[1:-1] # strip off brackets
+ values = [from_string(v, type) for v in value.split(', ')]
+ assert count == -1 or len(values) == count, (
+ 'array with %d != %d values: %s'
+ % (len(values), count, values))
+ return values
return fn(value)
def _string_to_string(value):