summaryrefslogtreecommitdiff
path: root/configuration.py
diff options
context:
space:
mode:
authorSylvain Th?nault <sylvain.thenault@logilab.fr>2009-06-10 18:45:42 +0200
committerSylvain Th?nault <sylvain.thenault@logilab.fr>2009-06-10 18:45:42 +0200
commit078ff12bec0fb5c79f2cabb6672bc5032d69297d (patch)
tree36b4f20878786d2f7984b8b3e833dea7862cc821 /configuration.py
parent5d8f38cb9491365af78dfbecabc1853075430603 (diff)
downloadlogilab-common-078ff12bec0fb5c79f2cabb6672bc5032d69297d.tar.gz
d-t-w
Diffstat (limited to 'configuration.py')
-rw-r--r--configuration.py110
1 files changed, 55 insertions, 55 deletions
diff --git a/configuration.py b/configuration.py
index 4876aef..d29d591 100644
--- a/configuration.py
+++ b/configuration.py
@@ -32,15 +32,15 @@ Quick start: simplest usage
2
>>> print config.help()
Usage: [options]
-
+
Options:
-h, --help show this help message and exit
- --dothis=<y or n>
- --value=<string>
+ --dothis=<y or n>
+ --value=<string>
--multiple=<comma separated values>
you can also document the option [current: none]
- --number=<int>
-
+ --number=<int>
+
>>> f = open('myconfig.ini', 'w')
>>> f.write('''[MY CONFIG]
... number = 3
@@ -66,18 +66,18 @@ Quick start: simplest usage
>>> config.generate_config()
# class for simple configurations which don't need the
# manager / providers model and prefer delegation to inheritance
- #
+ #
# configuration values are accessible through a dict like interface
- #
+ #
[MY CONFIG]
-
+
dothis=no
-
+
value=bacon
-
+
# you can also document the option
multiple=4,5,6
-
+
number=3
>>>
@@ -86,7 +86,7 @@ Quick start: simplest usage
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: General Public License version 2 - http://www.gnu.org/licenses
"""
-from __future__ import generators
+from __future__ import generators
__docformat__ = "restructuredtext en"
__all__ = ('OptionsManagerMixIn', 'OptionsProviderMixIn',
@@ -245,7 +245,7 @@ INPUT_FUNCTIONS = {
for opttype in VALIDATORS.keys():
INPUT_FUNCTIONS.setdefault(opttype, _make_input_function(opttype))
-
+
def expand_default(self, option):
"""monkey patch OptionParser.expand_default since we have a particular
way to handle defaults to avoid overriding values in the configuration
@@ -267,10 +267,10 @@ def expand_default(self, option):
value = self.NO_DEFAULT_VALUE
return option.help.replace(self.default_tag, str(value))
-
+
def convert(value, opt_dict, name=''):
"""return a validated value for an option according to its type
-
+
optional argument name is only used for error message formatting
"""
try:
@@ -290,7 +290,7 @@ def format_option_value(optdict, value):
if isinstance(value, (list, tuple)):
value = ','.join(value)
elif isinstance(value, dict):
- value = ','.join(['%s:%s' % (k,v) for k,v in value.items()])
+ value = ','.join(['%s:%s' % (k,v) for k,v in value.items()])
elif hasattr(value, 'match'): # optdict.get('type') == 'regexp'
# compiled regexp
value = value.pattern
@@ -320,7 +320,7 @@ def ini_format_section(stream, section, options, encoding=None, doc=None):
else:
value = _encode(value, encoding).strip()
print >> stream, '%s=%s' % (optname, value)
-
+
format_section = ini_format_section
def rest_format_section(stream, section, options, encoding=None, doc=None):
@@ -348,7 +348,7 @@ class OptionsManagerMixIn(object):
"""MixIn to handle a configuration from both a configuration file and
command line options
"""
-
+
def __init__(self, usage, config_file=None, version=None, quiet=0):
self.config_file = config_file
self.reset_parsers(usage, version=version)
@@ -367,7 +367,7 @@ class OptionsManagerMixIn(object):
# command line parser
self._optik_parser = OptionParser(usage=usage, version=version)
self._optik_parser.options_manager = self
-
+
def register_options_provider(self, provider, own_group=True):
"""register an options provider"""
assert provider.priority <= 0, "provider's priority can't be >= 0"
@@ -385,16 +385,16 @@ class OptionsManagerMixIn(object):
non_group_spec_options, provider)
else:
for opt_name, opt_dict in non_group_spec_options:
- args, opt_dict = self.optik_option(provider, opt_name, opt_dict)
+ args, opt_dict = self.optik_option(provider, opt_name, opt_dict)
self._optik_parser.add_option(*args, **opt_dict)
-
+
self._all_options[opt_name] = provider
for gname, gdoc in groups:
gname = gname.upper()
goptions = [option for option in provider.options
if option[1].get('group', '').upper() == gname]
self.add_option_group(gname, gdoc, goptions, provider)
-
+
def add_option_group(self, group_name, doc, options, provider):
"""add an option group including the listed options
"""
@@ -411,7 +411,7 @@ class OptionsManagerMixIn(object):
args, opt_dict = self.optik_option(provider, opt_name, opt_dict)
group.add_option(*args, **opt_dict)
self._all_options[opt_name] = provider
-
+
def optik_option(self, provider, opt_name, opt_dict):
"""get our personal option definition and return a suitable form for
use with optik/optparse
@@ -441,7 +441,7 @@ class OptionsManagerMixIn(object):
if not key in available_keys:
opt_dict.pop(key)
return args, opt_dict
-
+
def cb_set_provider_option(self, option, opt_name, value, parser):
"""optik callback for option setting"""
if opt_name.startswith('--'):
@@ -454,7 +454,7 @@ class OptionsManagerMixIn(object):
if value is None:
value = 1
self.global_set_option(opt_name, value)
-
+
def global_set_option(self, opt_name, value):
"""set option on the correct option provider"""
self._all_options[opt_name].set_option(opt_name, value)
@@ -496,19 +496,19 @@ class OptionsManagerMixIn(object):
section, stream=stream or sys.stdout)
finally:
self._unmonkeypatch_expand_default()
-
+
# initialization methods ##################################################
def load_provider_defaults(self):
"""initialize configuration using default values"""
for provider in self.options_providers:
provider.load_defaults()
-
+
def load_file_configuration(self, config_file=None):
"""load the configuration from file"""
self.read_config_file(config_file)
self.load_config_file()
-
+
def read_config_file(self, config_file=None):
"""read the configuration file but do not load it (ie dispatching
values to each options provider)
@@ -528,7 +528,7 @@ class OptionsManagerMixIn(object):
msg = 'No config file found, using default configuration'
print >> sys.stderr, msg
return
-
+
def input_config(self, onlysection=None, inputlevel=0, stream=None):
"""interactivly get configuration values by asking to the user and generate
a configuration file
@@ -548,7 +548,7 @@ class OptionsManagerMixIn(object):
"""dispatch values previously read from a configuration file to each
options provider)
"""
- parser = self._config_parser
+ parser = self._config_parser
for provider in self.options_providers:
for section, option, optdict in provider.all_options():
try:
@@ -564,7 +564,7 @@ class OptionsManagerMixIn(object):
opt_name = opt_name.replace('_', '-')
provider = self._all_options[opt_name]
provider.set_option(opt_name, opt_value)
-
+
def load_command_line_configuration(self, args=None):
"""override configuration according to command line parameters
@@ -611,15 +611,15 @@ class OptionsManagerMixIn(object):
if hasattr(HelpFormatter, 'expand_default'):
# unpatch optparse to avoid side effects
HelpFormatter.expand_default = self.__expand_default_backup
-
+
def help(self):
- """return the usage string for available options """
+ """return the usage string for available options """
self._monkeypatch_expand_default()
try:
return self._optik_parser.format_help()
finally:
self._unmonkeypatch_expand_default()
-
+
class Method(object):
"""used to ease late binding of default method (so you can define options
@@ -628,12 +628,12 @@ class Method(object):
def __init__(self, methname):
self.method = methname
self._inst = None
-
+
def bind(self, instance):
"""bind the method to its instance"""
if self._inst is None:
self._inst = instance
-
+
def __call__(self):
assert self._inst, 'unbound method'
return getattr(self._inst, self.method)()
@@ -641,7 +641,7 @@ class Method(object):
class OptionsProviderMixIn(object):
"""Mixin to provide options to an OptionsManager"""
-
+
# those attributes should be overridden
priority = -1
name = 'default'
@@ -657,7 +657,7 @@ class OptionsProviderMixIn(object):
if isinstance(optdict.get('default'), Method):
optdict['default'].bind(self)
self.load_defaults()
-
+
def load_defaults(self):
"""initialize the provider using default values"""
for opt_name, opt_dict in self.options:
@@ -677,18 +677,18 @@ class OptionsProviderMixIn(object):
if callable(default):
default = default()
return default
-
+
def option_name(self, opt_name, opt_dict=None):
"""get the config attribute corresponding to opt_name
"""
if opt_dict is None:
opt_dict = self.get_option_def(opt_name)
return opt_dict.get('dest', opt_name.replace('-', '_'))
-
+
def option_value(self, opt_name):
"""get the current value for the given option"""
return getattr(self.config, self.option_name(opt_name), None)
-
+
def set_option(self, opt_name, value, action=None, opt_dict=None):
"""method called to set an option (registered in the options list)
"""
@@ -751,7 +751,7 @@ class OptionsProviderMixIn(object):
if value is None and default is not None:
value = default
self.set_option(option, value, opt_dict=optdict)
-
+
def get_option_def(self, opt_name):
"""return the dictionary defining an option given it's name"""
assert self.options
@@ -765,16 +765,16 @@ class OptionsProviderMixIn(object):
"""return an iterator on available options for this provider
option are actually described by a 3-uple:
(section, option name, option dictionary)
- """
+ """
for section, options in self.options_by_section():
if section is None:
section = self.name.upper()
for option, optiondict, value in options:
yield section, option, optiondict
-
+
def options_by_section(self):
"""return an iterator on options grouped by section
-
+
(section, [list of (optname, optdict, optvalue)])
"""
sections = {}
@@ -785,7 +785,7 @@ class OptionsProviderMixIn(object):
yield None, sections.pop(None)
for section, options in sections.items():
yield section.upper(), options
-
+
class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn):
"""basic mixin for simple configurations which don't need the
@@ -816,13 +816,13 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn):
for group, options in options_by_group.items():
self.add_option_group(group, None, options, self)
self.options += tuple(options)
-
+
def load_defaults(self):
OptionsProviderMixIn.load_defaults(self)
def __iter__(self):
return iter(self.config.__dict__.iteritems())
-
+
def __getitem__(self, key):
try:
return getattr(self.config, self.option_name(key))
@@ -831,13 +831,13 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn):
def __setitem__(self, key, value):
self.set_option(self.option_name(key), value)
-
+
def get(self, key, default=None):
try:
return getattr(self.config, self.option_name(key))
except (OptionError, AttributeError):
return default
-
+
class Configuration(ConfigurationMixIn):
"""class for simple configurations which don't need the
@@ -863,10 +863,10 @@ class OptionsManager2ConfigurationAdapter(object):
"""
def __init__(self, provider):
self.config = provider
-
+
def __getattr__(self, key):
return getattr(self.config, key)
-
+
def __getitem__(self, key):
provider = self.config._all_options[key]
try:
@@ -887,7 +887,7 @@ class OptionsManager2ConfigurationAdapter(object):
def read_old_config(newconfig, changes, configfile):
"""initialize newconfig from a deprecated configuration file
-
+
possible changes:
* ('renamed', oldname, newname)
* ('moved', option, oldgroup, newgroup)
@@ -907,10 +907,10 @@ def read_old_config(newconfig, changes, configfile):
if action[0] == 'typechanged':
option, oldtype, newvalue = action[1:]
changesindex.setdefault(option, []).append((action[0], oldtype, newvalue))
- continue
+ continue
if action[1] in ('added', 'removed'):
continue # nothing to do here
- raise Exception('unknown change %s' % action[0])
+ raise Exception('unknown change %s' % action[0])
# build a config object able to read the old config
options = []
for optname, optdef in newconfig.options: