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

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

Issue 753543006: pylint: upgrade to 1.4.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years 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/design_analysis.py ('k') | third_party/pylint/checkers/format.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 94186eba72f14c31a38013f27a4ae2d7c241006d..e8e5a54120327730bd0959a3cfd610c6aa110be5 100644
--- a/third_party/pylint/checkers/exceptions.py
+++ b/third_party/pylint/checkers/exceptions.py
@@ -19,29 +19,45 @@ import sys
from logilab.common.compat import builtins
BUILTINS_NAME = builtins.__name__
import astroid
-from astroid import YES, Instance, unpack_infer
+from astroid import YES, Instance, unpack_infer, List, Tuple
from pylint.checkers import BaseChecker
-from pylint.checkers.utils import is_empty, is_raising, check_messages
-from pylint.interfaces import IAstroidChecker
+from pylint.checkers.utils import (
+ is_empty, is_raising,
+ check_messages, inherit_from_std_ex,
+ EXCEPTIONS_MODULE, has_known_bases)
+from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE
-def infer_bases(klass):
- """ Fully infer the bases of the klass node.
-
- This doesn't use .ancestors(), because we need
- the non-inferable nodes (YES nodes),
- which can't be retrieved from .ancestors()
+def _annotated_unpack_infer(stmt, context=None):
+ """
+ Recursively generate nodes inferred by the given statement.
+ If the inferred value is a list or a tuple, recurse on the elements.
+ Returns an iterator which yields tuples in the format
+ ('original node', 'infered node').
"""
- for base in klass.bases:
- try:
- inferit = base.infer().next()
- except astroid.InferenceError:
- continue
- if inferit is YES:
- yield inferit
+ # 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
+ 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 base in infer_bases(inferit):
- yield base
+ for inf_inf in unpack_infer(infered, context):
+ yield stmt, inf_inf
+
PY3K = sys.version_info >= (3, 0)
OVERGENERAL_EXCEPTIONS = ('Exception',)
@@ -52,7 +68,7 @@ MSGS = {
'Used when except clauses are not in the correct order (from the '
'more specific to the more generic). If you don\'t fix the order, '
'some exceptions may not be catched by the most specific handler.'),
- 'E0702': ('Raising %s while only classes, instances or string are allowed',
+ 'E0702': ('Raising %s while only classes or instances are allowed',
'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).'),
@@ -75,10 +91,6 @@ MSGS = {
'catching-non-exception',
'Used when a class which doesn\'t inherit from \
BaseException is used as an exception in an except clause.'),
-
- 'W0701': ('Raising a string exception',
- 'raising-string',
- 'Used when a string exception is raised.'),
'W0702': ('No exception type(s) specified',
'bare-except',
'Used when an except clause doesn\'t specify exceptions type to \
@@ -101,25 +113,9 @@ MSGS = {
'Used when the exception to catch is of the form \
"except A or B:". If intending to catch multiple, \
rewrite as "except (A, B):"'),
- 'W0712': ('Implicit unpacking of exceptions is not supported in Python 3',
- 'unpacking-in-except',
- 'Python3 will not allow implicit unpacking of exceptions in except '
- 'clauses. '
- 'See http://www.python.org/dev/peps/pep-3110/',
- {'maxversion': (3, 0)}),
- 'W0713': ('Indexing exceptions will not work on Python 3',
- 'indexing-exception',
- 'Indexing exceptions will not work on Python 3. Use '
- '`exception.args[index]` instead.',
- {'maxversion': (3, 0)}),
}
-if sys.version_info < (3, 0):
- EXCEPTIONS_MODULE = "exceptions"
-else:
- EXCEPTIONS_MODULE = "builtins"
-
class ExceptionsChecker(BaseChecker):
"""checks for
* excepts without exception filter
@@ -140,8 +136,9 @@ class ExceptionsChecker(BaseChecker):
),
)
- @check_messages('raising-string', 'nonstandard-exception', 'raising-bad-type',
- 'raising-non-exception', 'notimplemented-raised', 'bad-exception-context')
+ @check_messages('nonstandard-exception',
+ 'raising-bad-type', 'raising-non-exception',
+ 'notimplemented-raised', 'bad-exception-context')
def visit_raise(self, node):
"""visit raise possibly inferring value"""
# ignore empty raise
@@ -149,7 +146,7 @@ class ExceptionsChecker(BaseChecker):
return
if PY3K and node.cause:
try:
- cause = node.cause.infer().next()
+ cause = next(node.cause.infer())
except astroid.InferenceError:
pass
else:
@@ -168,7 +165,7 @@ class ExceptionsChecker(BaseChecker):
return
else:
try:
- value = unpack_infer(expr).next()
+ value = next(unpack_infer(expr))
except astroid.InferenceError:
return
self._check_raise_value(node, value)
@@ -180,7 +177,8 @@ class ExceptionsChecker(BaseChecker):
if isinstance(expr, astroid.Const):
value = expr.value
if isinstance(value, str):
- self.add_message('raising-string', node=node)
+ # raising-string will be emitted from python3 porting checker.
+ pass
else:
self.add_message('raising-bad-type', node=node,
args=value.__class__.__name__)
@@ -194,8 +192,6 @@ class ExceptionsChecker(BaseChecker):
isinstance(expr.func, astroid.Name) and
expr.func.name == 'NotImplemented')):
self.add_message('notimplemented-raised', node=node)
- elif isinstance(expr, astroid.BinOp) and expr.op == '%':
- self.add_message('raising-string', node=node)
elif isinstance(expr, (Instance, astroid.Class)):
if isinstance(expr, Instance):
expr = expr._proxied
@@ -205,31 +201,15 @@ class ExceptionsChecker(BaseChecker):
if expr.newstyle:
self.add_message('raising-non-exception', node=node)
else:
- self.add_message('nonstandard-exception', node=node)
+ self.add_message(
+ 'nonstandard-exception', node=node,
+ confidence=INFERENCE if has_known_bases(expr) else INFERENCE_FAILURE)
else:
value_found = False
else:
value_found = False
return value_found
- @check_messages('unpacking-in-except')
- def visit_excepthandler(self, node):
- """Visit an except handler block and check for exception unpacking."""
- if isinstance(node.name, (astroid.Tuple, astroid.List)):
- self.add_message('unpacking-in-except', node=node)
-
- @check_messages('indexing-exception')
- def visit_subscript(self, node):
- """ Look for indexing exceptions. """
- try:
- for infered in node.value.infer():
- if not isinstance(infered, astroid.Instance):
- continue
- if inherit_from_std_ex(infered):
- self.add_message('indexing-exception', node=node)
- except astroid.InferenceError:
- return
-
@check_messages('bare-except', 'broad-except', 'pointless-except',
'binary-op-exception', 'bad-except-order',
'catching-non-exception')
@@ -237,10 +217,11 @@ class ExceptionsChecker(BaseChecker):
"""check for empty except"""
exceptions_classes = []
nb_handlers = len(node.handlers)
- for index, handler in enumerate(node.handlers):
+ for index, handler in enumerate(node.handlers):
# single except doing nothing but "pass" without else clause
if is_empty(handler.body) and not node.orelse:
- self.add_message('pointless-except', node=handler.type or handler.body[0])
+ self.add_message('pointless-except',
+ node=handler.type or handler.body[0])
if handler.type is None:
if not is_raising(handler.body):
self.add_message('bare-except', node=handler)
@@ -251,56 +232,64 @@ class ExceptionsChecker(BaseChecker):
self.add_message('bad-except-order', node=node, args=msg)
elif isinstance(handler.type, astroid.BoolOp):
- self.add_message('binary-op-exception', node=handler, args=handler.type.op)
+ self.add_message('binary-op-exception',
+ node=handler, args=handler.type.op)
else:
try:
- excs = list(unpack_infer(handler.type))
+ excs = list(_annotated_unpack_infer(handler.type))
except astroid.InferenceError:
continue
- for exc in excs:
- # XXX skip other non class nodes
- if exc is YES or not isinstance(exc, astroid.Class):
+ for part, exc in excs:
+ if exc is YES:
continue
+ if isinstance(exc, astroid.Instance) and inherit_from_std_ex(exc):
+ exc = exc._proxied
+ 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()
if isinstance(anc, astroid.Class)]
for previous_exc in exceptions_classes:
if previous_exc in exc_ancestors:
msg = '%s is an ancestor class of %s' % (
previous_exc.name, exc.name)
- self.add_message('bad-except-order', node=handler.type, args=msg)
+ self.add_message('bad-except-order',
+ node=handler.type, args=msg)
if (exc.name in self.config.overgeneral_exceptions
and exc.root().name == EXCEPTIONS_MODULE
and not is_raising(handler.body)):
- self.add_message('broad-except', args=exc.name, node=handler.type)
+ self.add_message('broad-except',
+ args=exc.name, node=handler.type)
if (not inherit_from_std_ex(exc) and
exc.root().name != BUILTINS_NAME):
- # try to see if the exception is based on a C based
- # exception, by infering all the base classes and
- # looking for inference errors
- bases = infer_bases(exc)
- fully_infered = all(inferit is not YES
- for inferit in bases)
- if fully_infered:
+ if has_known_bases(exc):
self.add_message('catching-non-exception',
node=handler.type,
args=(exc.name, ))
- exceptions_classes += excs
+ exceptions_classes += [exc for _, exc in excs]
-def inherit_from_std_ex(node):
- """return true if the given class node is subclass of
- exceptions.Exception
- """
- if node.name in ('Exception', 'BaseException') \
- and node.root().name == EXCEPTIONS_MODULE:
- return True
- for parent in node.ancestors(recurs=False):
- if inherit_from_std_ex(parent):
- return True
- return False
-
def register(linter):
"""required method to auto register this checker"""
linter.register_checker(ExceptionsChecker(linter))
« no previous file with comments | « third_party/pylint/checkers/design_analysis.py ('k') | third_party/pylint/checkers/format.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698