Esempio n. 1
0
 def reset_parsers(self, usage='', version=None):
     # configuration file parser
     self._config_parser = ConfigParser()
     # command line parser
     self._optik_parser = OptionParser(usage=usage, version=version)
     self._optik_parser.options_manager = self
Esempio n. 2
0
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)
        # list of registered options providers
        self.options_providers = []
        # dictionary assocating option name to checker
        self._all_options = {}
        self._short_options = {}
        self._nocallback_options = {}
        # verbosity
        self.quiet = quiet

    def reset_parsers(self, usage='', version=None):
        # configuration file parser
        self._config_parser = ConfigParser()
        # 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"
        for i in range(len(self.options_providers)):
            if provider.priority > self.options_providers[i].priority:
                self.options_providers.insert(i, provider)
                break
        else:
            self.options_providers.append(provider)
        non_group_spec_options = [option for option in provider.options
                                  if not option[1].has_key('group')]
        groups = getattr(provider, 'option_groups', ())
        if own_group:
            self.add_option_group(provider.name.upper(), provider.__doc__,
                                  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)
                self._optik_parser.add_option(*args, **opt_dict)
                self._all_options[opt_name] = provider                
        for gname, gdoc in groups:
            goptions = [option for option in provider.options
                        if option[1].get('group') == 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
        """
        # add section to the config file
        self._config_parser.add_section(group_name)
        # add option group to the command line parser
        if options:
            group = OptionGroup(self._optik_parser,
                                title=group_name.capitalize())
            self._optik_parser.add_option_group(group)
        # add provider's specific options
        for opt_name, opt_dict in options:
            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
        """
        opt_dict = copy(opt_dict)
        if opt_dict.has_key('action'):
            self._nocallback_options[provider] = opt_name
        else:
            opt_dict['action'] = 'callback'
            opt_dict['callback'] = self.cb_set_provider_option
        for specific in ('default', 'group', 'inputlevel'):
            if opt_dict.has_key(specific):
                del opt_dict[specific]
                if (OPTPARSE_FORMAT_DEFAULT
                    and specific == 'default' and opt_dict.has_key('help')):
                    opt_dict['help'] += ' [current: %default]'
        args = ['--' + opt_name]
        if opt_dict.has_key('short'):
            self._short_options[opt_dict['short']] = opt_name
            args.append('-' + opt_dict['short'])
            del opt_dict['short']
        available_keys = set(self._optik_parser.option_class.ATTRS)
        for key in opt_dict.keys():
            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('--'):
            # remove -- on long option
            opt_name = opt_name[2:]
        else:
            # short option, get its long equivalent
            opt_name = self._short_options[opt_name[1:]]
        # trick since we can't set action='store_true' on options
        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)

    def generate_config(self, stream=None, skipsections=()):
        """write a configuration file according to the current configuration
        into the given stream or stdout
        """
        stream = stream or sys.stdout
        printed = False
        for provider in self.options_providers:
            default_options = []
            sections = {}
            for section, options in provider.options_by_section():
                if section in skipsections:
                    continue
                options = [(n, d, v) for (n, d, v) in options
                           if d.get('type') is not None]
                if not options:
                    continue
                if section is None:
                    section = provider.name
                    doc = provider.__doc__
                else:
                    doc = None
                if printed:
                    print >> stream, '\n'
                format_section(stream, section.upper(), options, doc)
                printed = True

    def generate_manpage(self, pkginfo, section=1, stream=None):
        """write a man page for the current configuration into the given
        stream or stdout
        """
        generate_manpage(self._optik_parser, pkginfo,
                         section, stream=stream or sys.stdout)
        
    # 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)
        """
        if config_file is None:
            config_file = self.config_file
        if config_file and exists(config_file):
            self._config_parser.read([config_file])
        elif not self.quiet:
            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
        """
        if onlysection is not None:
            onlysection = onlysection.upper()
        for provider in self.options_providers:
            for section, option, optdict in provider.all_options():
                if onlysection is not None and section != onlysection:
                    continue
                provider.input_option(option, optdict, inputlevel)
        # now we can generate the configuration file
        if stream is not None:
            self.generate_config(stream)

    def load_config_file(self):
        """dispatch values previously read from a configuration file to each
        options provider)
        """
        parser = self._config_parser        
        for provider in self.options_providers:
            for section, option, optdict in provider.all_options():
                try:
                    value = parser.get(section, option)
                    provider.set_option(option, value, opt_dict=optdict)
                except (NoSectionError, NoOptionError), ex:
                    continue