summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--pylint/checkers/exceptions.py27
-rw-r--r--pylint/test/functional/wrong_exception_operation.py18
-rw-r--r--pylint/test/functional/wrong_exception_operation.txt3
4 files changed, 57 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 0768f789d..6d90cdf52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,7 +5,7 @@ Pylint's ChangeLog
What's New in Pylint 2.3.0?
===========================
-Release date: TB
+Release date: TBA
* Refactor ``bad-reversed-sequence`` to account for more objects that can define ``__reversed__``
@@ -15,6 +15,14 @@ Release date: TB
Close #2598
+* Added ``wrong-exception-operation``
+
+ Used when an operation is done against an exception, but the operation
+ is not valid for the exception in question. Usually emitted when having
+ binary operations between exceptions in except handlers.
+
+ Close #2494
+
What's New in Pylint 2.2.2?
===========================
diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py
index e0a449ca8..80ea98ae2 100644
--- a/pylint/checkers/exceptions.py
+++ b/pylint/checkers/exceptions.py
@@ -160,6 +160,13 @@ MSGS = {
"constructor, the first of them a string literal containing what "
"appears to be placeholders intended for formatting",
),
+ "W0716": (
+ "Invalid exception operation. %s",
+ "wrong-exception-operation",
+ "Used when an operation is done against an exception, but the operation "
+ "is not valid for the exception in question. Usually emitted when having "
+ "binary operations between exceptions in except handlers.",
+ ),
}
@@ -448,6 +455,26 @@ class ExceptionsChecker(checkers.BaseChecker):
if bare_raise:
self.add_message("try-except-raise", node=handler_having_bare_raise)
+ @utils.check_messages("wrong-exception-operation")
+ def visit_binop(self, node):
+ if isinstance(node.parent, astroid.ExceptHandler):
+ # except (V | A)
+ suggestion = "Did you mean '(%s, %s)' instead?" % (
+ node.left.as_string(),
+ node.right.as_string(),
+ )
+ self.add_message("wrong-exception-operation", node=node, args=(suggestion,))
+
+ @utils.check_messages("wrong-exception-operation")
+ def visit_compare(self, node):
+ if isinstance(node.parent, astroid.ExceptHandler):
+ # except (V < A)
+ suggestion = "Did you mean '(%s, %s)' instead?" % (
+ node.left.as_string(),
+ ", ".join(operand.as_string() for _, operand in node.ops),
+ )
+ self.add_message("wrong-exception-operation", node=node, args=(suggestion,))
+
@utils.check_messages(
"bare-except",
"broad-except",
diff --git a/pylint/test/functional/wrong_exception_operation.py b/pylint/test/functional/wrong_exception_operation.py
new file mode 100644
index 000000000..1c3c4e380
--- /dev/null
+++ b/pylint/test/functional/wrong_exception_operation.py
@@ -0,0 +1,18 @@
+# pylint: disable=missing-docstring, superfluous-parens
+
+
+try:
+ 1/0
+except (ValueError | TypeError): # [wrong-exception-operation]
+ pass
+
+try:
+ 1/0
+except (ValueError + TypeError): # [wrong-exception-operation]
+ pass
+
+
+try:
+ 1/0
+except (ValueError < TypeError): # [wrong-exception-operation]
+ pass
diff --git a/pylint/test/functional/wrong_exception_operation.txt b/pylint/test/functional/wrong_exception_operation.txt
new file mode 100644
index 000000000..61a2e179f
--- /dev/null
+++ b/pylint/test/functional/wrong_exception_operation.txt
@@ -0,0 +1,3 @@
+wrong-exception-operation:6::Invalid exception operation. Did you mean '(ValueError, TypeError)' instead?
+wrong-exception-operation:11::Invalid exception operation. Did you mean '(ValueError, TypeError)' instead?
+wrong-exception-operation:17::Invalid exception operation. Did you mean '(ValueError, TypeError)' instead?