From 30431155513c177a52c0f8ce0e6ed6d6274c6144 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Sun, 31 Dec 2017 18:45:27 -0600 Subject: [PATCH] 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. --- src/flake8/checker.py | 10 +++++++++- src/flake8/exceptions.py | 19 +++++++++++++++++++ src/flake8/main/application.py | 7 ++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/flake8/checker.py b/src/flake8/checker.py index 6e53cb5..7a18ce5 100644 --- a/src/flake8/checker.py +++ b/src/flake8/checker.py @@ -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): diff --git a/src/flake8/exceptions.py b/src/flake8/exceptions.py index 13e8996..c7217f5 100644 --- a/src/flake8/exceptions.py +++ b/src/flake8/exceptions.py @@ -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.""" diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py index 233b9af..aed6175 100644 --- a/src/flake8/main/application.py +++ b/src/flake8/main/application.py @@ -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()