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

Side by Side Diff: third_party/pylint/checkers/exceptions.py

Issue 10447014: Add pylint to depot_tools. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix unittests. Created 8 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # This program is free software; you can redistribute it and/or modify it under
4 # the terms of the GNU General Public License as published by the Free Software
5 # Foundation; either version 2 of the License, or (at your option) any later
6 # version.
7 #
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License along with
13 # this program; if not, write to the Free Software Foundation, Inc.,
14 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 """exceptions handling (raising, catching, exceptions classes) checker
16 """
17 import sys
18
19 from logilab.common.compat import builtins
20 BUILTINS_NAME = builtins.__name__
21 from logilab import astng
22 from logilab.astng import YES, Instance, unpack_infer
23
24 from pylint.checkers import BaseChecker
25 from pylint.checkers.utils import is_empty, is_raising
26 from pylint.interfaces import IASTNGChecker
27
28
29 OVERGENERAL_EXCEPTIONS = ('Exception',)
30
31 MSGS = {
32 'E0701': (
33 'Bad except clauses order (%s)',
34 'Used when except clauses are not in the correct order (from the \
35 more specific to the more generic). If you don\'t fix the order, \
36 some exceptions may not be catched by the most specific handler.'),
37 'E0702': ('Raising %s while only classes, instances or string are allowed',
38 'Used when something which is neither a class, an instance or a \
39 string is raised (i.e. a `TypeError` will be raised).'),
40 'E0710': ('Raising a new style class which doesn\'t inherit from BaseExcepti on',
41 'Used when a new style class which doesn\'t inherit from \
42 BaseException is raised.'),
43 'E0711': ('NotImplemented raised - should raise NotImplementedError',
44 'Used when NotImplemented is raised instead of \
45 NotImplementedError'),
46
47 'W0701': ('Raising a string exception',
48 'Used when a string exception is raised.'),
49 'W0702': ('No exception type(s) specified',
50 'Used when an except clause doesn\'t specify exceptions type to \
51 catch.'),
52 'W0703': ('Catching too general exception %s',
53 'Used when an except catches a too general exception, \
54 possibly burying unrelated errors.'),
55 'W0704': ('Except doesn\'t do anything',
56 'Used when an except clause does nothing but "pass" and there is\
57 no "else" clause.'),
58 'W0710': ('Exception doesn\'t inherit from standard "Exception" class',
59 'Used when a custom exception class is raised but doesn\'t \
60 inherit from the builtin "Exception" class.'),
61 }
62
63
64 if sys.version_info < (3, 0):
65 EXCEPTIONS_MODULE = "exceptions"
66 else:
67 EXCEPTIONS_MODULE = "builtins"
68
69 class ExceptionsChecker(BaseChecker):
70 """checks for
71 * excepts without exception filter
72 * type of raise argument : string, Exceptions, other values
73 """
74
75 __implements__ = IASTNGChecker
76
77 name = 'exceptions'
78 msgs = MSGS
79 priority = -4
80 options = (('overgeneral-exceptions',
81 {'default' : OVERGENERAL_EXCEPTIONS,
82 'type' :'csv', 'metavar' : '<comma-separated class names>',
83 'help' : 'Exceptions that will emit a warning '
84 'when being caught. Defaults to "%s"' % (
85 ', '.join(OVERGENERAL_EXCEPTIONS),)}
86 ),
87 )
88
89 def visit_raise(self, node):
90 """visit raise possibly inferring value"""
91 # ignore empty raise
92 if node.exc is None:
93 return
94 expr = node.exc
95 if self._check_raise_value(node, expr):
96 return
97 else:
98 try:
99 value = unpack_infer(expr).next()
100 except astng.InferenceError:
101 return
102 self._check_raise_value(node, value)
103
104 def _check_raise_value(self, node, expr):
105 """check for bad values, string exception and class inheritance
106 """
107 value_found = True
108 if isinstance(expr, astng.Const):
109 value = expr.value
110 if isinstance(value, str):
111 self.add_message('W0701', node=node)
112 else:
113 self.add_message('E0702', node=node,
114 args=value.__class__.__name__)
115 elif (isinstance(expr, astng.Name) and \
116 expr.name in ('None', 'True', 'False')) or \
117 isinstance(expr, (astng.List, astng.Dict, astng.Tuple,
118 astng.Module, astng.Function)):
119 self.add_message('E0702', node=node, args=expr.name)
120 elif ( (isinstance(expr, astng.Name) and expr.name == 'NotImplemented')
121 or (isinstance(expr, astng.CallFunc) and
122 isinstance(expr.func, astng.Name) and
123 expr.func.name == 'NotImplemented') ):
124 self.add_message('E0711', node=node)
125 elif isinstance(expr, astng.BinOp) and expr.op == '%':
126 self.add_message('W0701', node=node)
127 elif isinstance(expr, (Instance, astng.Class)):
128 if isinstance(expr, Instance):
129 expr = expr._proxied
130 if (isinstance(expr, astng.Class) and
131 not inherit_from_std_ex(expr) and
132 expr.root().name != BUILTINS_NAME):
133 if expr.newstyle:
134 self.add_message('E0710', node=node)
135 else:
136 self.add_message('W0710', node=node)
137 else:
138 value_found = False
139 else:
140 value_found = False
141 return value_found
142
143
144 def visit_tryexcept(self, node):
145 """check for empty except"""
146 exceptions_classes = []
147 nb_handlers = len(node.handlers)
148 for index, handler in enumerate(node.handlers):
149 # single except doing nothing but "pass" without else clause
150 if nb_handlers == 1 and is_empty(handler.body) and not node.orelse:
151 self.add_message('W0704', node=handler.type or handler.body[0])
152 if handler.type is None:
153 if nb_handlers == 1 and not is_raising(handler.body):
154 self.add_message('W0702', node=handler)
155 # check if a "except:" is followed by some other
156 # except
157 elif index < (nb_handlers - 1):
158 msg = 'empty except clause should always appear last'
159 self.add_message('E0701', node=node, args=msg)
160 else:
161 try:
162 excs = list(unpack_infer(handler.type))
163 except astng.InferenceError:
164 continue
165 for exc in excs:
166 # XXX skip other non class nodes
167 if exc is YES or not isinstance(exc, astng.Class):
168 continue
169 exc_ancestors = [anc for anc in exc.ancestors()
170 if isinstance(anc, astng.Class)]
171 for previous_exc in exceptions_classes:
172 if previous_exc in exc_ancestors:
173 msg = '%s is an ancestor class of %s' % (
174 previous_exc.name, exc.name)
175 self.add_message('E0701', node=handler.type, args=ms g)
176 if (exc.name in self.config.overgeneral_exceptions
177 and exc.root().name == EXCEPTIONS_MODULE
178 and nb_handlers == 1 and not is_raising(handler.body)):
179 self.add_message('W0703', args=exc.name, node=handler.ty pe)
180 exceptions_classes += excs
181
182
183 def inherit_from_std_ex(node):
184 """return true if the given class node is subclass of
185 exceptions.Exception
186 """
187 if node.name in ('Exception', 'BaseException') \
188 and node.root().name == EXCEPTIONS_MODULE:
189 return True
190 for parent in node.ancestors(recurs=False):
191 if inherit_from_std_ex(parent):
192 return True
193 return False
194
195 def register(linter):
196 """required method to auto register this checker"""
197 linter.register_checker(ExceptionsChecker(linter))
OLDNEW
« 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