0001"""
0002**Deprecated** (13 Aug 2006)
0003"""
0004
0005
0006import warnings
0007warnings.warn('initools.configwrapper is not supported or recommended for use.',
0008 DeprecationWarning)
0009
0010
0011import os
0012import iniparser
0013
0014class _ConfigParser(iniparser.INIParser):
0015
0016 """
0017 An internal subclass of the abstract ini parser, which saves
0018 everything into one dictionary.
0019 """
0020
0021 def __init__(self, allow_empty_sections=True):
0022 self.allow_empty_sections = allow_empty_sections
0023 iniparser.INIParser.__init__(self)
0024
0025 def reset(self):
0026 self.data = {}
0027 self.key_order = {}
0028 self.section_order = []
0029 iniparser.INIParser.reset(self)
0030
0031 def assignment(self, name, content):
0032 section = self.data.setdefault(self.section, {})
0033 name = clean_name(name)
0034 section.setdefault(name, []).append(content)
0035 self.key_order.setdefault(self.section, []).append(name)
0036
0037 def new_section(self, section):
0038 section = section.strip().lower()
0039 if not section or section == 'general':
0040 section = None
0041 self.section = section
0042 if not section in self.section_order:
0043 self.section_order.append(section)
0044
0045class NoDefault:
0046 pass
0047
0048def clean_name(name):
0049 name = name.strip().lower()
0050 for char in ' \t_-':
0051 name = name.replace(char, '')
0052 return name
0053
0054class Config(object):
0055
0056 """
0057 A configuration object. Acts a little like a dictionary, but not
0058 really.
0059
0060 Configuration can be nested with ``[section]`` markers, or can be
0061 flat (everything globally available). If in sections then
0062 ``section.key`` is used, otherwise just ``key``.
0063 """
0064
0065
0066 allow_empty_sections = True
0067
0068 def __init__(self, filename, file=None,
0069 allow_empty_sections=NoDefault):
0070 if allow_empty_sections is not NoDefault:
0071 self.allow_empty_sections = allow_empty_sections
0072 self.filename = filename
0073 p = _ConfigParser(allow_empty_sections=self.allow_empty_sections)
0074 if file is None:
0075 p.load(filename)
0076 else:
0077 p.loadfile(file)
0078 self.raw_data = p.data
0079 self._section_order = p.section_order
0080 self._key_order = p.key_order
0081 self.name = os.path.splitext(os.path.basename(filename))[0]
0082
0083 def keys(self, section=NoDefault):
0084 if section is NoDefault:
0085 all = []
0086 for section_name in self._section_order:
0087 for key_name in self._key_order[section_name]:
0088 if section_name:
0089 key_name = '%s|%s' % (section_name, key_name)
0090 all.append(key_name)
0091 return all
0092 else:
0093 try:
0094 return self._key_order[section]
0095 except KeyError:
0096 raise KeyError(
0097 "Section [%s] not found (from sections %r)"
0098 %(section, self._key_order.keys()))
0099
0100 def sections(self):
0101 return self._section_order
0102
0103 def getraw(self, key, section=None):
0104 """
0105 Mostly for internal use, returns a list of all matching keys.
0106 """
0107 if '|' in key:
0108 assert section is None, (
0109 "Cannot have | in a key (%r) and an explicit section (%r)"
0110 % (key, section))
0111 section, key = key.split('|', 1)
0112 section = self.clean_section(section)
0113 try:
0114 return self.raw_data[section][key]
0115 except KeyError:
0116 return ()
0117
0118 def clean_section(self, section_name):
0119 if not section_name or section_name == 'general':
0120 return None
0121 return section_name.lower()
0122
0123 def get(self, key, default=None, section=None):
0124 """
0125 Get a single value, returning `default` if none found.
0126 """
0127 value = self.getraw(key, section=section)
0128 if not value:
0129 return default
0130 else:
0131 return value[0]
0132
0133 def getlist(self, key, default=(), section=None):
0134 """
0135 Get a list of all matching keys. Example::
0136
0137 foo = bar
0138 foo = baz
0139
0140 Then::
0141
0142 >>> config.getlist('foo')
0143 ['bar', 'baz']
0144 """
0145 value = self.getraw(key, section=section)
0146 if not value:
0147 return default
0148 else:
0149 return value
0150
0151 true_values = ['t', 'true', '1', 'y', 'yes', 'on']
0152 false_values = ['f', 'false', '0', 'n', 'no', 'off']
0153
0154 def getbool(self, key, default=False, section=None):
0155 """
0156 Get a single boolean value. Boolean values are things
0157 like ``true``, ``false``, etc.
0158 """
0159 value = self.getraw(key, section=section)
0160 if not value:
0161 return default
0162 value = value[0]
0163 if isinstance(value, (str, unicode)):
0164 value = value.lower()
0165 if value in self.true_values:
0166 return True
0167 elif value in self.false_values:
0168 return False
0169 else:
0170 raise ValueError(
0171 "Yes/No value expected for %s (got %r)"
0172 % (key, value))
0173 else:
0174 return value
0175
0176 def getint(self, key, default=None, section=None):
0177 """
0178 Get an integer value.
0179 """
0180 v = self.get(key, default=default, section=section)
0181 if v is None:
0182 return v
0183 else:
0184 return int(v)
0185
0186 def getinlinelist(self, key, default=(), section=None):
0187 """
0188 Get a list, where the list is defined like::
0189
0190 foo = bar, baz
0191
0192 Gives::
0193
0194 >>> config.getinlinelist('foo')
0195 ['bar', 'baz']
0196 """
0197 result = []
0198 for item in self.getlist(key, default, section):
0199 item = item.strip()
0200 if not item:
0201 continue
0202 if ',' in item:
0203 result.extend([i.strip() for i in item.split(',')])
0204 else:
0205 result.append(item)
0206 return result
0207
0208 def getstartswith(self, startswith, section):
0209 """
0210 Returns a list of ``[(key, value), ...]`` for all keys in the
0211 section that start with startswith.
0212 """
0213 result = []
0214 for key in self.keys(section=section):
0215 if not key.startswith(startswith):
0216 continue
0217 for value in self.getraw(key, section=section):
0218 result.append((key, value))
0219 return result
0220
0221 def __repr__(self):
0222 return '<%s filename=%s>' % (
0223 self.__class__.__name__, self.filename)
0224
0225 def __str__(self):
0226 data = []
0227 data.append('%s from %s:' % (
0228 self.__class__.__name__, self.filename))
0229 for name, value_list in self.raw_data.get(None, {}).items():
0230 for value in value_list:
0231 data.append('%s: %s' % (name, value))
0232 for section_name, value_dict in self.raw_data.items():
0233 if section_name is None:
0234 continue
0235 data.append('[%s]' % section_name)
0236 for name, value_list in value_dict.items():
0237 for value in value_list:
0238 data.append('%s: %s' % (name, value))
0239 return '\n'.join(data)
0240
0241def load_options(parser, options, config, if_exists=True):
0242 """
0243 Given a parser object and the parsed options and a configuration
0244 object or filename, this will load the configuration into the
0245 parsed options.
0246 """
0247 types = {}
0248 dests = {}
0249 aliases = {}
0250 for option in parser.option_list:
0251 if not option.dest:
0252
0253 continue
0254 name = clean_name(option.dest)
0255 dests[name] = option.dest
0256 if option.action in ('store_true', 'store_false'):
0257 types[name] = 'getbool'
0258 else:
0259 types[name] = 'get'
0260 for lst in option._long_opts, option._short_opts:
0261 for opt in lst:
0262 aliases[clean_name(opt)] = name
0263 if isinstance(config, str):
0264 if if_exists and not os.path.exists(config):
0265 return
0266 config = Config(config)
0267 for config_key in config.keys():
0268 name = aliases.get(config_key, config_key)
0269 if name not in dests:
0270 raise ValueError(
0271 "Bad configuration file: option %r unexpected" % config_key)
0272 value = getattr(config, types[name])(config_key)
0273 setattr(options, dests[name], value)