mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-14 08:24:46 +00:00
Make plugin and version loading lazy
Abstract plugin type management into one class and provide specific classes for each of our known types of plugins
This commit is contained in:
parent
1870811137
commit
f1010b7733
1 changed files with 72 additions and 29 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
"""Plugin loading and management logic and classes."""
|
"""Plugin loading and management logic and classes."""
|
||||||
|
import collections
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
|
@ -21,13 +22,22 @@ class Plugin(object):
|
||||||
"""
|
"""
|
||||||
self.name = name
|
self.name = name
|
||||||
self.entry_point = entry_point
|
self.entry_point = entry_point
|
||||||
self.plugin = None
|
self._plugin = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Plugin(name="{0}", entry_point="{1}")'.format(
|
return 'Plugin(name="{0}", entry_point="{1}")'.format(
|
||||||
self.name, self.entry_point
|
self.name, self.entry_point
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def plugin(self):
|
||||||
|
self.load_plugin()
|
||||||
|
return self._plugin
|
||||||
|
|
||||||
|
@property
|
||||||
|
def version(self):
|
||||||
|
return self.plugin.version
|
||||||
|
|
||||||
def execute(self, *args, **kwargs):
|
def execute(self, *args, **kwargs):
|
||||||
r"""Call the plugin with \*args and \*\*kwargs."""
|
r"""Call the plugin with \*args and \*\*kwargs."""
|
||||||
return self.plugin(*args, **kwargs)
|
return self.plugin(*args, **kwargs)
|
||||||
|
|
@ -45,7 +55,22 @@ class Plugin(object):
|
||||||
:returns:
|
:returns:
|
||||||
The plugin resolved from the entry-point.
|
The plugin resolved from the entry-point.
|
||||||
"""
|
"""
|
||||||
if self.plugin is None:
|
return self.plugin
|
||||||
|
|
||||||
|
def load_plugin(self, verify_requirements=False):
|
||||||
|
"""Retrieve the plugin for this entry-point.
|
||||||
|
|
||||||
|
This loads the plugin, stores it on the instance and then returns it.
|
||||||
|
It does not reload it after the first time, it merely returns the
|
||||||
|
cached plugin.
|
||||||
|
|
||||||
|
:param bool verify_requirements:
|
||||||
|
Whether or not to make setuptools verify that the requirements for
|
||||||
|
the plugin are satisfied.
|
||||||
|
:returns:
|
||||||
|
Nothing
|
||||||
|
"""
|
||||||
|
if self._plugin is None:
|
||||||
LOG.debug('Loading plugin "%s" from entry-point.', self.name)
|
LOG.debug('Loading plugin "%s" from entry-point.', self.name)
|
||||||
# Avoid relying on hasattr() here.
|
# Avoid relying on hasattr() here.
|
||||||
resolve = getattr(self.entry_point, 'resolve', None)
|
resolve = getattr(self.entry_point, 'resolve', None)
|
||||||
|
|
@ -55,14 +80,12 @@ class Plugin(object):
|
||||||
LOG.debug('Verifying plugin "%s"\'s requirements.',
|
LOG.debug('Verifying plugin "%s"\'s requirements.',
|
||||||
self.name)
|
self.name)
|
||||||
require()
|
require()
|
||||||
self.plugin = resolve()
|
self._plugin = resolve()
|
||||||
else:
|
else:
|
||||||
self.plugin = self.entry_point.load(
|
self._plugin = self.entry_point.load(
|
||||||
require=verify_requirements
|
require=verify_requirements
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.plugin
|
|
||||||
|
|
||||||
def provide_options(self, optmanager, options, extra_args):
|
def provide_options(self, optmanager, options, extra_args):
|
||||||
"""Pass the parsed options and extra arguments to the plugin."""
|
"""Pass the parsed options and extra arguments to the plugin."""
|
||||||
plugin = self.load()
|
plugin = self.load()
|
||||||
|
|
@ -152,48 +175,68 @@ class PluginManager(object):
|
||||||
yield func(self.plugins[name], *args, **kwargs)
|
yield func(self.plugins[name], *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Checkers(object):
|
class PluginTypeManager(object):
|
||||||
"""All of the checkers registered through entry-ponits."""
|
"""Parent class for most of the specific plugin types."""
|
||||||
|
|
||||||
def __init__(self, namespace='flake8.extension'):
|
def __init__(self):
|
||||||
"""Initialize the Checkers collection."""
|
"""Initialize the plugin type's manager."""
|
||||||
self.manager = PluginManager(namespace)
|
self.manager = PluginManager(self.namespace)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def names(self):
|
def names(self):
|
||||||
|
"""Proxy attribute to underlying manager."""
|
||||||
return self.manager.names
|
return self.manager.names
|
||||||
|
|
||||||
|
@property
|
||||||
|
def plugins(self):
|
||||||
|
"""Proxy attribute to underlying manager."""
|
||||||
|
return self.manager.plugins
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _generate_call_function(method_name, optmanager, *args, **kwargs):
|
||||||
|
def generated_function(plugin):
|
||||||
|
method = getattr(plugin, method_name, None)
|
||||||
|
if (method is not None and
|
||||||
|
isinstance(method, collections.Callable)):
|
||||||
|
return method(optmanager, *args, **kwargs)
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
def load_plugin(plugin):
|
||||||
|
return plugin.load()
|
||||||
|
|
||||||
|
return list(self.manager.map(load_plugin))
|
||||||
|
|
||||||
def register_options(self, optmanager):
|
def register_options(self, optmanager):
|
||||||
"""Register all of the checkers' options to the OptionManager."""
|
"""Register all of the checkers' options to the OptionManager."""
|
||||||
def call_register_options(plugin, optmanager):
|
call_register_options = self._generate_call_function(
|
||||||
return plugin.register_options(optmanager)
|
'register_options', optmanager,
|
||||||
|
)
|
||||||
|
|
||||||
list(self.map(call_register_options, optmanager))
|
list(self.manager.map(call_register_options, optmanager))
|
||||||
|
|
||||||
def provide_options(self, optmanager, options, extra_args):
|
def provide_options(self, optmanager, options, extra_args):
|
||||||
def call_provide_options(plugin, optmanager, options, extra_args):
|
"""Provide parsed options and extra arguments to the plugins."""
|
||||||
return plugin.provide_options(optmanager, options, extra_args)
|
call_provide_options = self._generate_call_function(
|
||||||
|
'provide_options', optmanager, options, extra_args,
|
||||||
|
)
|
||||||
|
|
||||||
list(self.map(call_provide_options, optmanager, options, extra_args))
|
list(self.manager.map(call_provide_options, optmanager, options,
|
||||||
|
extra_args))
|
||||||
|
|
||||||
|
|
||||||
|
class Checkers(PluginTypeManager):
|
||||||
|
"""All of the checkers registered through entry-ponits."""
|
||||||
|
|
||||||
|
namespace = 'flake8.extension'
|
||||||
|
|
||||||
|
|
||||||
class Listeners(object):
|
class Listeners(object):
|
||||||
"""All of the listeners registered through entry-points."""
|
"""All of the listeners registered through entry-points."""
|
||||||
|
|
||||||
def __init__(self, namespace='flake8.listener'):
|
namespace = 'flake8.listen'
|
||||||
self.manager = PluginManager(namespace)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def names(self):
|
|
||||||
return self.manager.names
|
|
||||||
|
|
||||||
|
|
||||||
class ReportFormatters(object):
|
class ReportFormatters(object):
|
||||||
"""All of the report formatters registered through entry-points."""
|
"""All of the report formatters registered through entry-points."""
|
||||||
|
|
||||||
def __init__(self, namespace='flake8.report'):
|
namespace = 'flake8.report'
|
||||||
self.manager = PluginManager(namespace)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def names(self):
|
|
||||||
return self.manager.names
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue