# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""utilities for Pylint configuration :

* pylintrc
* pylint.d (PYLINTHOME)
"""
from __future__ import print_function

# TODO(cpopa): this module contains the logic for the
# configuration parser and for the command line parser,
# but it's really coupled to optparse's internals.
# The code was copied almost verbatim from logilab.common,
# in order to not depend on it anymore and it will definitely
# need a cleanup. It could be completely reengineered as well.

import contextlib
import collections
import copy
import io
import optparse
import os
import pickle
import re
import sys
import time

from six.moves import configparser
from six.moves import range

from pylint import utils


USER_HOME = os.path.expanduser('~')
if 'PYLINTHOME' in os.environ:
    PYLINT_HOME = os.environ['PYLINTHOME']
    if USER_HOME == '~':
        USER_HOME = os.path.dirname(PYLINT_HOME)
elif USER_HOME == '~':
    PYLINT_HOME = ".pylint.d"
else:
    PYLINT_HOME = os.path.join(USER_HOME, '.pylint.d')


def _get_pdata_path(base_name, recurs):
    base_name = base_name.replace(os.sep, '_')
    return os.path.join(PYLINT_HOME, "%s%s%s"%(base_name, recurs, '.stats'))


def load_results(base):
    data_file = _get_pdata_path(base, 1)
    try:
        with open(data_file, _PICK_LOAD) as stream:
            return pickle.load(stream)
    except Exception: # pylint: disable=broad-except
        return {}

if sys.version_info < (3, 0):
    _PICK_DUMP, _PICK_LOAD = 'w', 'r'
else:
    _PICK_DUMP, _PICK_LOAD = 'wb', 'rb'

def save_results(results, base):
    if not os.path.exists(PYLINT_HOME):
        try:
            os.mkdir(PYLINT_HOME)
        except OSError:
            print('Unable to create directory %s' % PYLINT_HOME, file=sys.stderr)
    data_file = _get_pdata_path(base, 1)
    try:
        with open(data_file, _PICK_DUMP) as stream:
            pickle.dump(results, stream)
    except (IOError, OSError) as ex:
        print('Unable to create file %s: %s' % (data_file, ex), file=sys.stderr)


def find_pylintrc():
    """search the pylint rc file and return its path if it find it, else None
    """
    # is there a pylint rc file in the current directory ?
    if os.path.exists('pylintrc'):
        return os.path.abspath('pylintrc')
    if os.path.exists('.pylintrc'):
        return os.path.abspath('.pylintrc')
    if os.path.isfile('__init__.py'):
        curdir = os.path.abspath(os.getcwd())
        while os.path.isfile(os.path.join(curdir, '__init__.py')):
            curdir = os.path.abspath(os.path.join(curdir, '..'))
            if os.path.isfile(os.path.join(curdir, 'pylintrc')):
                return os.path.join(curdir, 'pylintrc')
            if os.path.isfile(os.path.join(curdir, '.pylintrc')):
                return os.path.join(curdir, '.pylintrc')
    if 'PYLINTRC' in os.environ and os.path.exists(os.environ['PYLINTRC']):
        pylintrc = os.environ['PYLINTRC']
    else:
        user_home = os.path.expanduser('~')
        if user_home == '~' or user_home == '/root':
            pylintrc = ".pylintrc"
        else:
            pylintrc = os.path.join(user_home, '.pylintrc')
            if not os.path.isfile(pylintrc):
                pylintrc = os.path.join(user_home, '.config', 'pylintrc')
    if not os.path.isfile(pylintrc):
        if os.path.isfile('/etc/pylintrc'):
            pylintrc = '/etc/pylintrc'
        else:
            pylintrc = None
    return pylintrc

PYLINTRC = find_pylintrc()

ENV_HELP = '''
The following environment variables are used:
    * PYLINTHOME
    Path to the directory where the persistent for the run will be stored. If
not found, it defaults to ~/.pylint.d/ or .pylint.d (in the current working
directory).
    * PYLINTRC
    Path to the configuration file. See the documentation for the method used
to search for configuration file.
''' % globals()


class UnsupportedAction(Exception):
    """raised by set_option when it doesn't know what to do for an action"""


def _multiple_choice_validator(choices, name, value):
    values = utils._check_csv(value)
    for value in values:
        if value not in choices:
            msg = "option %s: invalid value: %r, should be in %s"
            raise optparse.OptionValueError(msg % (name, value, choices))
    return values


def _choice_validator(choices, name, value):
    if value not in choices:
        msg = "option %s: invalid value: %r, should be in %s"
        raise optparse.OptionValueError(msg % (name, value, choices))
    return value

# pylint: disable=unused-argument
def _csv_validator(_, name, value):
    return utils._check_csv(value)


# pylint: disable=unused-argument
def _regexp_validator(_, name, value):
    if hasattr(value, 'pattern'):
        return value
    return re.compile(value)


def _yn_validator(opt, _, value):
    if isinstance(value, int):
        return bool(value)
    if value in ('y', 'yes'):
        return True
    if value in ('n', 'no'):
        return False
    msg = "option %s: invalid yn value %r, should be in (y, yes, n, no)"
    raise optparse.OptionValueError(msg % (opt, value))


VALIDATORS = {
    'string': utils._unquote,
    'int': int,
    'regexp': re.compile,
    'csv': _csv_validator,
    'yn': _yn_validator,
    'choice': lambda opt, name, value: _choice_validator(opt['choices'], name, value),
    'multiple_choice': lambda opt, name, value: _multiple_choice_validator(opt['choices'],
                                                                           name, value),
}

def _call_validator(opttype, optdict, option, value):
    if opttype not in VALIDATORS:
        raise Exception('Unsupported type "%s"' % opttype)
    try:
        return VALIDATORS[opttype](optdict, option, value)
    except TypeError:
        try:
            return VALIDATORS[opttype](value)
        except Exception:
            raise optparse.OptionValueError('%s value (%r) should be of type %s' %
                                            (option, value, opttype))


def _validate(value, optdict, name=''):
    """return a validated value for an option according to its type

    optional argument name is only used for error message formatting
    """
    try:
        _type = optdict['type']
    except KeyError:
        # FIXME
        return value
    return _call_validator(_type, optdict, name, value)


def _level_options(group, outputlevel):
    return [option for option in group.option_list
            if (getattr(option, 'level', 0) or 0) <= outputlevel
            and option.help is not optparse.SUPPRESS_HELP]


def _expand_default(self, option):
    """Patch OptionParser.expand_default with custom behaviour

    This will handle defaults to avoid overriding values in the
    configuration file.
    """
    if self.parser is None or not self.default_tag:
        return option.help
    optname = option._long_opts[0][2:]
    try:
        provider = self.parser.options_manager._all_options[optname]
    except KeyError:
        value = None
    else:
        optdict = provider.get_option_def(optname)
        optname = provider.option_attrname(optname, optdict)
        value = getattr(provider.config, optname, optdict)
        value = utils._format_option_value(optdict, value)
    if value is optparse.NO_DEFAULT or not value:
        value = self.NO_DEFAULT_VALUE
    return option.help.replace(self.default_tag, str(value))


@contextlib.contextmanager
def _patch_optparse():
    orig_default = optparse.HelpFormatter
    try:
        optparse.HelpFormatter.expand_default = _expand_default
        yield
    finally:
        optparse.HelpFormatter.expand_default = orig_default


def _multiple_choices_validating_option(opt, name, value):
    return _multiple_choice_validator(opt.choices, name, value)


class Option(optparse.Option):
    TYPES = optparse.Option.TYPES + ('regexp', 'csv', 'yn', 'multiple_choice')
    ATTRS = optparse.Option.ATTRS + ['hide', 'level']
    TYPE_CHECKER = copy.copy(optparse.Option.TYPE_CHECKER)
    TYPE_CHECKER['regexp'] = _regexp_validator
    TYPE_CHECKER['csv'] = _csv_validator
    TYPE_CHECKER['yn'] = _yn_validator
    TYPE_CHECKER['multiple_choice'] = _multiple_choices_validating_option

    def __init__(self, *opts, **attrs):
        optparse.Option.__init__(self, *opts, **attrs)
        if hasattr(self, "hide") and self.hide:
            self.help = optparse.SUPPRESS_HELP

    def _check_choice(self):
        if self.type in ("choice", "multiple_choice"):
            if self.choices is None:
                raise optparse.OptionError(
                    "must supply a list of choices for type 'choice'", self)
            elif not isinstance(self.choices, (tuple, list)):
                raise optparse.OptionError(
                    "choices must be a list of strings ('%s' supplied)"
                    % str(type(self.choices)).split("'")[1], self)
        elif self.choices is not None:
            raise optparse.OptionError(
                "must not supply choices for type %r" % self.type, self)
    optparse.Option.CHECK_METHODS[2] = _check_choice

    def process(self, opt, value, values, parser):
        # First, convert the value(s) to the right type.  Howl if any
        # value(s) are bogus.
        value = self.convert_value(opt, value)
        if self.type == 'named':
            existant = getattr(values, self.dest)
            if existant:
                existant.update(value)
                value = existant
        # And then take whatever action is expected of us.
        # This is a separate method to make life easier for
        # subclasses to add new actions.
        return self.take_action(
            self.action, self.dest, opt, value, values, parser)


class OptionParser(optparse.OptionParser):

    def __init__(self, option_class=Option, *args, **kwargs):
        optparse.OptionParser.__init__(self, option_class=Option, *args, **kwargs)

    def format_option_help(self, formatter=None):
        if formatter is None:
            formatter = self.formatter
        outputlevel = getattr(formatter, 'output_level', 0)
        formatter.store_option_strings(self)
        result = []
        result.append(formatter.format_heading("Options"))
        formatter.indent()
        if self.option_list:
            result.append(optparse.OptionContainer.format_option_help(self, formatter))
            result.append("\n")
        for group in self.option_groups:
            if group.level <= outputlevel and (
                    group.description or _level_options(group, outputlevel)):
                result.append(group.format_help(formatter))
                result.append("\n")
        formatter.dedent()
        # Drop the last "\n", or the header if no options or option groups:
        return "".join(result[:-1])

    def _match_long_opt(self, opt):
        """Disable abbreviations."""
        if opt not in self._long_opt:
            raise optparse.BadOptionError(opt)
        return opt


# pylint: disable=abstract-method; by design?
class _ManHelpFormatter(optparse.HelpFormatter):

    def __init__(self, indent_increment=0, max_help_position=24,
                 width=79, short_first=0):
        optparse.HelpFormatter.__init__(
            self, indent_increment, max_help_position, width, short_first)

    def format_heading(self, heading):
        return '.SH %s\n' % heading.upper()

    def format_description(self, description):
        return description

    def format_option(self, option):
        try:
            optstring = option.option_strings
        except AttributeError:
            optstring = self.format_option_strings(option)
        if option.help:
            help_text = self.expand_default(option)
            help = ' '.join([l.strip() for l in help_text.splitlines()])
        else:
            help = ''
        return '''.IP "%s"
%s
''' % (optstring, help)

    def format_head(self, optparser, pkginfo, section=1):
        long_desc = ""
        try:
            pgm = optparser._get_prog_name()
        except AttributeError:
            # py >= 2.4.X (dunno which X exactly, at least 2)
            pgm = optparser.get_prog_name()
        short_desc = self.format_short_description(pgm, pkginfo.description)
        if hasattr(pkginfo, "long_desc"):
            long_desc = self.format_long_description(pgm, pkginfo.long_desc)
        return '%s\n%s\n%s\n%s' % (self.format_title(pgm, section),
                                   short_desc, self.format_synopsis(pgm),
                                   long_desc)

    @staticmethod
    def format_title(pgm, section):
        date = '-'.join(str(num) for num in time.localtime()[:3])
        return '.TH %s %s "%s" %s' % (pgm, section, date, pgm)

    @staticmethod
    def format_short_description(pgm, short_desc):
        return '''.SH NAME
.B %s
\- %s
''' % (pgm, short_desc.strip())

    @staticmethod
    def format_synopsis(pgm):
        return '''.SH SYNOPSIS
.B  %s
[
.I OPTIONS
] [
.I <arguments>
]
''' % pgm

    @staticmethod
    def format_long_description(pgm, long_desc):
        long_desc = '\n'.join(line.lstrip()
                              for line in long_desc.splitlines())
        long_desc = long_desc.replace('\n.\n', '\n\n')
        if long_desc.lower().startswith(pgm):
            long_desc = long_desc[len(pgm):]
        return '''.SH DESCRIPTION
.B %s
%s
''' % (pgm, long_desc.strip())

    @staticmethod
    def format_tail(pkginfo):
        tail = '''.SH SEE ALSO
/usr/share/doc/pythonX.Y-%s/

.SH BUGS
Please report bugs on the project\'s mailing list:
%s

.SH AUTHOR
%s <%s>
''' % (getattr(pkginfo, 'debian_name', pkginfo.modname),
       pkginfo.mailinglist, pkginfo.author, pkginfo.author_email)

        if hasattr(pkginfo, "copyright"):
            tail += '''
.SH COPYRIGHT
%s
''' % pkginfo.copyright

        return tail


class OptionsManagerMixIn(object):
    """Handle 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 associating option name to checker
        self._all_options = collections.OrderedDict()
        self._short_options = {}
        self._nocallback_options = {}
        self._mygroups = {}
        # verbosity
        self.quiet = quiet
        self._maxlevel = 0

    def reset_parsers(self, usage='', version=None):
        # configuration file parser
        self.cfgfile_parser = configparser.ConfigParser()
        # command line parser
        self.cmdline_parser = OptionParser(usage=usage, version=version)
        self.cmdline_parser.options_manager = self
        self._optik_option_attrs = set(self.cmdline_parser.option_class.ATTRS)

    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 'group' not in option[1]]
        groups = getattr(provider, 'option_groups', ())
        if own_group and non_group_spec_options:
            self.add_option_group(provider.name.upper(), provider.__doc__,
                                  non_group_spec_options, provider)
        else:
            for opt, optdict in non_group_spec_options:
                self.add_optik_option(provider, self.cmdline_parser, opt, optdict)
        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, _, options, provider):
        # add option group to the command line parser
        if group_name in self._mygroups:
            group = self._mygroups[group_name]
        else:
            group = optparse.OptionGroup(self.cmdline_parser,
                                         title=group_name.capitalize())
            self.cmdline_parser.add_option_group(group)
            group.level = provider.level
            self._mygroups[group_name] = group
            # add section to the config file
            if group_name != "DEFAULT":
                self.cfgfile_parser.add_section(group_name)
        # add provider's specific options
        for opt, optdict in options:
            self.add_optik_option(provider, group, opt, optdict)

    def add_optik_option(self, provider, optikcontainer, opt, optdict):
        args, optdict = self.optik_option(provider, opt, optdict)
        option = optikcontainer.add_option(*args, **optdict)
        self._all_options[opt] = provider
        self._maxlevel = max(self._maxlevel, option.level or 0)

    def optik_option(self, provider, opt, optdict):
        """get our personal option definition and return a suitable form for
        use with optik/optparse
        """
        optdict = copy.copy(optdict)
        if 'action' in optdict:
            self._nocallback_options[provider] = opt
        else:
            optdict['action'] = 'callback'
            optdict['callback'] = self.cb_set_provider_option
        # default is handled here and *must not* be given to optik if you
        # want the whole machinery to work
        if 'default' in optdict:
            if ('help' in optdict
                    and optdict.get('default') is not None
                    and optdict['action'] not in ('store_true', 'store_false')):
                optdict['help'] += ' [current: %default]'
            del optdict['default']
        args = ['--' + str(opt)]
        if 'short' in optdict:
            self._short_options[optdict['short']] = opt
            args.append('-' + optdict['short'])
            del optdict['short']
        # cleanup option definition dict before giving it to optik
        for key in list(optdict.keys()):
            if key not in self._optik_option_attrs:
                optdict.pop(key)
        return args, optdict

    def cb_set_provider_option(self, option, opt, value, parser):
        """optik callback for option setting"""
        if opt.startswith('--'):
            # remove -- on long option
            opt = opt[2:]
        else:
            # short option, get its long equivalent
            opt = self._short_options[opt[1:]]
        # trick since we can't set action='store_true' on options
        if value is None:
            value = 1
        self.global_set_option(opt, value)

    def global_set_option(self, opt, value):
        """set option on the correct option provider"""
        self._all_options[opt].set_option(opt, value)

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

    def generate_manpage(self, pkginfo, section=1, stream=None):
        with _patch_optparse():
            _generate_manpage(self.cmdline_parser, pkginfo,
                              section, stream=stream or sys.stdout,
                              level=self._maxlevel)

    def load_provider_defaults(self):
        """initialize configuration using default values"""
        for provider in self.options_providers:
            provider.load_defaults()

    def read_config_file(self, config_file=None):
        """read the configuration file but do not load it (i.e. dispatching
        values to each options provider)
        """
        helplevel = 1
        while helplevel <= self._maxlevel:
            opt = '-'.join(['long'] * helplevel) + '-help'
            if opt in self._all_options:
                break # already processed
            # pylint: disable=unused-argument
            def helpfunc(option, opt, val, p, level=helplevel):
                print(self.help(level))
                sys.exit(0)
            helpmsg = '%s verbose help.' % ' '.join(['more'] * helplevel)
            optdict = {'action': 'callback', 'callback': helpfunc,
                       'help': helpmsg}
            provider = self.options_providers[0]
            self.add_optik_option(provider, self.cmdline_parser, opt, optdict)
            provider.options += ((opt, optdict),)
            helplevel += 1
        if config_file is None:
            config_file = self.config_file
        if config_file is not None:
            config_file = os.path.expanduser(config_file)
        if config_file and os.path.exists(config_file):
            parser = self.cfgfile_parser

            # Use this encoding in order to strip the BOM marker, if any.
            with io.open(config_file, 'r', encoding='utf_8_sig') as fp:
                # pylint: disable=deprecated-method
                parser.readfp(fp)

            # normalize sections'title
            for sect, values in list(parser._sections.items()):
                if not sect.isupper() and values:
                    parser._sections[sect.upper()] = values
        elif not self.quiet:
            msg = 'No config file found, using default configuration'
            print(msg, file=sys.stderr)
            return

    def load_config_file(self):
        """dispatch values previously read from a configuration file to each
        options provider)
        """
        parser = self.cfgfile_parser
        for section in parser.sections():
            for option, value in parser.items(section):
                try:
                    self.global_set_option(option, value)
                except (KeyError, optparse.OptionError):
                    # TODO handle here undeclared options appearing in the config file
                    continue

    def load_configuration(self, **kwargs):
        """override configuration according to given parameters"""
        return self.load_configuration_from_config(kwargs)

    def load_configuration_from_config(self, config):
        for opt, opt_value in config.items():
            opt = opt.replace('_', '-')
            provider = self._all_options[opt]
            provider.set_option(opt, opt_value)

    def load_command_line_configuration(self, args=None):
        """Override configuration according to command line parameters

        return additional arguments
        """
        with _patch_optparse():
            if args is None:
                args = sys.argv[1:]
            else:
                args = list(args)
            (options, args) = self.cmdline_parser.parse_args(args=args)
            for provider in self._nocallback_options.keys():
                config = provider.config
                for attr in config.__dict__.keys():
                    value = getattr(options, attr, None)
                    if value is None:
                        continue
                    setattr(config, attr, value)
            return args

    def add_help_section(self, title, description, level=0):
        """add a dummy option section for help purpose """
        group = optparse.OptionGroup(self.cmdline_parser,
                                     title=title.capitalize(),
                                     description=description)
        group.level = level
        self._maxlevel = max(self._maxlevel, level)
        self.cmdline_parser.add_option_group(group)

    def help(self, level=0):
        """return the usage string for available options """
        self.cmdline_parser.formatter.output_level = level
        with _patch_optparse():
            return self.cmdline_parser.format_help()


class OptionsProviderMixIn(object):
    """Mixin to provide options to an OptionsManager"""

    # those attributes should be overridden
    priority = -1
    name = 'default'
    options = ()
    level = 0

    def __init__(self):
        self.config = optparse.Values()
        self.load_defaults()

    def load_defaults(self):
        """initialize the provider using default values"""
        for opt, optdict in self.options:
            action = optdict.get('action')
            if action != 'callback':
                # callback action have no default
                if optdict is None:
                    optdict = self.get_option_def(opt)
                default = optdict.get('default')
                self.set_option(opt, default, action, optdict)

    def option_attrname(self, opt, optdict=None):
        """get the config attribute corresponding to opt"""
        if optdict is None:
            optdict = self.get_option_def(opt)
        return optdict.get('dest', opt.replace('-', '_'))

    def option_value(self, opt):
        """get the current value for the given option"""
        return getattr(self.config, self.option_attrname(opt), None)

    def set_option(self, opt, value, action=None, optdict=None):
        """method called to set an option (registered in the options list)"""
        if optdict is None:
            optdict = self.get_option_def(opt)
        if value is not None:
            value = _validate(value, optdict, opt)
        if action is None:
            action = optdict.get('action', 'store')
        if action == 'store':
            setattr(self.config, self.option_attrname(opt, optdict), value)
        elif action in ('store_true', 'count'):
            setattr(self.config, self.option_attrname(opt, optdict), 0)
        elif action == 'store_false':
            setattr(self.config, self.option_attrname(opt, optdict), 1)
        elif action == 'append':
            opt = self.option_attrname(opt, optdict)
            _list = getattr(self.config, opt, None)
            if _list is None:
                if isinstance(value, (list, tuple)):
                    _list = value
                elif value is not None:
                    _list = []
                    _list.append(value)
                setattr(self.config, opt, _list)
            elif isinstance(_list, tuple):
                setattr(self.config, opt, _list + (value,))
            else:
                _list.append(value)
        elif action == 'callback':
            optdict['callback'](None, opt, value, None)
        else:
            raise UnsupportedAction(action)

    def get_option_def(self, opt):
        """return the dictionary defining an option given its name"""
        assert self.options
        for option in self.options:
            if option[0] == opt:
                return option[1]
        raise optparse.OptionError('no such option %s in section %r'
                                   % (opt, self.name), opt)

    def options_by_section(self):
        """return an iterator on options grouped by section

        (section, [list of (optname, optdict, optvalue)])
        """
        sections = {}
        for optname, optdict in self.options:
            sections.setdefault(optdict.get('group'), []).append(
                (optname, optdict, self.option_value(optname)))
        if None in sections:
            yield None, sections.pop(None)
        for section, options in sorted(sections.items()):
            yield section.upper(), options

    def options_and_values(self, options=None):
        if options is None:
            options = self.options
        for optname, optdict in options:
            yield (optname, optdict, self.option_value(optname))


class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn):
    """basic mixin for simple configurations which don't need the
    manager / providers model
    """
    def __init__(self, *args, **kwargs):
        if not args:
            kwargs.setdefault('usage', '')
        kwargs.setdefault('quiet', 1)
        OptionsManagerMixIn.__init__(self, *args, **kwargs)
        OptionsProviderMixIn.__init__(self)
        if not getattr(self, 'option_groups', None):
            self.option_groups = []
            for _, optdict in self.options:
                try:
                    gdef = (optdict['group'].upper(), '')
                except KeyError:
                    continue
                if gdef not in self.option_groups:
                    self.option_groups.append(gdef)
        self.register_options_provider(self, own_group=False)


def _generate_manpage(optparser, pkginfo, section=1,
                      stream=sys.stdout, level=0):
    formatter = _ManHelpFormatter()
    formatter.output_level = level
    formatter.parser = optparser
    print(formatter.format_head(optparser, pkginfo, section), file=stream)
    print(optparser.format_option_help(formatter), file=stream)
    print(formatter.format_tail(pkginfo), file=stream)
