Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Unified Diff: third_party/pylint/checkers/exceptions.py

Issue 876793002: pylint: upgrade to 1.4.1 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/pylint/checkers/classes.py ('k') | third_party/pylint/checkers/misc.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/pylint/checkers/exceptions.py
diff --git a/third_party/pylint/checkers/exceptions.py b/third_party/pylint/checkers/exceptions.py
index e8e5a54120327730bd0959a3cfd610c6aa110be5..88a8f225e2e80304f8959fbcbe1a39a0aed02267 100644
--- a/third_party/pylint/checkers/exceptions.py
+++ b/third_party/pylint/checkers/exceptions.py
@@ -16,18 +16,22 @@
"""
import sys
-from logilab.common.compat import builtins
-BUILTINS_NAME = builtins.__name__
import astroid
from astroid import YES, Instance, unpack_infer, List, Tuple
+from logilab.common.compat import builtins
from pylint.checkers import BaseChecker
from pylint.checkers.utils import (
- is_empty, is_raising,
- check_messages, inherit_from_std_ex,
- EXCEPTIONS_MODULE, has_known_bases)
+ is_empty,
+ is_raising,
+ check_messages,
+ inherit_from_std_ex,
+ EXCEPTIONS_MODULE,
+ has_known_bases,
+ safe_infer)
from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE
+
def _annotated_unpack_infer(stmt, context=None):
"""
Recursively generate nodes inferred by the given statement.
@@ -35,33 +39,21 @@ def _annotated_unpack_infer(stmt, context=None):
Returns an iterator which yields tuples in the format
('original node', 'infered node').
"""
- # TODO: the same code as unpack_infer, except for the annotated
- # return. We need this type of annotation only here and
- # there is no point in complicating the API for unpack_infer.
- # If the need arises, this behaviour can be promoted to unpack_infer
- # as well.
if isinstance(stmt, (List, Tuple)):
for elt in stmt.elts:
- for infered_elt in unpack_infer(elt, context):
- yield elt, infered_elt
+ inferred = safe_infer(elt)
+ if inferred and inferred is not YES:
+ yield elt, inferred
return
- # if infered is a final node, return it and stop
- infered = next(stmt.infer(context))
- if infered is stmt:
- yield stmt, infered
- return
- # else, infer recursivly, except YES object that should be returned as is
for infered in stmt.infer(context):
if infered is YES:
- yield stmt, infered
- else:
- for inf_inf in unpack_infer(infered, context):
- yield stmt, inf_inf
+ continue
+ yield stmt, infered
PY3K = sys.version_info >= (3, 0)
OVERGENERAL_EXCEPTIONS = ('Exception',)
-
+BUILTINS_NAME = builtins.__name__
MSGS = {
'E0701': ('Bad except clauses order (%s)',
'bad-except-order',
@@ -145,21 +137,8 @@ class ExceptionsChecker(BaseChecker):
if node.exc is None:
return
if PY3K and node.cause:
- try:
- cause = next(node.cause.infer())
- except astroid.InferenceError:
- pass
- else:
- if cause is YES:
- return
- if isinstance(cause, astroid.Const):
- if cause.value is not None:
- self.add_message('bad-exception-context',
- node=node)
- elif (not isinstance(cause, astroid.Class) and
- not inherit_from_std_ex(cause)):
- self.add_message('bad-exception-context',
- node=node)
+ self._check_bad_exception_context(node)
+
expr = node.exc
if self._check_raise_value(node, expr):
return
@@ -170,23 +149,59 @@ class ExceptionsChecker(BaseChecker):
return
self._check_raise_value(node, value)
+ def _check_bad_exception_context(self, node):
+ """Verify that the exception context is properly set.
+
+ An exception context can be only `None` or an exception.
+ """
+ cause = safe_infer(node.cause)
+ if cause in (YES, None):
+ return
+ if isinstance(cause, astroid.Const):
+ if cause.value is not None:
+ self.add_message('bad-exception-context',
+ node=node)
+ elif (not isinstance(cause, astroid.Class) and
+ not inherit_from_std_ex(cause)):
+ self.add_message('bad-exception-context',
+ node=node)
+
def _check_raise_value(self, node, expr):
"""check for bad values, string exception and class inheritance
"""
value_found = True
if isinstance(expr, astroid.Const):
value = expr.value
- if isinstance(value, str):
+ if not isinstance(value, str):
# raising-string will be emitted from python3 porting checker.
- pass
- else:
self.add_message('raising-bad-type', node=node,
args=value.__class__.__name__)
- elif (isinstance(expr, astroid.Name) and \
- expr.name in ('None', 'True', 'False')) or \
- isinstance(expr, (astroid.List, astroid.Dict, astroid.Tuple,
- astroid.Module, astroid.Function)):
- self.add_message('raising-bad-type', node=node, args=expr.name)
+ elif ((isinstance(expr, astroid.Name) and
+ expr.name in ('None', 'True', 'False')) or
+ isinstance(expr, (astroid.List, astroid.Dict, astroid.Tuple,
+ astroid.Module, astroid.Function))):
+ emit = True
+ if not PY3K and isinstance(expr, astroid.Tuple):
+ # On Python 2, using the following is not an error:
+ # raise (ZeroDivisionError, None)
+ # raise (ZeroDivisionError, )
+ # What's left to do is to check that the first
+ # argument is indeed an exception.
+ # Verifying the other arguments is not
+ # the scope of this check.
+ first = expr.elts[0]
+ inferred = safe_infer(first)
+ if isinstance(inferred, Instance):
+ # pylint: disable=protected-access
+ inferred = inferred._proxied
+ if (inferred is YES or
+ isinstance(inferred, astroid.Class)
+ and inherit_from_std_ex(inferred)):
+ emit = False
+ if emit:
+ self.add_message('raising-bad-type',
+ node=node,
+ args=expr.name)
elif ((isinstance(expr, astroid.Name) and expr.name == 'NotImplemented')
or (isinstance(expr, astroid.CallFunc) and
isinstance(expr.func, astroid.Name) and
@@ -194,22 +209,65 @@ class ExceptionsChecker(BaseChecker):
self.add_message('notimplemented-raised', node=node)
elif isinstance(expr, (Instance, astroid.Class)):
if isinstance(expr, Instance):
+ # pylint: disable=protected-access
expr = expr._proxied
if (isinstance(expr, astroid.Class) and
- not inherit_from_std_ex(expr) and
- expr.root().name != BUILTINS_NAME):
+ not inherit_from_std_ex(expr)):
if expr.newstyle:
self.add_message('raising-non-exception', node=node)
else:
+ if has_known_bases(expr):
+ confidence = INFERENCE
+ else:
+ confidence = INFERENCE_FAILURE
self.add_message(
'nonstandard-exception', node=node,
- confidence=INFERENCE if has_known_bases(expr) else INFERENCE_FAILURE)
+ confidence=confidence)
else:
value_found = False
else:
value_found = False
return value_found
+ def _check_catching_non_exception(self, handler, exc, part):
+ if isinstance(exc, astroid.Tuple):
+ # Check if it is a tuple of exceptions.
+ inferred = [safe_infer(elt) for elt in exc.elts]
+ if any(node is astroid.YES for node in inferred):
+ # Don't emit if we don't know every component.
+ return
+ if all(node and inherit_from_std_ex(node)
+ for node in inferred):
+ return
+
+ if not isinstance(exc, astroid.Class):
+ # Don't emit the warning if the infered stmt
+ # is None, but the exception handler is something else,
+ # maybe it was redefined.
+ if (isinstance(exc, astroid.Const) and
+ exc.value is None):
+ if ((isinstance(handler.type, astroid.Const) and
+ handler.type.value is None) or
+ handler.type.parent_of(exc)):
+ # If the exception handler catches None or
+ # the exception component, which is None, is
+ # defined by the entire exception handler, then
+ # emit a warning.
+ self.add_message('catching-non-exception',
+ node=handler.type,
+ args=(part.as_string(), ))
+ else:
+ self.add_message('catching-non-exception',
+ node=handler.type,
+ args=(part.as_string(), ))
+ return
+ if (not inherit_from_std_ex(exc) and
+ exc.root().name != BUILTINS_NAME):
+ if has_known_bases(exc):
+ self.add_message('catching-non-exception',
+ node=handler.type,
+ args=(exc.name, ))
+
@check_messages('bare-except', 'broad-except', 'pointless-except',
'binary-op-exception', 'bad-except-order',
'catching-non-exception')
@@ -242,28 +300,14 @@ class ExceptionsChecker(BaseChecker):
for part, exc in excs:
if exc is YES:
continue
- if isinstance(exc, astroid.Instance) and inherit_from_std_ex(exc):
+ if (isinstance(exc, astroid.Instance)
+ and inherit_from_std_ex(exc)):
+ # pylint: disable=protected-access
exc = exc._proxied
+
+ self._check_catching_non_exception(handler, exc, part)
+
if not isinstance(exc, astroid.Class):
- # Don't emit the warning if the infered stmt
- # is None, but the exception handler is something else,
- # maybe it was redefined.
- if (isinstance(exc, astroid.Const) and
- exc.value is None):
- if ((isinstance(handler.type, astroid.Const) and
- handler.type.value is None) or
- handler.type.parent_of(exc)):
- # If the exception handler catches None or
- # the exception component, which is None, is
- # defined by the entire exception handler, then
- # emit a warning.
- self.add_message('catching-non-exception',
- node=handler.type,
- args=(part.as_string(), ))
- else:
- self.add_message('catching-non-exception',
- node=handler.type,
- args=(part.as_string(), ))
continue
exc_ancestors = [anc for anc in exc.ancestors()
@@ -280,13 +324,6 @@ class ExceptionsChecker(BaseChecker):
self.add_message('broad-except',
args=exc.name, node=handler.type)
- if (not inherit_from_std_ex(exc) and
- exc.root().name != BUILTINS_NAME):
- if has_known_bases(exc):
- self.add_message('catching-non-exception',
- node=handler.type,
- args=(exc.name, ))
-
exceptions_classes += [exc for _, exc in excs]
« no previous file with comments | « third_party/pylint/checkers/classes.py ('k') | third_party/pylint/checkers/misc.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698