summaryrefslogtreecommitdiff
path: root/venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py')
-rw-r--r--venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py88
1 files changed, 88 insertions, 0 deletions
diff --git a/venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py b/venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py
new file mode 100644
index 0000000..be2208c
--- /dev/null
+++ b/venv/Lib/site-packages/pylint/extensions/overlapping_exceptions.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+
+"""Looks for overlapping exceptions."""
+
+import astroid
+
+from pylint import checkers, interfaces
+from pylint.checkers import utils
+from pylint.checkers.exceptions import _annotated_unpack_infer
+
+
+class OverlappingExceptionsChecker(checkers.BaseChecker):
+ """Checks for two or more exceptions in the same exception handler
+ clause that are identical or parts of the same inheritance hierarchy
+ (i.e. overlapping)."""
+
+ __implements__ = interfaces.IAstroidChecker
+
+ name = "overlap-except"
+ msgs = {
+ "W0714": (
+ "Overlapping exceptions (%s)",
+ "overlapping-except",
+ "Used when exceptions in handler overlap or are identical",
+ )
+ }
+ priority = -2
+ options = ()
+
+ @utils.check_messages("overlapping-except")
+ def visit_tryexcept(self, node):
+ """check for empty except"""
+ for handler in node.handlers:
+ if handler.type is None:
+ continue
+ if isinstance(handler.type, astroid.BoolOp):
+ continue
+ try:
+ excs = list(_annotated_unpack_infer(handler.type))
+ except astroid.InferenceError:
+ continue
+
+ handled_in_clause = []
+ for part, exc in excs:
+ if exc is astroid.Uninferable:
+ continue
+ if isinstance(exc, astroid.Instance) and utils.inherit_from_std_ex(exc):
+ # pylint: disable=protected-access
+ exc = exc._proxied
+
+ if not isinstance(exc, astroid.ClassDef):
+ continue
+
+ exc_ancestors = [
+ anc for anc in exc.ancestors() if isinstance(anc, astroid.ClassDef)
+ ]
+
+ for prev_part, prev_exc in handled_in_clause:
+ prev_exc_ancestors = [
+ anc
+ for anc in prev_exc.ancestors()
+ if isinstance(anc, astroid.ClassDef)
+ ]
+ if exc == prev_exc:
+ self.add_message(
+ "overlapping-except",
+ node=handler.type,
+ args="%s and %s are the same"
+ % (prev_part.as_string(), part.as_string()),
+ )
+ elif prev_exc in exc_ancestors or exc in prev_exc_ancestors:
+ ancestor = part if exc in prev_exc_ancestors else prev_part
+ descendant = part if prev_exc in exc_ancestors else prev_part
+ self.add_message(
+ "overlapping-except",
+ node=handler.type,
+ args="%s is an ancestor class of %s"
+ % (ancestor.as_string(), descendant.as_string()),
+ )
+ handled_in_clause += [(part, exc)]
+
+
+def register(linter):
+ """Required method to auto register this checker."""
+ linter.register_checker(OverlappingExceptionsChecker(linter))