diff --git a/ChangeLog b/ChangeLog index b1cdff2fd1..6cd34b1e63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,12 @@ Pylint's ChangeLog What's New in Pylint 1.8? ========================= -Release date: TBD + * Raise meaningful exception for invalid reporter class being selected + + When unknown reporter class will be selected as Pylint reporter, + meaningful error message would be raised instead of bare ``ImportError`` + or ``AttribueError`` related to module or reporter class being not found. + Close #1388 What's New in Pylint 1.7.1? diff --git a/doc/whatsnew/1.8.rst b/doc/whatsnew/1.8.rst index 5300f4cb04..f696e20884 100644 --- a/doc/whatsnew/1.8.rst +++ b/doc/whatsnew/1.8.rst @@ -9,4 +9,5 @@ Summary -- Release highlights ============================= -* None yet. +* Raise meaningful exception in case of invalid reporter class (output format) + being selected. diff --git a/pylint/exceptions.py b/pylint/exceptions.py index 429379d97f..783c7e5c29 100644 --- a/pylint/exceptions.py +++ b/pylint/exceptions.py @@ -13,3 +13,6 @@ class UnknownMessageError(Exception): class EmptyReportError(Exception): """raised when a report is empty and so should not be displayed""" + +class InvalidReporterError(Exception): + """raised when selected reporter is invalid (e.g. not found)""" diff --git a/pylint/lint.py b/pylint/lint.py index 537d6f2503..dab057fce6 100644 --- a/pylint/lint.py +++ b/pylint/lint.py @@ -473,12 +473,20 @@ def _load_reporter(self): if name in self._reporters: self.set_reporter(self._reporters[name]()) else: - qname = self._reporter_name - module = modutils.load_module_from_name( - modutils.get_module_part(qname)) - class_name = qname.split('.')[-1] - reporter_class = getattr(module, class_name) - self.set_reporter(reporter_class()) + try: + reporter_class = self._load_reporter_class() + except (ImportError, AttributeError): + raise exceptions.InvalidReporterError(name) + else: + self.set_reporter(reporter_class()) + + def _load_reporter_class(self): + qname = self._reporter_name + module = modutils.load_module_from_name( + modutils.get_module_part(qname)) + class_name = qname.split('.')[-1] + reporter_class = getattr(module, class_name) + return reporter_class def set_reporter(self, reporter): """set the reporter used to display messages and reports""" diff --git a/pylint/test/unittest_lint.py b/pylint/test/unittest_lint.py index 690a19432c..a6e401cbba 100644 --- a/pylint/test/unittest_lint.py +++ b/pylint/test/unittest_lint.py @@ -28,6 +28,7 @@ from pylint.reporters import text from pylint import checkers from pylint.checkers.utils import check_messages +from pylint import exceptions from pylint import interfaces import pytest @@ -390,6 +391,12 @@ def test_report_output_format_aliased(linter): assert linter.reporter.__class__.__name__ == 'TextReporter' +def test_set_unsupported_reporter(linter): + text.register(linter) + with pytest.raises(exceptions.InvalidReporterError): + linter.set_option('output-format', 'missing.module.Class') + + def test_set_option_1(linter): linter.set_option('disable', 'C0111,W0234') assert not linter.is_message_enabled('C0111')