diff options
| author | cpopa <devnull@localhost> | 2013-12-28 15:14:03 +0200 |
|---|---|---|
| committer | cpopa <devnull@localhost> | 2013-12-28 15:14:03 +0200 |
| commit | 74796a1eb4a79fc2f85e3208e74945b7a2db9af4 (patch) | |
| tree | 0cc032a0e9a54a7185660155a572deefff833633 | |
| parent | 3927b761d923c9d8d32290c5a694acda9083480b (diff) | |
| download | pylint-74796a1eb4a79fc2f85e3208e74945b7a2db9af4.tar.gz | |
Add bad-exception-context warning for checking that `raise ... from ...` sets a proper exception context.
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | checkers/exceptions.py | 27 | ||||
| -rw-r--r-- | test/input/func_bad_exception_context_py30.py | 17 | ||||
| -rw-r--r-- | test/messages/func_bad_exception_context_py30.txt | 2 |
4 files changed, 49 insertions, 2 deletions
@@ -1,6 +1,11 @@ ChangeLog for Pylint ==================== +-- + * Add new warning 'bad-exception-context', checking + that `raise ... from ...` uses a proper exception context + (None or an exception). + 2013-12-22 -- 1.1.0 * Add new check for use of deprecated pragma directives "pylint:disable-msg" or "pylint:enable-msg" (I0022, deprecated-pragma) which was previously diff --git a/checkers/exceptions.py b/checkers/exceptions.py index 9843001..693e0f5 100644 --- a/checkers/exceptions.py +++ b/checkers/exceptions.py @@ -25,7 +25,7 @@ from pylint.checkers import BaseChecker from pylint.checkers.utils import is_empty, is_raising, check_messages from pylint.interfaces import IAstroidChecker - +PY3K = sys.version_info >= (3, 0) OVERGENERAL_EXCEPTIONS = ('Exception',) MSGS = { @@ -38,6 +38,13 @@ MSGS = { 'raising-bad-type', 'Used when something which is neither a class, an instance or a \ string is raised (i.e. a `TypeError` will be raised).'), + 'E0703': ('Exception context set to something which is not an ' + 'exception, nor None', + 'bad-exception-context', + 'Used when using the syntax "raise ... from ...", ' + 'where the exception context is not an exception, ' + 'nor None.', + {'minversion': (3, 0)}), 'E0710': ('Raising a new style class which doesn\'t inherit from BaseException', 'raising-non-exception', 'Used when a new style class which doesn\'t inherit from \ @@ -109,12 +116,28 @@ class ExceptionsChecker(BaseChecker): ), ) - @check_messages('W0701', 'W0710', 'E0702', 'E0710', 'E0711') + @check_messages('W0701', 'W0710', 'E0702', 'E0710', 'E0711', + 'bad-exception-context') def visit_raise(self, node): """visit raise possibly inferring value""" # ignore empty raise if node.exc is None: return + if PY3K and node.cause: + if isinstance(node.cause, astroid.Const): + if node.cause.value is not None: + self.add_message('bad-exception-context', + node=node) + else: + try: + cause = node.cause.infer().next() + except astroid.InferenceError: + pass + else: + if (not isinstance(cause, astroid.Class) and + not inherit_from_std_ex(cause)): + self.add_message('bad-exception-context', + node=node) expr = node.exc if self._check_raise_value(node, expr): return diff --git a/test/input/func_bad_exception_context_py30.py b/test/input/func_bad_exception_context_py30.py new file mode 100644 index 0000000..b520e68 --- /dev/null +++ b/test/input/func_bad_exception_context_py30.py @@ -0,0 +1,17 @@ +"""Check that raise ... from .. uses a proper exception context """ + +# pylint: disable=unreachable + +__revision__ = 0 + +class ExceptionSubclass(Exception): + """ subclass """ + +def test(): + """ docstring """ + raise IndexError from 1 + raise IndexError from None + raise IndexError from ZeroDivisionError + raise IndexError from object() + raise IndexError from ExceptionSubclass + diff --git a/test/messages/func_bad_exception_context_py30.txt b/test/messages/func_bad_exception_context_py30.txt new file mode 100644 index 0000000..0a4b3ec --- /dev/null +++ b/test/messages/func_bad_exception_context_py30.txt @@ -0,0 +1,2 @@ +E: 12:test: Exception context set to something which is not an exception, nor None
+E: 15:test: Exception context set to something which is not an exception, nor None
\ No newline at end of file |
