diff options
| author | Carl Meyer <carl@oddbird.net> | 2017-08-03 00:25:37 -0700 |
|---|---|---|
| committer | Carl Meyer <carl@oddbird.net> | 2017-08-03 00:25:37 -0700 |
| commit | 4e58068657ece52e3f1636cb028e42c15b86fec3 (patch) | |
| tree | c739fe9428a1a3f46d836773e243cdcdb22ddb27 /src/flake8/options | |
| parent | 6df26ffd57178e50194aea31b3bf9c572f91fa54 (diff) | |
| download | flake8-4e58068657ece52e3f1636cb028e42c15b86fec3.tar.gz | |
Add support for local (in-repo, non-setuptools) plugins.
Closes #357
Diffstat (limited to 'src/flake8/options')
| -rw-r--r-- | src/flake8/options/aggregator.py | 13 | ||||
| -rw-r--r-- | src/flake8/options/config.py | 99 |
2 files changed, 81 insertions, 31 deletions
diff --git a/src/flake8/options/aggregator.py b/src/flake8/options/aggregator.py index 4075dc9..5b8ab9c 100644 --- a/src/flake8/options/aggregator.py +++ b/src/flake8/options/aggregator.py @@ -5,17 +5,18 @@ applies the user-specified command-line configuration on top of it. """ import logging -from flake8 import utils from flake8.options import config LOG = logging.getLogger(__name__) -def aggregate_options(manager, arglist=None, values=None): +def aggregate_options(manager, config_finder, arglist=None, values=None): """Aggregate and merge CLI and config file options. - :param flake8.option.manager.OptionManager manager: + :param flake8.options.manager.OptionManager manager: The instance of the OptionManager that we're presently using. + :param flake8.options.config.ConfigFileFinder config_finder: + The config file finder to use. :param list arglist: The list of arguments to pass to ``manager.parse_args``. In most cases this will be None so ``parse_args`` uses ``sys.argv``. This is mostly @@ -32,14 +33,12 @@ def aggregate_options(manager, arglist=None, values=None): default_values, _ = manager.parse_args([], values=values) # Get original CLI values so we can find additional config file paths and # see if --config was specified. - original_values, original_args = manager.parse_args(arglist) - extra_config_files = utils.normalize_paths(original_values.append_config) + original_values, _ = manager.parse_args(arglist) # Make our new configuration file mergerator config_parser = config.MergedConfigParser( option_manager=manager, - extra_config_files=extra_config_files, - args=original_args, + config_finder=config_finder, ) # Get the parsed config diff --git a/src/flake8/options/config.py b/src/flake8/options/config.py index a6ac63f..251697a 100644 --- a/src/flake8/options/config.py +++ b/src/flake8/options/config.py @@ -1,4 +1,5 @@ """Config handling logic for Flake8.""" +import collections import configparser import logging import os.path @@ -49,6 +50,11 @@ class ConfigFileFinder(object): args = ['.'] self.parent = self.tail = os.path.abspath(os.path.commonprefix(args)) + # caches to avoid double-reading config files + self._local_configs = None + self._user_config = None + self._cli_configs = {} + @staticmethod def _read_config(files): config = configparser.RawConfigParser() @@ -63,10 +69,12 @@ class ConfigFileFinder(object): def cli_config(self, files): """Read and parse the config file specified on the command-line.""" - config, found_files = self._read_config(files) - if found_files: - LOG.debug('Found cli configuration files: %s', found_files) - return config + if files not in self._cli_configs: + config, found_files = self._read_config(files) + if found_files: + LOG.debug('Found cli configuration files: %s', found_files) + self._cli_configs[files] = config + return self._cli_configs[files] def generate_possible_local_files(self): """Find and generate all local config files.""" @@ -104,10 +112,12 @@ class ConfigFileFinder(object): def local_configs(self): """Parse all local config files into one config object.""" - config, found_files = self._read_config(self.local_config_files()) - if found_files: - LOG.debug('Found local configuration files: %s', found_files) - return config + if self._local_configs is None: + config, found_files = self._read_config(self.local_config_files()) + if found_files: + LOG.debug('Found local configuration files: %s', found_files) + self._local_configs = config + return self._local_configs def user_config_file(self): """Find the user-level config file.""" @@ -117,10 +127,12 @@ class ConfigFileFinder(object): def user_config(self): """Parse the user config file into a config object.""" - config, found_files = self._read_config(self.user_config_file()) - if found_files: - LOG.debug('Found user configuration files: %s', found_files) - return config + if self._user_config is None: + config, found_files = self._read_config(self.user_config_file()) + if found_files: + LOG.debug('Found user configuration files: %s', found_files) + self._user_config = config + return self._user_config class MergedConfigParser(object): @@ -138,30 +150,23 @@ class MergedConfigParser(object): #: :meth:`~configparser.RawConfigParser.getbool` method. GETBOOL_ACTIONS = {'store_true', 'store_false'} - def __init__(self, option_manager, extra_config_files=None, args=None): + def __init__(self, option_manager, config_finder): """Initialize the MergedConfigParser instance. - :param flake8.option.manager.OptionManager option_manager: + :param flake8.options.manager.OptionManager option_manager: Initialized OptionManager. - :param list extra_config_files: - List of extra config files to parse. - :params list args: - The extra parsed arguments from the command-line. + :param flake8.options.config.ConfigFileFinder config_finder: + Initialized ConfigFileFinder. """ #: Our instance of flake8.options.manager.OptionManager self.option_manager = option_manager #: The prog value for the cli parser self.program_name = option_manager.program_name - #: Parsed extra arguments - self.args = args #: Mapping of configuration option names to #: :class:`~flake8.options.manager.Option` instances self.config_options = option_manager.config_options_dict - #: List of extra config files - self.extra_config_files = extra_config_files or [] #: Our instance of our :class:`~ConfigFileFinder` - self.config_finder = ConfigFileFinder(self.program_name, self.args, - self.extra_config_files) + self.config_finder = config_finder def _normalize_value(self, option, value): final_value = option.normalize( @@ -280,3 +285,49 @@ class MergedConfigParser(object): return self.parse_cli_config(cli_config) return self.merge_user_and_local_config() + + +def get_local_plugins(config_finder, cli_config=None, isolated=False): + """Get local plugins lists from config files. + + :param flake8.options.config.ConfigFileFinder config_finder: + The config file finder to use. + :param str cli_config: + Value of --config when specified at the command-line. Overrides + all other config files. + :param bool isolated: + Determines if we should parse configuration files at all or not. + If running in isolated mode, we ignore all configuration files + :returns: + LocalPlugins namedtuple containing two lists of plugin strings, + one for extension (checker) plugins and one for report plugins. + :rtype: + flake8.options.config.LocalPlugins + """ + local_plugins = LocalPlugins(extension=[], report=[]) + if isolated: + LOG.debug('Refusing to look for local plugins in configuration' + 'files due to user-requested isolation') + return local_plugins + + if cli_config: + LOG.debug('Reading local plugins only from "%s" specified via ' + '--config by the user', cli_config) + configs = [config_finder.cli_config(cli_config)] + else: + configs = [ + config_finder.user_config(), + config_finder.local_configs(), + ] + + section = '%s:local-plugins' % config_finder.program_name + for config in configs: + for plugin_type in ['extension', 'report']: + if config.has_option(section, plugin_type): + getattr(local_plugins, plugin_type).extend( + config.get(section, plugin_type).strip().splitlines() + ) + return local_plugins + + +LocalPlugins = collections.namedtuple('LocalPlugins', 'extension report') |
