Implement better UX around broken plugins

This handles most any exception arising from a plugin and provides the
user with a better experience and view of the problem. It also provides
a way to retrieve the information about what exactly failed for
providing bug reports to plugin authors.
This commit is contained in:
Ian Stapleton Cordasco 2017-12-31 18:45:27 -06:00
parent 3530870679
commit 3043115551
No known key found for this signature in database
GPG key ID: C9D7A2604B4FCB2A
3 changed files with 34 additions and 2 deletions

View file

@ -432,7 +432,15 @@ class FileChecker(object):
plugin=plugin,
exception=ae,
)
return plugin['plugin'](**arguments)
try:
return plugin['plugin'](**arguments)
except Exception as all_exc:
LOG.critical('Plugin %s raised an unexpected exception',
plugin['name'])
raise exceptions.PluginExecutionFailed(
plugin=plugin,
excetion=all_exc,
)
@staticmethod
def _extract_syntax_information(exception):

View file

@ -76,6 +76,25 @@ class PluginRequestedUnknownParameters(Flake8Exception):
'exc': self.original_exception}
class PluginExecutionFailed(Flake8Exception):
"""The plugin failed during execution."""
FORMAT = '"%(name)s" failed during execution due to "%(exc)s"'
def __init__(self, *args, **kwargs):
"""Utilize keyword arguments for message generation."""
self.original_exception = kwargs.pop('exception')
self.plugin = kwargs.pop('plugin')
super(PluginExecutionFailed, self).__init__(
str(self), *args, **kwargs
)
def __str__(self):
"""Format our exception message."""
return self.FORMAT % {'name': self.plugin['plugin_name'],
'exc': self.original_exception}
class HookInstallationError(Flake8Exception):
"""Parent exception for all hooks errors."""

View file

@ -309,7 +309,12 @@ class Application(object):
if self.running_against_diff:
files = sorted(self.parsed_diff)
self.file_checker_manager.start(files)
self.file_checker_manager.run()
try:
self.file_checker_manager.run()
except exceptions.PluginExecutionFailed as plugin_failed:
print(str(plugin_failed))
print('Run flake8 with greater verbosity to see more details')
self.catastrophic_failure = True
LOG.info('Finished running')
self.file_checker_manager.stop()
self.end_time = time.time()