"""Combined argparse and ConfigParser."""

import argparse
from configparser import ConfigParser
from typing import NoReturn, List, Union

class UsageError(RuntimeError):
    pass

class ConfigError(RuntimeError):
    pass

class ConfigArgumentParser(argparse.ArgumentParser):

    def error(self, message: str) -> NoReturn:
        raise UsageError(message)

    def configure_defaults(
            self, config: ConfigParser,
            defaults_section: Union[List[str], str, None]) -> None:
        """Merge those configurations files in the list `config_paths` which
        exist and return the corresponding `ConfigParser` object.  Later files
        take presedence over former.  Variables from `defaults_section` will be
        used as defaults for the argument parser options."""

        if not defaults_section:
            defaults_section = []
        elif not isinstance(defaults_section, list):
            defaults_section = [defaults_section]
        for section in defaults_section:
            if config.has_section(section):
                defaults = [(var, config.get(section, var))
                            for var in config.options(section)]
                self.set_defaults(**dict(defaults))
                break

        # TODO: Validation can be refined. Ideally we should check each config
        # variable individually and report a) the variable name rather than
        # the option name and b) the line number of the bad value.
        try:
            self.parse_args()
        except argparse.ArgumentTypeError as exn:
            raise ConfigError(
                    'The configuration corresponding to a command-line '
                    'option failed: %s' % exn) from exn
