OLD | NEW |
1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # | 3 # |
4 # This file is part of logilab-common. | 4 # This file is part of logilab-common. |
5 # | 5 # |
6 # logilab-common is free software: you can redistribute it and/or modify it unde
r | 6 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
7 # the terms of the GNU Lesser General Public License as published by the Free | 7 # the terms of the GNU Lesser General Public License as published by the Free |
8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y | 8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
9 # later version. | 9 # later version. |
10 # | 10 # |
11 # logilab-common is distributed in the hope that it will be useful, but WITHOUT | 11 # logilab-common is distributed in the hope that it will be useful, but WITHOUT |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 [MY CONFIG] | 89 [MY CONFIG] |
90 | 90 |
91 dothis=no | 91 dothis=no |
92 | 92 |
93 value=bacon | 93 value=bacon |
94 | 94 |
95 # you can also document the option | 95 # you can also document the option |
96 multiple=4,5,6 | 96 multiple=4,5,6 |
97 | 97 |
98 number=3 | 98 number=3 |
99 | 99 >>> |
100 Note : starting with Python 2.7 ConfigParser is able to take into | |
101 account the order of occurrences of the options into a file (by | |
102 using an OrderedDict). If you have two options changing some common | |
103 state, like a 'disable-all-stuff' and a 'enable-some-stuff-a', their | |
104 order of appearance will be significant : the last specified in the | |
105 file wins. For earlier version of python and logilab.common newer | |
106 than 0.61 the behaviour is unspecified. | |
107 | |
108 """ | 100 """ |
109 | |
110 from __future__ import print_function | |
111 | |
112 __docformat__ = "restructuredtext en" | 101 __docformat__ = "restructuredtext en" |
113 | 102 |
114 __all__ = ('OptionsManagerMixIn', 'OptionsProviderMixIn', | 103 __all__ = ('OptionsManagerMixIn', 'OptionsProviderMixIn', |
115 'ConfigurationMixIn', 'Configuration', | 104 'ConfigurationMixIn', 'Configuration', |
116 'OptionsManager2ConfigurationAdapter') | 105 'OptionsManager2ConfigurationAdapter') |
117 | 106 |
118 import os | 107 import os |
119 import sys | 108 import sys |
120 import re | 109 import re |
121 from os.path import exists, expanduser | 110 from os.path import exists, expanduser |
122 from copy import copy | 111 from copy import copy |
| 112 from ConfigParser import ConfigParser, NoOptionError, NoSectionError, \ |
| 113 DuplicateSectionError |
123 from warnings import warn | 114 from warnings import warn |
124 | 115 |
125 from six import string_types | 116 from logilab.common.compat import callable, raw_input, str_encode as _encode |
126 from six.moves import range, configparser as cp, input | |
127 | 117 |
128 from logilab.common.compat import str_encode as _encode | |
129 from logilab.common.deprecation import deprecated | |
130 from logilab.common.textutils import normalize_text, unquote | 118 from logilab.common.textutils import normalize_text, unquote |
131 from logilab.common import optik_ext | 119 from logilab.common import optik_ext as optparse |
132 | 120 |
133 OptionError = optik_ext.OptionError | 121 OptionError = optparse.OptionError |
134 | 122 |
135 REQUIRED = [] | 123 REQUIRED = [] |
136 | 124 |
137 class UnsupportedAction(Exception): | 125 class UnsupportedAction(Exception): |
138 """raised by set_option when it doesn't know what to do for an action""" | 126 """raised by set_option when it doesn't know what to do for an action""" |
139 | 127 |
140 | 128 |
141 def _get_encoding(encoding, stream): | 129 def _get_encoding(encoding, stream): |
142 encoding = encoding or getattr(stream, 'encoding', None) | 130 encoding = encoding or getattr(stream, 'encoding', None) |
143 if not encoding: | 131 if not encoding: |
144 import locale | 132 import locale |
145 encoding = locale.getpreferredencoding() | 133 encoding = locale.getpreferredencoding() |
146 return encoding | 134 return encoding |
147 | 135 |
148 | 136 |
149 # validation functions ######################################################## | 137 # validation functions ######################################################## |
150 | 138 |
151 # validators will return the validated value or raise optparse.OptionValueError | |
152 # XXX add to documentation | |
153 | |
154 def choice_validator(optdict, name, value): | 139 def choice_validator(optdict, name, value): |
155 """validate and return a converted value for option of type 'choice' | 140 """validate and return a converted value for option of type 'choice' |
156 """ | 141 """ |
157 if not value in optdict['choices']: | 142 if not value in optdict['choices']: |
158 msg = "option %s: invalid value: %r, should be in %s" | 143 msg = "option %s: invalid value: %r, should be in %s" |
159 raise optik_ext.OptionValueError(msg % (name, value, optdict['choices'])
) | 144 raise optparse.OptionValueError(msg % (name, value, optdict['choices'])) |
160 return value | 145 return value |
161 | 146 |
162 def multiple_choice_validator(optdict, name, value): | 147 def multiple_choice_validator(optdict, name, value): |
163 """validate and return a converted value for option of type 'choice' | 148 """validate and return a converted value for option of type 'choice' |
164 """ | 149 """ |
165 choices = optdict['choices'] | 150 choices = optdict['choices'] |
166 values = optik_ext.check_csv(None, name, value) | 151 values = optparse.check_csv(None, name, value) |
167 for value in values: | 152 for value in values: |
168 if not value in choices: | 153 if not value in choices: |
169 msg = "option %s: invalid value: %r, should be in %s" | 154 msg = "option %s: invalid value: %r, should be in %s" |
170 raise optik_ext.OptionValueError(msg % (name, value, choices)) | 155 raise optparse.OptionValueError(msg % (name, value, choices)) |
171 return values | 156 return values |
172 | 157 |
173 def csv_validator(optdict, name, value): | 158 def csv_validator(optdict, name, value): |
174 """validate and return a converted value for option of type 'csv' | 159 """validate and return a converted value for option of type 'csv' |
175 """ | 160 """ |
176 return optik_ext.check_csv(None, name, value) | 161 return optparse.check_csv(None, name, value) |
177 | 162 |
178 def yn_validator(optdict, name, value): | 163 def yn_validator(optdict, name, value): |
179 """validate and return a converted value for option of type 'yn' | 164 """validate and return a converted value for option of type 'yn' |
180 """ | 165 """ |
181 return optik_ext.check_yn(None, name, value) | 166 return optparse.check_yn(None, name, value) |
182 | 167 |
183 def named_validator(optdict, name, value): | 168 def named_validator(optdict, name, value): |
184 """validate and return a converted value for option of type 'named' | 169 """validate and return a converted value for option of type 'named' |
185 """ | 170 """ |
186 return optik_ext.check_named(None, name, value) | 171 return optparse.check_named(None, name, value) |
187 | 172 |
188 def file_validator(optdict, name, value): | 173 def file_validator(optdict, name, value): |
189 """validate and return a filepath for option of type 'file'""" | 174 """validate and return a filepath for option of type 'file'""" |
190 return optik_ext.check_file(None, name, value) | 175 return optparse.check_file(None, name, value) |
191 | 176 |
192 def color_validator(optdict, name, value): | 177 def color_validator(optdict, name, value): |
193 """validate and return a valid color for option of type 'color'""" | 178 """validate and return a valid color for option of type 'color'""" |
194 return optik_ext.check_color(None, name, value) | 179 return optparse.check_color(None, name, value) |
195 | 180 |
196 def password_validator(optdict, name, value): | 181 def password_validator(optdict, name, value): |
197 """validate and return a string for option of type 'password'""" | 182 """validate and return a string for option of type 'password'""" |
198 return optik_ext.check_password(None, name, value) | 183 return optparse.check_password(None, name, value) |
199 | 184 |
200 def date_validator(optdict, name, value): | 185 def date_validator(optdict, name, value): |
201 """validate and return a mx DateTime object for option of type 'date'""" | 186 """validate and return a mx DateTime object for option of type 'date'""" |
202 return optik_ext.check_date(None, name, value) | 187 return optparse.check_date(None, name, value) |
203 | 188 |
204 def time_validator(optdict, name, value): | 189 def time_validator(optdict, name, value): |
205 """validate and return a time object for option of type 'time'""" | 190 """validate and return a time object for option of type 'time'""" |
206 return optik_ext.check_time(None, name, value) | 191 return optparse.check_time(None, name, value) |
207 | 192 |
208 def bytes_validator(optdict, name, value): | 193 def bytes_validator(optdict, name, value): |
209 """validate and return an integer for option of type 'bytes'""" | 194 """validate and return an integer for option of type 'bytes'""" |
210 return optik_ext.check_bytes(None, name, value) | 195 return optparse.check_bytes(None, name, value) |
211 | 196 |
212 | 197 |
213 VALIDATORS = {'string': unquote, | 198 VALIDATORS = {'string': unquote, |
214 'int': int, | 199 'int': int, |
215 'float': float, | 200 'float': float, |
216 'file': file_validator, | 201 'file': file_validator, |
217 'font': unquote, | 202 'font': unquote, |
218 'color': color_validator, | 203 'color': color_validator, |
219 'regexp': re.compile, | 204 'regexp': re.compile, |
220 'csv': csv_validator, | 205 'csv': csv_validator, |
221 'yn': yn_validator, | 206 'yn': yn_validator, |
222 'bool': yn_validator, | 207 'bool': yn_validator, |
223 'named': named_validator, | 208 'named': named_validator, |
224 'password': password_validator, | 209 'password': password_validator, |
225 'date': date_validator, | 210 'date': date_validator, |
226 'time': time_validator, | 211 'time': time_validator, |
227 'bytes': bytes_validator, | 212 'bytes': bytes_validator, |
228 'choice': choice_validator, | 213 'choice': choice_validator, |
229 'multiple_choice': multiple_choice_validator, | 214 'multiple_choice': multiple_choice_validator, |
230 } | 215 } |
231 | 216 |
232 def _call_validator(opttype, optdict, option, value): | 217 def _call_validator(opttype, optdict, option, value): |
233 if opttype not in VALIDATORS: | 218 if opttype not in VALIDATORS: |
234 raise Exception('Unsupported type "%s"' % opttype) | 219 raise Exception('Unsupported type "%s"' % opttype) |
235 try: | 220 try: |
236 return VALIDATORS[opttype](optdict, option, value) | 221 return VALIDATORS[opttype](optdict, option, value) |
237 except TypeError: | 222 except TypeError: |
238 try: | 223 try: |
239 return VALIDATORS[opttype](value) | 224 return VALIDATORS[opttype](value) |
240 except optik_ext.OptionValueError: | 225 except optparse.OptionValueError: |
241 raise | 226 raise |
242 except: | 227 except: |
243 raise optik_ext.OptionValueError('%s value (%r) should be of type %s
' % | 228 raise optparse.OptionValueError('%s value (%r) should be of type %s'
% |
244 (option, value, opttype)) | 229 (option, value, opttype)) |
245 | 230 |
246 # user input functions ######################################################## | 231 # user input functions ######################################################## |
247 | 232 |
248 # user input functions will ask the user for input on stdin then validate | |
249 # the result and return the validated value or raise optparse.OptionValueError | |
250 # XXX add to documentation | |
251 | |
252 def input_password(optdict, question='password:'): | 233 def input_password(optdict, question='password:'): |
253 from getpass import getpass | 234 from getpass import getpass |
254 while True: | 235 while True: |
255 value = getpass(question) | 236 value = getpass(question) |
256 value2 = getpass('confirm: ') | 237 value2 = getpass('confirm: ') |
257 if value == value2: | 238 if value == value2: |
258 return value | 239 return value |
259 print('password mismatch, try again') | 240 print 'password mismatch, try again' |
260 | 241 |
261 def input_string(optdict, question): | 242 def input_string(optdict, question): |
262 value = input(question).strip() | 243 value = raw_input(question).strip() |
263 return value or None | 244 return value or None |
264 | 245 |
265 def _make_input_function(opttype): | 246 def _make_input_function(opttype): |
266 def input_validator(optdict, question): | 247 def input_validator(optdict, question): |
267 while True: | 248 while True: |
268 value = input(question) | 249 value = raw_input(question) |
269 if not value.strip(): | 250 if not value.strip(): |
270 return None | 251 return None |
271 try: | 252 try: |
272 return _call_validator(opttype, optdict, None, value) | 253 return _call_validator(opttype, optdict, None, value) |
273 except optik_ext.OptionValueError as ex: | 254 except optparse.OptionValueError, ex: |
274 msg = str(ex).split(':', 1)[-1].strip() | 255 msg = str(ex).split(':', 1)[-1].strip() |
275 print('bad value: %s' % msg) | 256 print 'bad value: %s' % msg |
276 return input_validator | 257 return input_validator |
277 | 258 |
278 INPUT_FUNCTIONS = { | 259 INPUT_FUNCTIONS = { |
279 'string': input_string, | 260 'string': input_string, |
280 'password': input_password, | 261 'password': input_password, |
281 } | 262 } |
282 | 263 |
283 for opttype in VALIDATORS.keys(): | 264 for opttype in VALIDATORS.keys(): |
284 INPUT_FUNCTIONS.setdefault(opttype, _make_input_function(opttype)) | 265 INPUT_FUNCTIONS.setdefault(opttype, _make_input_function(opttype)) |
285 | 266 |
286 # utility functions ############################################################ | |
287 | |
288 def expand_default(self, option): | 267 def expand_default(self, option): |
289 """monkey patch OptionParser.expand_default since we have a particular | 268 """monkey patch OptionParser.expand_default since we have a particular |
290 way to handle defaults to avoid overriding values in the configuration | 269 way to handle defaults to avoid overriding values in the configuration |
291 file | 270 file |
292 """ | 271 """ |
293 if self.parser is None or not self.default_tag: | 272 if self.parser is None or not self.default_tag: |
294 return option.help | 273 return option.help |
295 optname = option._long_opts[0][2:] | 274 optname = option._long_opts[0][2:] |
296 try: | 275 try: |
297 provider = self.parser.options_manager._all_options[optname] | 276 provider = self.parser.options_manager._all_options[optname] |
298 except KeyError: | 277 except KeyError: |
299 value = None | 278 value = None |
300 else: | 279 else: |
301 optdict = provider.get_option_def(optname) | 280 optdict = provider.get_option_def(optname) |
302 optname = provider.option_attrname(optname, optdict) | 281 optname = provider.option_name(optname, optdict) |
303 value = getattr(provider.config, optname, optdict) | 282 value = getattr(provider.config, optname, optdict) |
304 value = format_option_value(optdict, value) | 283 value = format_option_value(optdict, value) |
305 if value is optik_ext.NO_DEFAULT or not value: | 284 if value is optparse.NO_DEFAULT or not value: |
306 value = self.NO_DEFAULT_VALUE | 285 value = self.NO_DEFAULT_VALUE |
307 return option.help.replace(self.default_tag, str(value)) | 286 return option.help.replace(self.default_tag, str(value)) |
308 | 287 |
309 | 288 |
310 def _validate(value, optdict, name=''): | 289 def convert(value, optdict, name=''): |
311 """return a validated value for an option according to its type | 290 """return a validated value for an option according to its type |
312 | 291 |
313 optional argument name is only used for error message formatting | 292 optional argument name is only used for error message formatting |
314 """ | 293 """ |
315 try: | 294 try: |
316 _type = optdict['type'] | 295 _type = optdict['type'] |
317 except KeyError: | 296 except KeyError: |
318 # FIXME | 297 # FIXME |
319 return value | 298 return value |
320 return _call_validator(_type, optdict, name, value) | 299 return _call_validator(_type, optdict, name, value) |
321 convert = deprecated('[0.60] convert() was renamed _validate()')(_validate) | |
322 | |
323 # format and output functions ################################################## | |
324 | 300 |
325 def comment(string): | 301 def comment(string): |
326 """return string as a comment""" | 302 """return string as a comment""" |
327 lines = [line.strip() for line in string.splitlines()] | 303 lines = [line.strip() for line in string.splitlines()] |
328 return '# ' + ('%s# ' % os.linesep).join(lines) | 304 return '# ' + ('%s# ' % os.linesep).join(lines) |
329 | 305 |
330 def format_time(value): | 306 def format_time(value): |
331 if not value: | 307 if not value: |
332 return '0' | 308 return '0' |
333 if value != int(value): | 309 if value != int(value): |
(...skipping 29 matching lines...) Expand all Loading... |
363 """return the user input's value from a 'compiled' value""" | 339 """return the user input's value from a 'compiled' value""" |
364 if isinstance(value, (list, tuple)): | 340 if isinstance(value, (list, tuple)): |
365 value = ','.join(value) | 341 value = ','.join(value) |
366 elif isinstance(value, dict): | 342 elif isinstance(value, dict): |
367 value = ','.join(['%s:%s' % (k, v) for k, v in value.items()]) | 343 value = ','.join(['%s:%s' % (k, v) for k, v in value.items()]) |
368 elif hasattr(value, 'match'): # optdict.get('type') == 'regexp' | 344 elif hasattr(value, 'match'): # optdict.get('type') == 'regexp' |
369 # compiled regexp | 345 # compiled regexp |
370 value = value.pattern | 346 value = value.pattern |
371 elif optdict.get('type') == 'yn': | 347 elif optdict.get('type') == 'yn': |
372 value = value and 'yes' or 'no' | 348 value = value and 'yes' or 'no' |
373 elif isinstance(value, string_types) and value.isspace(): | 349 elif isinstance(value, (str, unicode)) and value.isspace(): |
374 value = "'%s'" % value | 350 value = "'%s'" % value |
375 elif optdict.get('type') == 'time' and isinstance(value, (float, int, long))
: | 351 elif optdict.get('type') == 'time' and isinstance(value, (float, int, long))
: |
376 value = format_time(value) | 352 value = format_time(value) |
377 elif optdict.get('type') == 'bytes' and hasattr(value, '__int__'): | 353 elif optdict.get('type') == 'bytes' and hasattr(value, '__int__'): |
378 value = format_bytes(value) | 354 value = format_bytes(value) |
379 return value | 355 return value |
380 | 356 |
381 def ini_format_section(stream, section, options, encoding=None, doc=None): | 357 def ini_format_section(stream, section, options, encoding=None, doc=None): |
382 """format an options section using the INI format""" | 358 """format an options section using the INI format""" |
383 encoding = _get_encoding(encoding, stream) | 359 encoding = _get_encoding(encoding, stream) |
384 if doc: | 360 if doc: |
385 print(_encode(comment(doc), encoding), file=stream) | 361 print >> stream, _encode(comment(doc), encoding) |
386 print('[%s]' % section, file=stream) | 362 print >> stream, '[%s]' % section |
387 ini_format(stream, options, encoding) | 363 ini_format(stream, options, encoding) |
388 | 364 |
389 def ini_format(stream, options, encoding): | 365 def ini_format(stream, options, encoding): |
390 """format options using the INI format""" | 366 """format options using the INI format""" |
391 for optname, optdict, value in options: | 367 for optname, optdict, value in options: |
392 value = format_option_value(optdict, value) | 368 value = format_option_value(optdict, value) |
393 help = optdict.get('help') | 369 help = optdict.get('help') |
394 if help: | 370 if help: |
395 help = normalize_text(help, line_len=79, indent='# ') | 371 help = normalize_text(help, line_len=79, indent='# ') |
396 print(file=stream) | 372 print >> stream |
397 print(_encode(help, encoding), file=stream) | 373 print >> stream, _encode(help, encoding) |
398 else: | 374 else: |
399 print(file=stream) | 375 print >> stream |
400 if value is None: | 376 if value is None: |
401 print('#%s=' % optname, file=stream) | 377 print >> stream, '#%s=' % optname |
402 else: | 378 else: |
403 value = _encode(value, encoding).strip() | 379 value = _encode(value, encoding).strip() |
404 print('%s=%s' % (optname, value), file=stream) | 380 print >> stream, '%s=%s' % (optname, value) |
405 | 381 |
406 format_section = ini_format_section | 382 format_section = ini_format_section |
407 | 383 |
408 def rest_format_section(stream, section, options, encoding=None, doc=None): | 384 def rest_format_section(stream, section, options, encoding=None, doc=None): |
409 """format an options section using as ReST formatted output""" | 385 """format an options section using the INI format""" |
410 encoding = _get_encoding(encoding, stream) | 386 encoding = _get_encoding(encoding, stream) |
411 if section: | 387 if section: |
412 print >> stream, '%s\n%s' % (section, "'"*len(section)) | 388 print >> stream, '%s\n%s' % (section, "'"*len(section)) |
413 if doc: | 389 if doc: |
414 print >> stream, _encode(normalize_text(doc, line_len=79, indent=''), | 390 print >> stream, _encode(normalize_text(doc, line_len=79, indent=''), |
415 encoding) | 391 encoding) |
416 print >> stream | 392 print >> stream |
417 for optname, optdict, value in options: | 393 for optname, optdict, value in options: |
418 help = optdict.get('help') | 394 help = optdict.get('help') |
419 print >> stream, ':%s:' % optname | 395 print >> stream, ':%s:' % optname |
420 if help: | 396 if help: |
421 help = normalize_text(help, line_len=79, indent=' ') | 397 help = normalize_text(help, line_len=79, indent=' ') |
422 print >> stream, _encode(help, encoding) | 398 print >> stream, _encode(help, encoding) |
423 if value: | 399 if value: |
424 value = _encode(format_option_value(optdict, value), encoding) | 400 value = _encode(format_option_value(optdict, value), encoding) |
425 print >> stream, '' | 401 print >> stream, '' |
426 print >> stream, ' Default: ``%s``' % value.replace("`` ", "```` ``
") | 402 print >> stream, ' Default: ``%s``' % value.replace("`` ", "```` ``
") |
427 | 403 |
428 # Options Manager ############################################################## | |
429 | 404 |
430 class OptionsManagerMixIn(object): | 405 class OptionsManagerMixIn(object): |
431 """MixIn to handle a configuration from both a configuration file and | 406 """MixIn to handle a configuration from both a configuration file and |
432 command line options | 407 command line options |
433 """ | 408 """ |
434 | 409 |
435 def __init__(self, usage, config_file=None, version=None, quiet=0): | 410 def __init__(self, usage, config_file=None, version=None, quiet=0): |
436 self.config_file = config_file | 411 self.config_file = config_file |
437 self.reset_parsers(usage, version=version) | 412 self.reset_parsers(usage, version=version) |
438 # list of registered options providers | 413 # list of registered options providers |
439 self.options_providers = [] | 414 self.options_providers = [] |
440 # dictionary associating option name to checker | 415 # dictionary associating option name to checker |
441 self._all_options = {} | 416 self._all_options = {} |
442 self._short_options = {} | 417 self._short_options = {} |
443 self._nocallback_options = {} | 418 self._nocallback_options = {} |
444 self._mygroups = dict() | 419 self._mygroups = dict() |
445 # verbosity | 420 # verbosity |
446 self.quiet = quiet | 421 self.quiet = quiet |
447 self._maxlevel = 0 | 422 self._maxlevel = 0 |
448 | 423 |
449 def reset_parsers(self, usage='', version=None): | 424 def reset_parsers(self, usage='', version=None): |
450 # configuration file parser | 425 # configuration file parser |
451 self.cfgfile_parser = cp.ConfigParser() | 426 self.cfgfile_parser = ConfigParser() |
452 # command line parser | 427 # command line parser |
453 self.cmdline_parser = optik_ext.OptionParser(usage=usage, version=versio
n) | 428 self.cmdline_parser = optparse.OptionParser(usage=usage, version=version
) |
454 self.cmdline_parser.options_manager = self | 429 self.cmdline_parser.options_manager = self |
455 self._optik_option_attrs = set(self.cmdline_parser.option_class.ATTRS) | 430 self._optik_option_attrs = set(self.cmdline_parser.option_class.ATTRS) |
456 | 431 |
457 def register_options_provider(self, provider, own_group=True): | 432 def register_options_provider(self, provider, own_group=True): |
458 """register an options provider""" | 433 """register an options provider""" |
459 assert provider.priority <= 0, "provider's priority can't be >= 0" | 434 assert provider.priority <= 0, "provider's priority can't be >= 0" |
460 for i in range(len(self.options_providers)): | 435 for i in range(len(self.options_providers)): |
461 if provider.priority > self.options_providers[i].priority: | 436 if provider.priority > self.options_providers[i].priority: |
462 self.options_providers.insert(i, provider) | 437 self.options_providers.insert(i, provider) |
463 break | 438 break |
(...skipping 15 matching lines...) Expand all Loading... |
479 self.add_option_group(gname, gdoc, goptions, provider) | 454 self.add_option_group(gname, gdoc, goptions, provider) |
480 | 455 |
481 def add_option_group(self, group_name, doc, options, provider): | 456 def add_option_group(self, group_name, doc, options, provider): |
482 """add an option group including the listed options | 457 """add an option group including the listed options |
483 """ | 458 """ |
484 assert options | 459 assert options |
485 # add option group to the command line parser | 460 # add option group to the command line parser |
486 if group_name in self._mygroups: | 461 if group_name in self._mygroups: |
487 group = self._mygroups[group_name] | 462 group = self._mygroups[group_name] |
488 else: | 463 else: |
489 group = optik_ext.OptionGroup(self.cmdline_parser, | 464 group = optparse.OptionGroup(self.cmdline_parser, |
490 title=group_name.capitalize()) | 465 title=group_name.capitalize()) |
491 self.cmdline_parser.add_option_group(group) | 466 self.cmdline_parser.add_option_group(group) |
492 group.level = provider.level | 467 group.level = provider.level |
493 self._mygroups[group_name] = group | 468 self._mygroups[group_name] = group |
494 # add section to the config file | 469 # add section to the config file |
495 if group_name != "DEFAULT": | 470 if group_name != "DEFAULT": |
496 self.cfgfile_parser.add_section(group_name) | 471 self.cfgfile_parser.add_section(group_name) |
497 # add provider's specific options | 472 # add provider's specific options |
498 for opt, optdict in options: | 473 for opt, optdict in options: |
499 self.add_optik_option(provider, group, opt, optdict) | 474 self.add_optik_option(provider, group, opt, optdict) |
(...skipping 15 matching lines...) Expand all Loading... |
515 optdict = copy(optdict) | 490 optdict = copy(optdict) |
516 others = {} | 491 others = {} |
517 if 'action' in optdict: | 492 if 'action' in optdict: |
518 self._nocallback_options[provider] = opt | 493 self._nocallback_options[provider] = opt |
519 else: | 494 else: |
520 optdict['action'] = 'callback' | 495 optdict['action'] = 'callback' |
521 optdict['callback'] = self.cb_set_provider_option | 496 optdict['callback'] = self.cb_set_provider_option |
522 # default is handled here and *must not* be given to optik if you | 497 # default is handled here and *must not* be given to optik if you |
523 # want the whole machinery to work | 498 # want the whole machinery to work |
524 if 'default' in optdict: | 499 if 'default' in optdict: |
525 if ('help' in optdict | 500 if (optparse.OPTPARSE_FORMAT_DEFAULT and 'help' in optdict and |
526 and optdict.get('default') is not None | 501 optdict.get('default') is not None and |
527 and not optdict['action'] in ('store_true', 'store_false')): | 502 not optdict['action'] in ('store_true', 'store_false')): |
528 optdict['help'] += ' [current: %default]' | 503 optdict['help'] += ' [current: %default]' |
529 del optdict['default'] | 504 del optdict['default'] |
530 args = ['--' + str(opt)] | 505 args = ['--' + str(opt)] |
531 if 'short' in optdict: | 506 if 'short' in optdict: |
532 self._short_options[optdict['short']] = opt | 507 self._short_options[optdict['short']] = opt |
533 args.append('-' + optdict['short']) | 508 args.append('-' + optdict['short']) |
534 del optdict['short'] | 509 del optdict['short'] |
535 # cleanup option definition dict before giving it to optik | 510 # cleanup option definition dict before giving it to optik |
536 for key in list(optdict.keys()): | 511 for key in optdict.keys(): |
537 if not key in self._optik_option_attrs: | 512 if not key in self._optik_option_attrs: |
538 optdict.pop(key) | 513 optdict.pop(key) |
539 return args, optdict | 514 return args, optdict |
540 | 515 |
541 def cb_set_provider_option(self, option, opt, value, parser): | 516 def cb_set_provider_option(self, option, opt, value, parser): |
542 """optik callback for option setting""" | 517 """optik callback for option setting""" |
543 if opt.startswith('--'): | 518 if opt.startswith('--'): |
544 # remove -- on long option | 519 # remove -- on long option |
545 opt = opt[2:] | 520 opt = opt[2:] |
546 else: | 521 else: |
(...skipping 26 matching lines...) Expand all Loading... |
573 continue | 548 continue |
574 if not section in sections: | 549 if not section in sections: |
575 sections.append(section) | 550 sections.append(section) |
576 alloptions = options_by_section.setdefault(section, []) | 551 alloptions = options_by_section.setdefault(section, []) |
577 alloptions += options | 552 alloptions += options |
578 stream = stream or sys.stdout | 553 stream = stream or sys.stdout |
579 encoding = _get_encoding(encoding, stream) | 554 encoding = _get_encoding(encoding, stream) |
580 printed = False | 555 printed = False |
581 for section in sections: | 556 for section in sections: |
582 if printed: | 557 if printed: |
583 print('\n', file=stream) | 558 print >> stream, '\n' |
584 format_section(stream, section.upper(), options_by_section[section], | 559 format_section(stream, section.upper(), options_by_section[section], |
585 encoding) | 560 encoding) |
586 printed = True | 561 printed = True |
587 | 562 |
588 def generate_manpage(self, pkginfo, section=1, stream=None): | 563 def generate_manpage(self, pkginfo, section=1, stream=None): |
589 """write a man page for the current configuration into the given | 564 """write a man page for the current configuration into the given |
590 stream or stdout | 565 stream or stdout |
591 """ | 566 """ |
592 self._monkeypatch_expand_default() | 567 self._monkeypatch_expand_default() |
593 try: | 568 try: |
594 optik_ext.generate_manpage(self.cmdline_parser, pkginfo, | 569 optparse.generate_manpage(self.cmdline_parser, pkginfo, |
595 section, stream=stream or sys.stdout, | 570 section, stream=stream or sys.stdout, |
596 level=self._maxlevel) | 571 level=self._maxlevel) |
597 finally: | 572 finally: |
598 self._unmonkeypatch_expand_default() | 573 self._unmonkeypatch_expand_default() |
599 | 574 |
600 # initialization methods ################################################## | 575 # initialization methods ################################################## |
601 | 576 |
602 def load_provider_defaults(self): | 577 def load_provider_defaults(self): |
603 """initialize configuration using default values""" | 578 """initialize configuration using default values""" |
604 for provider in self.options_providers: | 579 for provider in self.options_providers: |
605 provider.load_defaults() | 580 provider.load_defaults() |
606 | 581 |
607 def load_file_configuration(self, config_file=None): | 582 def load_file_configuration(self, config_file=None): |
608 """load the configuration from file""" | 583 """load the configuration from file""" |
609 self.read_config_file(config_file) | 584 self.read_config_file(config_file) |
610 self.load_config_file() | 585 self.load_config_file() |
611 | 586 |
612 def read_config_file(self, config_file=None): | 587 def read_config_file(self, config_file=None): |
613 """read the configuration file but do not load it (i.e. dispatching | 588 """read the configuration file but do not load it (i.e. dispatching |
614 values to each options provider) | 589 values to each options provider) |
615 """ | 590 """ |
616 helplevel = 1 | 591 helplevel = 1 |
617 while helplevel <= self._maxlevel: | 592 while helplevel <= self._maxlevel: |
618 opt = '-'.join(['long'] * helplevel) + '-help' | 593 opt = '-'.join(['long'] * helplevel) + '-help' |
619 if opt in self._all_options: | 594 if opt in self._all_options: |
620 break # already processed | 595 break # already processed |
621 def helpfunc(option, opt, val, p, level=helplevel): | 596 def helpfunc(option, opt, val, p, level=helplevel): |
622 print(self.help(level)) | 597 print self.help(level) |
623 sys.exit(0) | 598 sys.exit(0) |
624 helpmsg = '%s verbose help.' % ' '.join(['more'] * helplevel) | 599 helpmsg = '%s verbose help.' % ' '.join(['more'] * helplevel) |
625 optdict = {'action' : 'callback', 'callback' : helpfunc, | 600 optdict = {'action' : 'callback', 'callback' : helpfunc, |
626 'help' : helpmsg} | 601 'help' : helpmsg} |
627 provider = self.options_providers[0] | 602 provider = self.options_providers[0] |
628 self.add_optik_option(provider, self.cmdline_parser, opt, optdict) | 603 self.add_optik_option(provider, self.cmdline_parser, opt, optdict) |
629 provider.options += ( (opt, optdict), ) | 604 provider.options += ( (opt, optdict), ) |
630 helplevel += 1 | 605 helplevel += 1 |
631 if config_file is None: | 606 if config_file is None: |
632 config_file = self.config_file | 607 config_file = self.config_file |
633 if config_file is not None: | 608 if config_file is not None: |
634 config_file = expanduser(config_file) | 609 config_file = expanduser(config_file) |
635 if config_file and exists(config_file): | 610 if config_file and exists(config_file): |
636 parser = self.cfgfile_parser | 611 parser = self.cfgfile_parser |
637 parser.read([config_file]) | 612 parser.read([config_file]) |
638 # normalize sections'title | 613 # normalize sections'title |
639 for sect, values in parser._sections.items(): | 614 for sect, values in parser._sections.items(): |
640 if not sect.isupper() and values: | 615 if not sect.isupper() and values: |
641 parser._sections[sect.upper()] = values | 616 parser._sections[sect.upper()] = values |
642 elif not self.quiet: | 617 elif not self.quiet: |
643 msg = 'No config file found, using default configuration' | 618 msg = 'No config file found, using default configuration' |
644 print(msg, file=sys.stderr) | 619 print >> sys.stderr, msg |
645 return | 620 return |
646 | 621 |
647 def input_config(self, onlysection=None, inputlevel=0, stream=None): | 622 def input_config(self, onlysection=None, inputlevel=0, stream=None): |
648 """interactively get configuration values by asking to the user and gene
rate | 623 """interactively get configuration values by asking to the user and gene
rate |
649 a configuration file | 624 a configuration file |
650 """ | 625 """ |
651 if onlysection is not None: | 626 if onlysection is not None: |
652 onlysection = onlysection.upper() | 627 onlysection = onlysection.upper() |
653 for provider in self.options_providers: | 628 for provider in self.options_providers: |
654 for section, option, optdict in provider.all_options(): | 629 for section, option, optdict in provider.all_options(): |
655 if onlysection is not None and section != onlysection: | 630 if onlysection is not None and section != onlysection: |
656 continue | 631 continue |
657 if not 'type' in optdict: | 632 if not 'type' in optdict: |
658 # ignore action without type (callback, store_true...) | 633 # ignore action without type (callback, store_true...) |
659 continue | 634 continue |
660 provider.input_option(option, optdict, inputlevel) | 635 provider.input_option(option, optdict, inputlevel) |
661 # now we can generate the configuration file | 636 # now we can generate the configuration file |
662 if stream is not None: | 637 if stream is not None: |
663 self.generate_config(stream) | 638 self.generate_config(stream) |
664 | 639 |
665 def load_config_file(self): | 640 def load_config_file(self): |
666 """dispatch values previously read from a configuration file to each | 641 """dispatch values previously read from a configuration file to each |
667 options provider) | 642 options provider) |
668 """ | 643 """ |
669 parser = self.cfgfile_parser | 644 parser = self.cfgfile_parser |
670 for section in parser.sections(): | 645 for provider in self.options_providers: |
671 for option, value in parser.items(section): | 646 for section, option, optdict in provider.all_options(): |
672 try: | 647 try: |
673 self.global_set_option(option, value) | 648 value = parser.get(section, option) |
674 except (KeyError, OptionError): | 649 provider.set_option(option, value, optdict=optdict) |
675 # TODO handle here undeclared options appearing in the co
nfig file | 650 except (NoSectionError, NoOptionError), ex: |
676 continue | 651 continue |
677 | 652 |
678 def load_configuration(self, **kwargs): | 653 def load_configuration(self, **kwargs): |
679 """override configuration according to given parameters | 654 """override configuration according to given parameters |
680 """ | 655 """ |
681 for opt, opt_value in kwargs.items(): | 656 for opt, opt_value in kwargs.items(): |
682 opt = opt.replace('_', '-') | 657 opt = opt.replace('_', '-') |
683 provider = self._all_options[opt] | 658 provider = self._all_options[opt] |
684 provider.set_option(opt, opt_value) | 659 provider.set_option(opt, opt_value) |
685 | 660 |
686 def load_command_line_configuration(self, args=None): | 661 def load_command_line_configuration(self, args=None): |
(...skipping 17 matching lines...) Expand all Loading... |
704 setattr(config, attr, value) | 679 setattr(config, attr, value) |
705 return args | 680 return args |
706 finally: | 681 finally: |
707 self._unmonkeypatch_expand_default() | 682 self._unmonkeypatch_expand_default() |
708 | 683 |
709 | 684 |
710 # help methods ############################################################ | 685 # help methods ############################################################ |
711 | 686 |
712 def add_help_section(self, title, description, level=0): | 687 def add_help_section(self, title, description, level=0): |
713 """add a dummy option section for help purpose """ | 688 """add a dummy option section for help purpose """ |
714 group = optik_ext.OptionGroup(self.cmdline_parser, | 689 group = optparse.OptionGroup(self.cmdline_parser, |
715 title=title.capitalize(), | 690 title=title.capitalize(), |
716 description=description) | 691 description=description) |
717 group.level = level | 692 group.level = level |
718 self._maxlevel = max(self._maxlevel, level) | 693 self._maxlevel = max(self._maxlevel, level) |
719 self.cmdline_parser.add_option_group(group) | 694 self.cmdline_parser.add_option_group(group) |
720 | 695 |
721 def _monkeypatch_expand_default(self): | 696 def _monkeypatch_expand_default(self): |
722 # monkey patch optik_ext to deal with our default values | 697 # monkey patch optparse to deal with our default values |
723 try: | 698 try: |
724 self.__expand_default_backup = optik_ext.HelpFormatter.expand_defaul
t | 699 self.__expand_default_backup = optparse.HelpFormatter.expand_default |
725 optik_ext.HelpFormatter.expand_default = expand_default | 700 optparse.HelpFormatter.expand_default = expand_default |
726 except AttributeError: | 701 except AttributeError: |
727 # python < 2.4: nothing to be done | 702 # python < 2.4: nothing to be done |
728 pass | 703 pass |
729 def _unmonkeypatch_expand_default(self): | 704 def _unmonkeypatch_expand_default(self): |
730 # remove monkey patch | 705 # remove monkey patch |
731 if hasattr(optik_ext.HelpFormatter, 'expand_default'): | 706 if hasattr(optparse.HelpFormatter, 'expand_default'): |
732 # unpatch optik_ext to avoid side effects | 707 # unpatch optparse to avoid side effects |
733 optik_ext.HelpFormatter.expand_default = self.__expand_default_backu
p | 708 optparse.HelpFormatter.expand_default = self.__expand_default_backup |
734 | 709 |
735 def help(self, level=0): | 710 def help(self, level=0): |
736 """return the usage string for available options """ | 711 """return the usage string for available options """ |
737 self.cmdline_parser.formatter.output_level = level | 712 self.cmdline_parser.formatter.output_level = level |
738 self._monkeypatch_expand_default() | 713 self._monkeypatch_expand_default() |
739 try: | 714 try: |
740 return self.cmdline_parser.format_help() | 715 return self.cmdline_parser.format_help() |
741 finally: | 716 finally: |
742 self._unmonkeypatch_expand_default() | 717 self._unmonkeypatch_expand_default() |
743 | 718 |
744 | 719 |
745 class Method(object): | 720 class Method(object): |
746 """used to ease late binding of default method (so you can define options | 721 """used to ease late binding of default method (so you can define options |
747 on the class using default methods on the configuration instance) | 722 on the class using default methods on the configuration instance) |
748 """ | 723 """ |
749 def __init__(self, methname): | 724 def __init__(self, methname): |
750 self.method = methname | 725 self.method = methname |
751 self._inst = None | 726 self._inst = None |
752 | 727 |
753 def bind(self, instance): | 728 def bind(self, instance): |
754 """bind the method to its instance""" | 729 """bind the method to its instance""" |
755 if self._inst is None: | 730 if self._inst is None: |
756 self._inst = instance | 731 self._inst = instance |
757 | 732 |
758 def __call__(self, *args, **kwargs): | 733 def __call__(self, *args, **kwargs): |
759 assert self._inst, 'unbound method' | 734 assert self._inst, 'unbound method' |
760 return getattr(self._inst, self.method)(*args, **kwargs) | 735 return getattr(self._inst, self.method)(*args, **kwargs) |
761 | 736 |
762 # Options Provider ############################################################# | |
763 | 737 |
764 class OptionsProviderMixIn(object): | 738 class OptionsProviderMixIn(object): |
765 """Mixin to provide options to an OptionsManager""" | 739 """Mixin to provide options to an OptionsManager""" |
766 | 740 |
767 # those attributes should be overridden | 741 # those attributes should be overridden |
768 priority = -1 | 742 priority = -1 |
769 name = 'default' | 743 name = 'default' |
770 options = () | 744 options = () |
771 level = 0 | 745 level = 0 |
772 | 746 |
773 def __init__(self): | 747 def __init__(self): |
774 self.config = optik_ext.Values() | 748 self.config = optparse.Values() |
775 for option in self.options: | 749 for option in self.options: |
776 try: | 750 try: |
777 option, optdict = option | 751 option, optdict = option |
778 except ValueError: | 752 except ValueError: |
779 raise Exception('Bad option: %r' % option) | 753 raise Exception('Bad option: %r' % option) |
780 if isinstance(optdict.get('default'), Method): | 754 if isinstance(optdict.get('default'), Method): |
781 optdict['default'].bind(self) | 755 optdict['default'].bind(self) |
782 elif isinstance(optdict.get('callback'), Method): | 756 elif isinstance(optdict.get('callback'), Method): |
783 optdict['callback'].bind(self) | 757 optdict['callback'].bind(self) |
784 self.load_defaults() | 758 self.load_defaults() |
(...skipping 11 matching lines...) Expand all Loading... |
796 | 770 |
797 def option_default(self, opt, optdict=None): | 771 def option_default(self, opt, optdict=None): |
798 """return the default value for an option""" | 772 """return the default value for an option""" |
799 if optdict is None: | 773 if optdict is None: |
800 optdict = self.get_option_def(opt) | 774 optdict = self.get_option_def(opt) |
801 default = optdict.get('default') | 775 default = optdict.get('default') |
802 if callable(default): | 776 if callable(default): |
803 default = default() | 777 default = default() |
804 return default | 778 return default |
805 | 779 |
806 def option_attrname(self, opt, optdict=None): | 780 def option_name(self, opt, optdict=None): |
807 """get the config attribute corresponding to opt | 781 """get the config attribute corresponding to opt |
808 """ | 782 """ |
809 if optdict is None: | 783 if optdict is None: |
810 optdict = self.get_option_def(opt) | 784 optdict = self.get_option_def(opt) |
811 return optdict.get('dest', opt.replace('-', '_')) | 785 return optdict.get('dest', opt.replace('-', '_')) |
812 option_name = deprecated('[0.60] OptionsProviderMixIn.option_name() was rena
med to option_attrname()')(option_attrname) | |
813 | 786 |
814 def option_value(self, opt): | 787 def option_value(self, opt): |
815 """get the current value for the given option""" | 788 """get the current value for the given option""" |
816 return getattr(self.config, self.option_attrname(opt), None) | 789 return getattr(self.config, self.option_name(opt), None) |
817 | 790 |
818 def set_option(self, opt, value, action=None, optdict=None): | 791 def set_option(self, opt, value, action=None, optdict=None): |
819 """method called to set an option (registered in the options list) | 792 """method called to set an option (registered in the options list) |
820 """ | 793 """ |
| 794 # print "************ setting option", opt," to value", value |
821 if optdict is None: | 795 if optdict is None: |
822 optdict = self.get_option_def(opt) | 796 optdict = self.get_option_def(opt) |
823 if value is not None: | 797 if value is not None: |
824 value = _validate(value, optdict, opt) | 798 value = convert(value, optdict, opt) |
825 if action is None: | 799 if action is None: |
826 action = optdict.get('action', 'store') | 800 action = optdict.get('action', 'store') |
827 if optdict.get('type') == 'named': # XXX need specific handling | 801 if optdict.get('type') == 'named': # XXX need specific handling |
828 optname = self.option_attrname(opt, optdict) | 802 optname = self.option_name(opt, optdict) |
829 currentvalue = getattr(self.config, optname, None) | 803 currentvalue = getattr(self.config, optname, None) |
830 if currentvalue: | 804 if currentvalue: |
831 currentvalue.update(value) | 805 currentvalue.update(value) |
832 value = currentvalue | 806 value = currentvalue |
833 if action == 'store': | 807 if action == 'store': |
834 setattr(self.config, self.option_attrname(opt, optdict), value) | 808 setattr(self.config, self.option_name(opt, optdict), value) |
835 elif action in ('store_true', 'count'): | 809 elif action in ('store_true', 'count'): |
836 setattr(self.config, self.option_attrname(opt, optdict), 0) | 810 setattr(self.config, self.option_name(opt, optdict), 0) |
837 elif action == 'store_false': | 811 elif action == 'store_false': |
838 setattr(self.config, self.option_attrname(opt, optdict), 1) | 812 setattr(self.config, self.option_name(opt, optdict), 1) |
839 elif action == 'append': | 813 elif action == 'append': |
840 opt = self.option_attrname(opt, optdict) | 814 opt = self.option_name(opt, optdict) |
841 _list = getattr(self.config, opt, None) | 815 _list = getattr(self.config, opt, None) |
842 if _list is None: | 816 if _list is None: |
843 if isinstance(value, (list, tuple)): | 817 if isinstance(value, (list, tuple)): |
844 _list = value | 818 _list = value |
845 elif value is not None: | 819 elif value is not None: |
846 _list = [] | 820 _list = [] |
847 _list.append(value) | 821 _list.append(value) |
848 setattr(self.config, opt, _list) | 822 setattr(self.config, opt, _list) |
849 elif isinstance(_list, tuple): | 823 elif isinstance(_list, tuple): |
850 setattr(self.config, opt, _list + (value,)) | 824 setattr(self.config, opt, _list + (value,)) |
851 else: | 825 else: |
852 _list.append(value) | 826 _list.append(value) |
853 elif action == 'callback': | 827 elif action == 'callback': |
854 optdict['callback'](None, opt, value, None) | 828 optdict['callback'](None, opt, value, None) |
855 else: | 829 else: |
856 raise UnsupportedAction(action) | 830 raise UnsupportedAction(action) |
857 | 831 |
858 def input_option(self, option, optdict, inputlevel=99): | 832 def input_option(self, option, optdict, inputlevel=99): |
859 default = self.option_default(option, optdict) | 833 default = self.option_default(option, optdict) |
860 if default is REQUIRED: | 834 if default is REQUIRED: |
861 defaultstr = '(required): ' | 835 defaultstr = '(required): ' |
862 elif optdict.get('level', 0) > inputlevel: | 836 elif optdict.get('level', 0) > inputlevel: |
863 return | 837 return |
864 elif optdict['type'] == 'password' or default is None: | 838 elif optdict['type'] == 'password' or default is None: |
865 defaultstr = ': ' | 839 defaultstr = ': ' |
866 else: | 840 else: |
867 defaultstr = '(default: %s): ' % format_option_value(optdict, defaul
t) | 841 defaultstr = '(default: %s): ' % format_option_value(optdict, defaul
t) |
868 print(':%s:' % option) | 842 print ':%s:' % option |
869 print(optdict.get('help') or option) | 843 print optdict.get('help') or option |
870 inputfunc = INPUT_FUNCTIONS[optdict['type']] | 844 inputfunc = INPUT_FUNCTIONS[optdict['type']] |
871 value = inputfunc(optdict, defaultstr) | 845 value = inputfunc(optdict, defaultstr) |
872 while default is REQUIRED and not value: | 846 while default is REQUIRED and not value: |
873 print('please specify a value') | 847 print 'please specify a value' |
874 value = inputfunc(optdict, '%s: ' % option) | 848 value = inputfunc(optdict, '%s: ' % option) |
875 if value is None and default is not None: | 849 if value is None and default is not None: |
876 value = default | 850 value = default |
877 self.set_option(option, value, optdict=optdict) | 851 self.set_option(option, value, optdict=optdict) |
878 | 852 |
879 def get_option_def(self, opt): | 853 def get_option_def(self, opt): |
880 """return the dictionary defining an option given it's name""" | 854 """return the dictionary defining an option given it's name""" |
881 assert self.options | 855 assert self.options |
882 for option in self.options: | 856 for option in self.options: |
883 if option[0] == opt: | 857 if option[0] == opt: |
(...skipping 28 matching lines...) Expand all Loading... |
912 yield None, sections.pop(None) | 886 yield None, sections.pop(None) |
913 for section, options in sections.items(): | 887 for section, options in sections.items(): |
914 yield section.upper(), options | 888 yield section.upper(), options |
915 | 889 |
916 def options_and_values(self, options=None): | 890 def options_and_values(self, options=None): |
917 if options is None: | 891 if options is None: |
918 options = self.options | 892 options = self.options |
919 for optname, optdict in options: | 893 for optname, optdict in options: |
920 yield (optname, optdict, self.option_value(optname)) | 894 yield (optname, optdict, self.option_value(optname)) |
921 | 895 |
922 # configuration ################################################################ | |
923 | 896 |
924 class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): | 897 class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): |
925 """basic mixin for simple configurations which don't need the | 898 """basic mixin for simple configurations which don't need the |
926 manager / providers model | 899 manager / providers model |
927 """ | 900 """ |
928 def __init__(self, *args, **kwargs): | 901 def __init__(self, *args, **kwargs): |
929 if not args: | 902 if not args: |
930 kwargs.setdefault('usage', '') | 903 kwargs.setdefault('usage', '') |
931 kwargs.setdefault('quiet', 1) | 904 kwargs.setdefault('quiet', 1) |
932 OptionsManagerMixIn.__init__(self, *args, **kwargs) | 905 OptionsManagerMixIn.__init__(self, *args, **kwargs) |
933 OptionsProviderMixIn.__init__(self) | 906 OptionsProviderMixIn.__init__(self) |
934 if not getattr(self, 'option_groups', None): | 907 if not getattr(self, 'option_groups', None): |
935 self.option_groups = [] | 908 self.option_groups = [] |
936 for option, optdict in self.options: | 909 for option, optdict in self.options: |
937 try: | 910 try: |
938 gdef = (optdict['group'].upper(), '') | 911 gdef = (optdict['group'].upper(), '') |
939 except KeyError: | 912 except KeyError: |
940 continue | 913 continue |
941 if not gdef in self.option_groups: | 914 if not gdef in self.option_groups: |
942 self.option_groups.append(gdef) | 915 self.option_groups.append(gdef) |
943 self.register_options_provider(self, own_group=False) | 916 self.register_options_provider(self, own_group=0) |
944 | 917 |
945 def register_options(self, options): | 918 def register_options(self, options): |
946 """add some options to the configuration""" | 919 """add some options to the configuration""" |
947 options_by_group = {} | 920 options_by_group = {} |
948 for optname, optdict in options: | 921 for optname, optdict in options: |
949 options_by_group.setdefault(optdict.get('group', self.name.upper()),
[]).append((optname, optdict)) | 922 options_by_group.setdefault(optdict.get('group', self.name.upper()),
[]).append((optname, optdict)) |
950 for group, options in options_by_group.items(): | 923 for group, options in options_by_group.items(): |
951 self.add_option_group(group, None, options, self) | 924 self.add_option_group(group, None, options, self) |
952 self.options += tuple(options) | 925 self.options += tuple(options) |
953 | 926 |
954 def load_defaults(self): | 927 def load_defaults(self): |
955 OptionsProviderMixIn.load_defaults(self) | 928 OptionsProviderMixIn.load_defaults(self) |
956 | 929 |
957 def __iter__(self): | 930 def __iter__(self): |
958 return iter(self.config.__dict__.iteritems()) | 931 return iter(self.config.__dict__.iteritems()) |
959 | 932 |
960 def __getitem__(self, key): | 933 def __getitem__(self, key): |
961 try: | 934 try: |
962 return getattr(self.config, self.option_attrname(key)) | 935 return getattr(self.config, self.option_name(key)) |
963 except (optik_ext.OptionValueError, AttributeError): | 936 except (optparse.OptionValueError, AttributeError): |
964 raise KeyError(key) | 937 raise KeyError(key) |
965 | 938 |
966 def __setitem__(self, key, value): | 939 def __setitem__(self, key, value): |
967 self.set_option(key, value) | 940 self.set_option(key, value) |
968 | 941 |
969 def get(self, key, default=None): | 942 def get(self, key, default=None): |
970 try: | 943 try: |
971 return getattr(self.config, self.option_attrname(key)) | 944 return getattr(self.config, self.option_name(key)) |
972 except (OptionError, AttributeError): | 945 except (OptionError, AttributeError): |
973 return default | 946 return default |
974 | 947 |
975 | 948 |
976 class Configuration(ConfigurationMixIn): | 949 class Configuration(ConfigurationMixIn): |
977 """class for simple configurations which don't need the | 950 """class for simple configurations which don't need the |
978 manager / providers model and prefer delegation to inheritance | 951 manager / providers model and prefer delegation to inheritance |
979 | 952 |
980 configuration values are accessible through a dict like interface | 953 configuration values are accessible through a dict like interface |
981 """ | 954 """ |
(...skipping 15 matching lines...) Expand all Loading... |
997 """ | 970 """ |
998 def __init__(self, provider): | 971 def __init__(self, provider): |
999 self.config = provider | 972 self.config = provider |
1000 | 973 |
1001 def __getattr__(self, key): | 974 def __getattr__(self, key): |
1002 return getattr(self.config, key) | 975 return getattr(self.config, key) |
1003 | 976 |
1004 def __getitem__(self, key): | 977 def __getitem__(self, key): |
1005 provider = self.config._all_options[key] | 978 provider = self.config._all_options[key] |
1006 try: | 979 try: |
1007 return getattr(provider.config, provider.option_attrname(key)) | 980 return getattr(provider.config, provider.option_name(key)) |
1008 except AttributeError: | 981 except AttributeError: |
1009 raise KeyError(key) | 982 raise KeyError(key) |
1010 | 983 |
1011 def __setitem__(self, key, value): | 984 def __setitem__(self, key, value): |
1012 self.config.global_set_option(self.config.option_attrname(key), value) | 985 self.config.global_set_option(self.config.option_name(key), value) |
1013 | 986 |
1014 def get(self, key, default=None): | 987 def get(self, key, default=None): |
1015 provider = self.config._all_options[key] | 988 provider = self.config._all_options[key] |
1016 try: | 989 try: |
1017 return getattr(provider.config, provider.option_attrname(key)) | 990 return getattr(provider.config, provider.option_name(key)) |
1018 except AttributeError: | 991 except AttributeError: |
1019 return default | 992 return default |
1020 | 993 |
1021 # other functions ############################################################## | |
1022 | 994 |
1023 def read_old_config(newconfig, changes, configfile): | 995 def read_old_config(newconfig, changes, configfile): |
1024 """initialize newconfig from a deprecated configuration file | 996 """initialize newconfig from a deprecated configuration file |
1025 | 997 |
1026 possible changes: | 998 possible changes: |
1027 * ('renamed', oldname, newname) | 999 * ('renamed', oldname, newname) |
1028 * ('moved', option, oldgroup, newgroup) | 1000 * ('moved', option, oldgroup, newgroup) |
1029 * ('typechanged', option, oldtype, newvalue) | 1001 * ('typechanged', option, oldtype, newvalue) |
1030 """ | 1002 """ |
1031 # build an index of changes | 1003 # build an index of changes |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 done.add(newname) | 1048 done.add(newname) |
1077 elif action[0] == 'typechanged': | 1049 elif action[0] == 'typechanged': |
1078 optname, oldtype, newvalue = action[1:] | 1050 optname, oldtype, newvalue = action[1:] |
1079 newconfig[optname] = newvalue | 1051 newconfig[optname] = newvalue |
1080 done.add(optname) | 1052 done.add(optname) |
1081 for optname, optdef in newconfig.options: | 1053 for optname, optdef in newconfig.options: |
1082 if optdef.get('type') and not optname in done: | 1054 if optdef.get('type') and not optname in done: |
1083 newconfig.set_option(optname, oldconfig[optname], optdict=optdef) | 1055 newconfig.set_option(optname, oldconfig[optname], optdict=optdef) |
1084 | 1056 |
1085 | 1057 |
1086 def merge_options(options, optgroup=None): | 1058 def merge_options(options): |
1087 """preprocess a list of options and remove duplicates, returning a new list | 1059 """preprocess options to remove duplicate""" |
1088 (tuple actually) of options. | |
1089 | |
1090 Options dictionaries are copied to avoid later side-effect. Also, if | |
1091 `otpgroup` argument is specified, ensure all options are in the given group. | |
1092 """ | |
1093 alloptions = {} | 1060 alloptions = {} |
1094 options = list(options) | 1061 options = list(options) |
1095 for i in range(len(options)-1, -1, -1): | 1062 for i in range(len(options)-1, -1, -1): |
1096 optname, optdict = options[i] | 1063 optname, optdict = options[i] |
1097 if optname in alloptions: | 1064 if optname in alloptions: |
1098 options.pop(i) | 1065 options.pop(i) |
1099 alloptions[optname].update(optdict) | 1066 alloptions[optname].update(optdict) |
1100 else: | 1067 else: |
1101 optdict = optdict.copy() | |
1102 options[i] = (optname, optdict) | |
1103 alloptions[optname] = optdict | 1068 alloptions[optname] = optdict |
1104 if optgroup is not None: | |
1105 alloptions[optname]['group'] = optgroup | |
1106 return tuple(options) | 1069 return tuple(options) |
OLD | NEW |