diff options
| author | Ian Cordasco <graffatcolmingov@gmail.com> | 2016-06-28 09:36:24 -0500 |
|---|---|---|
| committer | Ian Cordasco <graffatcolmingov@gmail.com> | 2016-06-28 09:36:24 -0500 |
| commit | 2d3e277b1e0c0a24c30c611558692f95d14a8470 (patch) | |
| tree | dc011a113fc68de72189478d727fd3851af7290c /src/flake8 | |
| parent | ec2e601cbf9a56c9bee2ee3cc22999c795c1c824 (diff) | |
| download | flake8-2d3e277b1e0c0a24c30c611558692f95d14a8470.tar.gz | |
Handle optional parameters that were never supported
Previously, pycodestyle never introspected the argument names for
classes except to require that ``tree`` be an argument it could pass.
For Flake8 3.0, we lifted that restriction, but old plugins seem to
have cargo-culted their __init__ signature to be
def __init__(self, tree, builtins=None):
For some yet unknown reason. This was causing an AttributeError. By
updating flake8.utils.parameters_for to return a dictionary that
indicates whether the parameter is required or not, we can side-step
this by simply ignoring the parameter if it has a default value and
we cannot provide it.
Closes #151
Diffstat (limited to 'src/flake8')
| -rw-r--r-- | src/flake8/plugins/manager.py | 10 | ||||
| -rw-r--r-- | src/flake8/processor.py | 11 | ||||
| -rw-r--r-- | src/flake8/utils.py | 23 |
3 files changed, 32 insertions, 12 deletions
diff --git a/src/flake8/plugins/manager.py b/src/flake8/plugins/manager.py index 697b35f..5d9e52b 100644 --- a/src/flake8/plugins/manager.py +++ b/src/flake8/plugins/manager.py @@ -38,6 +38,7 @@ class Plugin(object): self.entry_point = entry_point self._plugin = None self._parameters = None + self._parameter_names = None self._group = None self._plugin_name = None self._version = None @@ -78,6 +79,13 @@ class Plugin(object): return self._parameters @property + def parameter_names(self): + """List of argument names that need to be passed to the plugin.""" + if self._parameter_names is None: + self._parameter_names = list(self.parameters) + return self._parameter_names + + @property def plugin(self): """The loaded (and cached) plugin associated with the entry-point. @@ -416,7 +424,7 @@ class Checkers(PluginTypeManager): Find all checker plugins that are expecting a specific argument. """ for plugin in self.plugins.values(): - if argument_name == plugin.parameters[0]: + if argument_name == plugin.parameter_names[0]: yield plugin def register_options(self, optmanager): diff --git a/src/flake8/processor.py b/src/flake8/processor.py index 0c33cc2..1824ed1 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -206,14 +206,19 @@ class FileProcessor(object): """Generate the keyword arguments for a list of parameters.""" if arguments is None: arguments = {} - for param in parameters: + for param, required in parameters.items(): if param in arguments: continue try: arguments[param] = getattr(self, param) except AttributeError as exc: - LOG.exception(exc) - raise + if required: + LOG.exception(exc) + raise + else: + LOG.warning('Plugin requested optional parameter "%s" ' + 'but this is not an available parameter.', + param) return arguments def check_physical_error(self, error_code, line): diff --git a/src/flake8/utils.py b/src/flake8/utils.py index 9f1189c..fbd15b9 100644 --- a/src/flake8/utils.py +++ b/src/flake8/utils.py @@ -249,7 +249,7 @@ def fnmatch(filename, patterns, default=True): def parameters_for(plugin): - # type: (flake8.plugins.manager.Plugin) -> List[str] + # type: (flake8.plugins.manager.Plugin) -> Dict[str, bool] """Return the parameters for the plugin. This will inspect the plugin and return either the function parameters @@ -261,9 +261,10 @@ def parameters_for(plugin): :type plugin: flake8.plugins.manager.Plugin :returns: - Parameters to the plugin. + A dictionary mapping the parameter name to whether or not it is + required (a.k.a., is positional only/does not have a default). :rtype: - list(str) + dict([(str, bool)]) """ func = plugin.plugin is_class = not inspect.isfunction(func) @@ -271,15 +272,21 @@ def parameters_for(plugin): func = plugin.plugin.__init__ if sys.version_info < (3, 3): - parameters = inspect.getargspec(func)[0] + argspec = inspect.getargspec(func) + start_of_optional_args = len(argspec[0]) - len(argspec[-1] or []) + parameter_names = argspec[0] + parameters = collections.OrderedDict([ + (name, position < start_of_optional_args) + for position, name in enumerate(parameter_names) + ]) else: - parameters = [ - parameter.name + parameters = collections.OrderedDict([ + (parameter.name, parameter.default is parameter.empty) for parameter in inspect.signature(func).parameters.values() if parameter.kind == parameter.POSITIONAL_OR_KEYWORD - ] + ]) if is_class: - parameters.remove('self') + parameters.pop('self', None) return parameters |
