summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcpopa <devnull@localhost>2014-01-03 12:36:02 +0200
committercpopa <devnull@localhost>2014-01-03 12:36:02 +0200
commit74235c75b27806b639cdde8b0df81d916d843f0d (patch)
treef72f8c81f7a3e1a1b559a9396170559fed2a5ccd
parente099a5685de2fd625de831d060d0b4a91ed4481d (diff)
parent74796a1eb4a79fc2f85e3208e74945b7a2db9af4 (diff)
downloadpylint-74235c75b27806b639cdde8b0df81d916d843f0d.tar.gz
Merge with default.
-rw-r--r--ChangeLog5
-rw-r--r--checkers/exceptions.py26
-rw-r--r--test/input/func_bad_exception_context_py30.py17
-rw-r--r--test/messages/func_bad_exception_context_py30.txt2
4 files changed, 49 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index f5b7192..6ed61d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 5bb07ac..0895a8b 100644
--- a/checkers/exceptions.py
+++ b/checkers/exceptions.py
@@ -43,6 +43,7 @@ def infer_bases(klass):
for base in infer_bases(inferit):
yield base
+PY3K = sys.version_info >= (3, 0)
OVERGENERAL_EXCEPTIONS = ('Exception',)
MSGS = {
@@ -55,6 +56,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 \
@@ -126,12 +134,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