mirror of
https://github.com/PyCQA/flake8.git
synced 2026-03-30 02:46:52 +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."""
|
||||
import collections
|
||||
import logging
|
||||
|
||||
import pkg_resources
|
||||
|
|
@ -21,13 +22,22 @@ class Plugin(object):
|
|||
"""
|
||||
self.name = name
|
||||
self.entry_point = entry_point
|
||||
self.plugin = None
|
||||
self._plugin = None
|
||||
|
||||
def __repr__(self):
|
||||
return 'Plugin(name="{0}", entry_point="{1}")'.format(
|
||||
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):
|
||||
r"""Call the plugin with \*args and \*\*kwargs."""
|
||||
return self.plugin(*args, **kwargs)
|
||||
|
|
@ -45,7 +55,22 @@ class Plugin(object):
|
|||
:returns:
|
||||
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)
|
||||
# Avoid relying on hasattr() here.
|
||||
resolve = getattr(self.entry_point, 'resolve', None)
|
||||
|
|
@ -55,14 +80,12 @@ class Plugin(object):
|
|||
LOG.debug('Verifying plugin "%s"\'s requirements.',
|
||||
self.name)
|
||||
require()
|
||||
self.plugin = resolve()
|
||||
self._plugin = resolve()
|
||||
else:
|
||||
self.plugin = self.entry_point.load(
|
||||
self._plugin = self.entry_point.load(
|
||||
require=verify_requirements
|
||||
)
|
||||
|
||||
return self.plugin
|
||||
|
||||
def provide_options(self, optmanager, options, extra_args):
|
||||
"""Pass the parsed options and extra arguments to the plugin."""
|
||||
plugin = self.load()
|
||||
|
|
@ -152,48 +175,68 @@ class PluginManager(object):
|
|||
yield func(self.plugins[name], *args, **kwargs)
|
||||
|
||||
|
||||
class Checkers(object):
|
||||
"""All of the checkers registered through entry-ponits."""
|
||||
class PluginTypeManager(object):
|
||||
"""Parent class for most of the specific plugin types."""
|
||||
|
||||
def __init__(self, namespace='flake8.extension'):
|
||||
"""Initialize the Checkers collection."""
|
||||
self.manager = PluginManager(namespace)
|
||||
def __init__(self):
|
||||
"""Initialize the plugin type's manager."""
|
||||
self.manager = PluginManager(self.namespace)
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
"""Proxy attribute to underlying manager."""
|
||||
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):
|
||||
"""Register all of the checkers' options to the OptionManager."""
|
||||
def call_register_options(plugin, optmanager):
|
||||
return plugin.register_options(optmanager)
|
||||
call_register_options = self._generate_call_function(
|
||||
'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 call_provide_options(plugin, optmanager, options, extra_args):
|
||||
return plugin.provide_options(optmanager, options, extra_args)
|
||||
"""Provide parsed options and extra arguments to the plugins."""
|
||||
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):
|
||||
"""All of the listeners registered through entry-points."""
|
||||
|
||||
def __init__(self, namespace='flake8.listener'):
|
||||
self.manager = PluginManager(namespace)
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return self.manager.names
|
||||
namespace = 'flake8.listen'
|
||||
|
||||
|
||||
class ReportFormatters(object):
|
||||
"""All of the report formatters registered through entry-points."""
|
||||
|
||||
def __init__(self, namespace='flake8.report'):
|
||||
self.manager = PluginManager(namespace)
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return self.manager.names
|
||||
namespace = 'flake8.report'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue