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

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

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years, 1 month 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/__init__.py ('k') | third_party/pylint/checkers/classes.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
2 # Copyright (c) 2009-2010 Arista Networks, Inc. 3 # Copyright (c) 2009-2010 Arista Networks, Inc.
3 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 4 #
4 # This program is free software; you can redistribute it and/or modify it under 5 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software 6 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; either version 2 of the License, or (at your option) any later 7 # Foundation; either version 2 of the License, or (at your option) any later
7 # version. 8 # version.
8 # 9 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT 10 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 # 13 #
13 # You should have received a copy of the GNU General Public License along with 14 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 15 # this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 """basic checker for Python code""" 17 """basic checker for Python code"""
17 18
19 import sys
20 import astroid
21 from logilab.common.ureports import Table
22 from astroid import are_exclusive, InferenceError
23 import astroid.bases
18 24
19 from logilab import astng 25 from pylint.interfaces import IAstroidChecker
20 from logilab.common.ureports import Table 26 from pylint.utils import EmptyReport
21 from logilab.astng import are_exclusive
22
23 from pylint.interfaces import IASTNGChecker
24 from pylint.reporters import diff_string 27 from pylint.reporters import diff_string
25 from pylint.checkers import BaseChecker, EmptyReport 28 from pylint.checkers import BaseChecker
26 from pylint.checkers.utils import check_messages, clobber_in_except, is_inside_e xcept 29 from pylint.checkers.utils import (
30 check_messages,
31 clobber_in_except,
32 is_builtin_object,
33 is_inside_except,
34 overrides_a_method,
35 safe_infer,
36 get_argument_from_call,
37 NoSuchArgumentError,
38 )
27 39
28 40
29 import re 41 import re
30 42
31 # regex for class/function/variable/constant name 43 # regex for class/function/variable/constant name
32 CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$') 44 CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$')
33 MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$') 45 MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$')
34 CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$') 46 CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$')
35 COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$') 47 COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$')
36 DEFAULT_NAME_RGX = re.compile('[a-z_][a-z0-9_]{2,30}$') 48 DEFAULT_NAME_RGX = re.compile('[a-z_][a-z0-9_]{2,30}$')
49 CLASS_ATTRIBUTE_RGX = re.compile(r'([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$')
37 # do not require a doc string on system methods 50 # do not require a doc string on system methods
38 NO_REQUIRED_DOC_RGX = re.compile('__.*__') 51 NO_REQUIRED_DOC_RGX = re.compile('__.*__')
52 REVERSED_METHODS = (('__getitem__', '__len__'),
53 ('__reversed__', ))
54
55 PY33 = sys.version_info >= (3, 3)
56 PY3K = sys.version_info >= (3, 0)
57 BAD_FUNCTIONS = ['map', 'filter', 'apply']
58 if sys.version_info < (3, 0):
59 BAD_FUNCTIONS.append('input')
60 BAD_FUNCTIONS.append('file')
61
62 # Name categories that are always consistent with all naming conventions.
63 EXEMPT_NAME_CATEGORIES = set(('exempt', 'ignore'))
39 64
40 del re 65 del re
41 66
42 def in_loop(node): 67 def in_loop(node):
43 """return True if the node is inside a kind of for loop""" 68 """return True if the node is inside a kind of for loop"""
44 parent = node.parent 69 parent = node.parent
45 while parent is not None: 70 while parent is not None:
46 if isinstance(parent, (astng.For, astng.ListComp, astng.SetComp, 71 if isinstance(parent, (astroid.For, astroid.ListComp, astroid.SetComp,
47 astng.DictComp, astng.GenExpr)): 72 astroid.DictComp, astroid.GenExpr)):
48 return True 73 return True
49 parent = parent.parent 74 parent = parent.parent
50 return False 75 return False
51 76
52 def in_nested_list(nested_list, obj): 77 def in_nested_list(nested_list, obj):
53 """return true if the object is an element of <nested_list> or of a nested 78 """return true if the object is an element of <nested_list> or of a nested
54 list 79 list
55 """ 80 """
56 for elmt in nested_list: 81 for elmt in nested_list:
57 if isinstance(elmt, (list, tuple)): 82 if isinstance(elmt, (list, tuple)):
58 if in_nested_list(elmt, obj): 83 if in_nested_list(elmt, obj):
59 return True 84 return True
60 elif elmt == obj: 85 elif elmt == obj:
61 return True 86 return True
62 return False 87 return False
63 88
89 def _loop_exits_early(loop):
90 """Returns true if a loop has a break statement in its body."""
91 loop_nodes = (astroid.For, astroid.While)
92 # Loop over body explicitly to avoid matching break statements
93 # in orelse.
94 for child in loop.body:
95 if isinstance(child, loop_nodes):
96 # break statement may be in orelse of child loop.
97 for orelse in (child.orelse or ()):
98 for _ in orelse.nodes_of_class(astroid.Break, skip_klass=loop_no des):
99 return True
100 continue
101 for _ in child.nodes_of_class(astroid.Break, skip_klass=loop_nodes):
102 return True
103 return False
104
105 if sys.version_info < (3, 0):
106 PROPERTY_CLASSES = set(('__builtin__.property', 'abc.abstractproperty'))
107 else:
108 PROPERTY_CLASSES = set(('builtins.property', 'abc.abstractproperty'))
109 ABC_METHODS = set(('abc.abstractproperty', 'abc.abstractmethod',
110 'abc.abstractclassmethod', 'abc.abstractstaticmethod'))
111
112 def _determine_function_name_type(node):
113 """Determine the name type whose regex the a function's name should match.
114
115 :param node: A function node.
116 :returns: One of ('function', 'method', 'attr')
117 """
118 if not node.is_method():
119 return 'function'
120 if node.decorators:
121 decorators = node.decorators.nodes
122 else:
123 decorators = []
124 for decorator in decorators:
125 # If the function is a property (decorated with @property
126 # or @abc.abstractproperty), the name type is 'attr'.
127 if (isinstance(decorator, astroid.Name) or
128 (isinstance(decorator, astroid.Getattr) and
129 decorator.attrname == 'abstractproperty')):
130 infered = safe_infer(decorator)
131 if infered and infered.qname() in PROPERTY_CLASSES:
132 return 'attr'
133 # If the function is decorated using the prop_method.{setter,getter}
134 # form, treat it like an attribute as well.
135 elif (isinstance(decorator, astroid.Getattr) and
136 decorator.attrname in ('setter', 'deleter')):
137 return 'attr'
138 return 'method'
139
140 def decorated_with_abc(func):
141 """ Determine if the `func` node is decorated
142 with `abc` decorators (abstractmethod et co.)
143 """
144 if func.decorators:
145 for node in func.decorators.nodes:
146 try:
147 infered = node.infer().next()
148 except InferenceError:
149 continue
150 if infered and infered.qname() in ABC_METHODS:
151 return True
152
153 def has_abstract_methods(node):
154 """ Determine if the given `node` has
155 abstract methods, defined with `abc` module.
156 """
157 return any(decorated_with_abc(meth)
158 for meth in node.mymethods())
159
64 def report_by_type_stats(sect, stats, old_stats): 160 def report_by_type_stats(sect, stats, old_stats):
65 """make a report of 161 """make a report of
66 162
67 * percentage of different types documented 163 * percentage of different types documented
68 * percentage of different types with a bad name 164 * percentage of different types with a bad name
69 """ 165 """
70 # percentage of different types documented and/or with a bad name 166 # percentage of different types documented and/or with a bad name
71 nice_stats = {} 167 nice_stats = {}
72 for node_type in ('module', 'class', 'method', 'function'): 168 for node_type in ('module', 'class', 'method', 'function'):
73 try: 169 try:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 """return True if the object is a method redefined via decorator. 201 """return True if the object is a method redefined via decorator.
106 202
107 For example: 203 For example:
108 @property 204 @property
109 def x(self): return self._x 205 def x(self): return self._x
110 @x.setter 206 @x.setter
111 def x(self, value): self._x = value 207 def x(self, value): self._x = value
112 """ 208 """
113 if node.decorators: 209 if node.decorators:
114 for decorator in node.decorators.nodes: 210 for decorator in node.decorators.nodes:
115 if (isinstance(decorator, astng.Getattr) and 211 if (isinstance(decorator, astroid.Getattr) and
116 decorator.expr.name == node.name): 212 getattr(decorator.expr, 'name', None) == node.name):
117 return True 213 return True
118 return False 214 return False
119 215
120 class _BasicChecker(BaseChecker): 216 class _BasicChecker(BaseChecker):
121 __implements__ = IASTNGChecker 217 __implements__ = IAstroidChecker
122 name = 'basic' 218 name = 'basic'
123 219
124 class BasicErrorChecker(_BasicChecker): 220 class BasicErrorChecker(_BasicChecker):
125 msgs = { 221 msgs = {
126 'E0100': ('__init__ method is a generator', 222 'E0100': ('__init__ method is a generator',
127 'Used when the special class method __init__ is turned into a ' 223 'init-is-generator',
128 'generator by a yield in its body.'), 224 'Used when the special class method __init__ is turned into a '
129 'E0101': ('Explicit return in __init__', 225 'generator by a yield in its body.'),
130 'Used when the special class method __init__ has an explicit \ 226 'E0101': ('Explicit return in __init__',
131 return value.'), 227 'return-in-init',
132 'E0102': ('%s already defined line %s', 228 'Used when the special class method __init__ has an explicit '
133 'Used when a function / class / method is redefined.'), 229 'return value.'),
134 'E0103': ('%r not properly in loop', 230 'E0102': ('%s already defined line %s',
135 'Used when break or continue keywords are used outside a loop.'), 231 'function-redefined',
232 'Used when a function / class / method is redefined.'),
233 'E0103': ('%r not properly in loop',
234 'not-in-loop',
235 'Used when break or continue keywords are used outside a loop. '),
236 'E0104': ('Return outside function',
237 'return-outside-function',
238 'Used when a "return" statement is found outside a function or '
239 'method.'),
240 'E0105': ('Yield outside function',
241 'yield-outside-function',
242 'Used when a "yield" statement is found outside a function or '
243 'method.'),
244 'E0106': ('Return with argument inside generator',
245 'return-arg-in-generator',
246 'Used when a "return" statement with an argument is found '
247 'outside in a generator function or method (e.g. with some '
248 '"yield" statements).',
249 {'maxversion': (3, 3)}),
250 'E0107': ("Use of the non-existent %s operator",
251 'nonexistent-operator',
252 "Used when you attempt to use the C-style pre-increment or"
253 "pre-decrement operator -- and ++, which doesn't exist in Pyth on."),
254 'E0108': ('Duplicate argument name %s in function definition',
255 'duplicate-argument-name',
256 'Duplicate argument names in function definitions are syntax'
257 ' errors.'),
258 'E0110': ('Abstract class with abstract methods instantiated',
259 'abstract-class-instantiated',
260 'Used when an abstract class with `abc.ABCMeta` as metaclass '
261 'has abstract methods and is instantiated.',
262 {'minversion': (3, 0)}),
263 'W0120': ('Else clause on loop without a break statement',
264 'useless-else-on-loop',
265 'Loops should only have an else clause if they can exit early '
266 'with a break statement, otherwise the statements under else '
267 'should be on the same scope as the loop itself.'),
268 }
136 269
137 'E0104': ('Return outside function', 270 @check_messages('function-redefined')
138 'Used when a "return" statement is found outside a function or '
139 'method.'),
140 'E0105': ('Yield outside function',
141 'Used when a "yield" statement is found outside a function or '
142 'method.'),
143 'E0106': ('Return with argument inside generator',
144 'Used when a "return" statement with an argument is found '
145 'outside in a generator function or method (e.g. with some '
146 '"yield" statements).'),
147 'E0107': ("Use of the non-existent %s operator",
148 "Used when you attempt to use the C-style pre-increment or"
149 "pre-decrement operator -- and ++, which doesn't exist in Python." ),
150 }
151
152 def __init__(self, linter):
153 _BasicChecker.__init__(self, linter)
154
155 @check_messages('E0102')
156 def visit_class(self, node): 271 def visit_class(self, node):
157 self._check_redefinition('class', node) 272 self._check_redefinition('class', node)
158 273
159 @check_messages('E0100', 'E0101', 'E0102', 'E0106') 274 @check_messages('init-is-generator', 'return-in-init',
275 'function-redefined', 'return-arg-in-generator',
276 'duplicate-argument-name')
160 def visit_function(self, node): 277 def visit_function(self, node):
161 if not redefined_by_decorator(node): 278 if not redefined_by_decorator(node):
162 self._check_redefinition(node.is_method() and 'method' or 'function' , node) 279 self._check_redefinition(node.is_method() and 'method' or 'function' , node)
163 # checks for max returns, branch, return in __init__ 280 # checks for max returns, branch, return in __init__
164 returns = node.nodes_of_class(astng.Return, 281 returns = node.nodes_of_class(astroid.Return,
165 skip_klass=(astng.Function, astng.Class)) 282 skip_klass=(astroid.Function, astroid.Clas s))
166 if node.is_method() and node.name == '__init__': 283 if node.is_method() and node.name == '__init__':
167 if node.is_generator(): 284 if node.is_generator():
168 self.add_message('E0100', node=node) 285 self.add_message('init-is-generator', node=node)
169 else: 286 else:
170 values = [r.value for r in returns] 287 values = [r.value for r in returns]
171 if [v for v in values if not (v is None or 288 # Are we returning anything but None from constructors
172 (isinstance(v, astng.Const) and v.value is None) 289 if [v for v in values
173 or (isinstance(v, astng.Name) and v.name == 'None'))]: 290 if not (v is None or
174 self.add_message('E0101', node=node) 291 (isinstance(v, astroid.Const) and v.value is Non e) or
292 (isinstance(v, astroid.Name) and v.name == 'Non e')
293 )]:
294 self.add_message('return-in-init', node=node)
175 elif node.is_generator(): 295 elif node.is_generator():
176 # make sure we don't mix non-None returns and yields 296 # make sure we don't mix non-None returns and yields
177 for retnode in returns: 297 if not PY33:
178 if isinstance(retnode.value, astng.Const) and \ 298 for retnode in returns:
179 retnode.value.value is not None: 299 if isinstance(retnode.value, astroid.Const) and \
180 self.add_message('E0106', node=node, 300 retnode.value.value is not None:
181 line=retnode.fromlineno) 301 self.add_message('return-arg-in-generator', node=node,
302 line=retnode.fromlineno)
303 # Check for duplicate names
304 args = set()
305 for name in node.argnames():
306 if name in args:
307 self.add_message('duplicate-argument-name', node=node, args=(nam e,))
308 else:
309 args.add(name)
182 310
183 @check_messages('E0104') 311
312 @check_messages('return-outside-function')
184 def visit_return(self, node): 313 def visit_return(self, node):
185 if not isinstance(node.frame(), astng.Function): 314 if not isinstance(node.frame(), astroid.Function):
186 self.add_message('E0104', node=node) 315 self.add_message('return-outside-function', node=node)
187 316
188 @check_messages('E0105') 317 @check_messages('yield-outside-function')
189 def visit_yield(self, node): 318 def visit_yield(self, node):
190 if not isinstance(node.frame(), astng.Function): 319 if not isinstance(node.frame(), (astroid.Function, astroid.Lambda)):
191 self.add_message('E0105', node=node) 320 self.add_message('yield-outside-function', node=node)
192 321
193 @check_messages('E0103') 322 @check_messages('not-in-loop')
194 def visit_continue(self, node): 323 def visit_continue(self, node):
195 self._check_in_loop(node, 'continue') 324 self._check_in_loop(node, 'continue')
196 325
197 @check_messages('E0103') 326 @check_messages('not-in-loop')
198 def visit_break(self, node): 327 def visit_break(self, node):
199 self._check_in_loop(node, 'break') 328 self._check_in_loop(node, 'break')
200 329
201 @check_messages('E0107') 330 @check_messages('useless-else-on-loop')
331 def visit_for(self, node):
332 self._check_else_on_loop(node)
333
334 @check_messages('useless-else-on-loop')
335 def visit_while(self, node):
336 self._check_else_on_loop(node)
337
338 @check_messages('nonexistent-operator')
202 def visit_unaryop(self, node): 339 def visit_unaryop(self, node):
203 """check use of the non-existent ++ adn -- operator operator""" 340 """check use of the non-existent ++ and -- operator operator"""
204 if ((node.op in '+-') and 341 if ((node.op in '+-') and
205 isinstance(node.operand, astng.UnaryOp) and 342 isinstance(node.operand, astroid.UnaryOp) and
206 (node.operand.op == node.op)): 343 (node.operand.op == node.op)):
207 self.add_message('E0107', node=node, args=node.op*2) 344 self.add_message('nonexistent-operator', node=node, args=node.op*2)
345
346 @check_messages('abstract-class-instantiated')
347 def visit_callfunc(self, node):
348 """ Check instantiating abstract class with
349 abc.ABCMeta as metaclass.
350 """
351 try:
352 infered = node.func.infer().next()
353 except astroid.InferenceError:
354 return
355 if not isinstance(infered, astroid.Class):
356 return
357 # __init__ was called
358 metaclass = infered.metaclass()
359 if metaclass is None:
360 # Python 3.4 has `abc.ABC`, which won't be detected
361 # by ClassNode.metaclass()
362 for ancestor in infered.ancestors():
363 if (ancestor.qname() == 'abc.ABC' and
364 has_abstract_methods(infered)):
365 self.add_message('abstract-class-instantiated', node=node)
366 break
367 return
368 if (metaclass.qname() == 'abc.ABCMeta' and
369 has_abstract_methods(infered)):
370 self.add_message('abstract-class-instantiated', node=node)
371
372 def _check_else_on_loop(self, node):
373 """Check that any loop with an else clause has a break statement."""
374 if node.orelse and not _loop_exits_early(node):
375 self.add_message('useless-else-on-loop', node=node,
376 # This is not optimal, but the line previous
377 # to the first statement in the else clause
378 # will usually be the one that contains the else:.
379 line=node.orelse[0].lineno - 1)
208 380
209 def _check_in_loop(self, node, node_name): 381 def _check_in_loop(self, node, node_name):
210 """check that a node is inside a for or while loop""" 382 """check that a node is inside a for or while loop"""
211 _node = node.parent 383 _node = node.parent
212 while _node: 384 while _node:
213 if isinstance(_node, (astng.For, astng.While)): 385 if isinstance(_node, (astroid.For, astroid.While)):
214 break 386 break
215 _node = _node.parent 387 _node = _node.parent
216 else: 388 else:
217 self.add_message('E0103', node=node, args=node_name) 389 self.add_message('not-in-loop', node=node, args=node_name)
218 390
219 def _check_redefinition(self, redeftype, node): 391 def _check_redefinition(self, redeftype, node):
220 """check for redefinition of a function / method / class name""" 392 """check for redefinition of a function / method / class name"""
221 defined_self = node.parent.frame()[node.name] 393 defined_self = node.parent.frame()[node.name]
222 if defined_self is not node and not are_exclusive(node, defined_self): 394 if defined_self is not node and not are_exclusive(node, defined_self):
223 self.add_message('E0102', node=node, 395 self.add_message('function-redefined', node=node,
224 args=(redeftype, defined_self.fromlineno)) 396 args=(redeftype, defined_self.fromlineno))
225 397
226 398
227 399
228 class BasicChecker(_BasicChecker): 400 class BasicChecker(_BasicChecker):
229 """checks for : 401 """checks for :
230 * doc strings 402 * doc strings
231 * modules / classes / functions / methods / arguments / variables name
232 * number of arguments, local variables, branches, returns and statements in 403 * number of arguments, local variables, branches, returns and statements in
233 functions, methods 404 functions, methods
234 * required module attributes 405 * required module attributes
235 * dangerous default values as arguments 406 * dangerous default values as arguments
236 * redefinition of function / method / class 407 * redefinition of function / method / class
237 * uses of the global statement 408 * uses of the global statement
238 """ 409 """
239 410
240 __implements__ = IASTNGChecker 411 __implements__ = IAstroidChecker
241 412
242 name = 'basic' 413 name = 'basic'
243 msgs = { 414 msgs = {
244 'W0101': ('Unreachable code', 415 'W0101': ('Unreachable code',
245 'Used when there is some code behind a "return" or "raise" \ 416 'unreachable',
246 statement, which will never be accessed.'), 417 'Used when there is some code behind a "return" or "raise" '
247 'W0102': ('Dangerous default value %s as argument', 418 'statement, which will never be accessed.'),
248 'Used when a mutable value as list or dictionary is detected in \ 419 'W0102': ('Dangerous default value %s as argument',
249 a default value for an argument.'), 420 'dangerous-default-value',
250 'W0104': ('Statement seems to have no effect', 421 'Used when a mutable value as list or dictionary is detected i n '
251 'Used when a statement doesn\'t have (or at least seems to) \ 422 'a default value for an argument.'),
252 any effect.'), 423 'W0104': ('Statement seems to have no effect',
253 'W0105': ('String statement has no effect', 424 'pointless-statement',
254 'Used when a string is used as a statement (which of course \ 425 'Used when a statement doesn\'t have (or at least seems to) '
255 has no effect). This is a particular case of W0104 with its \ 426 'any effect.'),
256 own message so you can easily disable it if you\'re using \ 427 'W0105': ('String statement has no effect',
257 those strings as documentation, instead of comments.'), 428 'pointless-string-statement',
258 'W0106': ('Expression "%s" is assigned to nothing', 429 'Used when a string is used as a statement (which of course '
259 'Used when an expression that is not a function call is assigned\ 430 'has no effect). This is a particular case of W0104 with its '
260 to nothing. Probably something else was intended.'), 431 'own message so you can easily disable it if you\'re using '
261 'W0108': ('Lambda may not be necessary', 432 'those strings as documentation, instead of comments.'),
262 'Used when the body of a lambda expression is a function call \ 433 'W0106': ('Expression "%s" is assigned to nothing',
263 on the same argument list as the lambda itself; such lambda \ 434 'expression-not-assigned',
264 expressions are in all but a few cases replaceable with the \ 435 'Used when an expression that is not a function call is assign ed '
265 function being called in the body of the lambda.'), 436 'to nothing. Probably something else was intended.'),
266 'W0109': ("Duplicate key %r in dictionary", 437 'W0108': ('Lambda may not be necessary',
267 "Used when a dictionary expression binds the same key multiple \ 438 'unnecessary-lambda',
268 times."), 439 'Used when the body of a lambda expression is a function call '
269 'W0122': ('Use of the exec statement', 440 'on the same argument list as the lambda itself; such lambda '
270 'Used when you use the "exec" statement, to discourage its \ 441 'expressions are in all but a few cases replaceable with the '
271 usage. That doesn\'t mean you can not use it !'), 442 'function being called in the body of the lambda.'),
443 'W0109': ("Duplicate key %r in dictionary",
444 'duplicate-key',
445 'Used when a dictionary expression binds the same key multiple '
446 'times.'),
447 'W0122': ('Use of exec',
448 'exec-used',
449 'Used when you use the "exec" statement (function for Python 3 ), to discourage its '
450 'usage. That doesn\'t mean you can not use it !'),
451 'W0123': ('Use of eval',
452 'eval-used',
453 'Used when you use the "eval" function, to discourage its '
454 'usage. Consider using `ast.literal_eval` for safely evaluatin g '
455 'strings containing Python expressions '
456 'from untrusted sources. '),
457 'W0141': ('Used builtin function %r',
458 'bad-builtin',
459 'Used when a black listed builtin function is used (see the '
460 'bad-function option). Usual black listed functions are the on es '
461 'like map, or filter , where Python offers now some cleaner '
462 'alternative like list comprehension.'),
463 'W0142': ('Used * or ** magic',
464 'star-args',
465 'Used when a function or method is called using `*args` or '
466 '`**kwargs` to dispatch arguments. This doesn\'t improve '
467 'readability and should be used with care.'),
468 'W0150': ("%s statement in finally block may swallow exception",
469 'lost-exception',
470 'Used when a break or a return statement is found inside the '
471 'finally clause of a try...finally block: the exceptions raise d '
472 'in the try clause will be silently swallowed instead of being '
473 're-raised.'),
474 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?',
475 'assert-on-tuple',
476 'A call of assert on a tuple will always evaluate to true if '
477 'the tuple is not empty, and will always evaluate to false if '
478 'it is.'),
479 'W0121': ('Use raise ErrorClass(args) instead of raise ErrorClass, args. ',
480 'old-raise-syntax',
481 "Used when the alternate raise syntax 'raise foo, bar' is used "
482 "instead of 'raise foo(bar)'.",
483 {'maxversion': (3, 0)}),
272 484
273 'W0141': ('Used builtin function %r', 485 'C0121': ('Missing required attribute "%s"', # W0103
274 'Used when a black listed builtin function is used (see the ' 486 'missing-module-attribute',
275 'bad-function option). Usual black listed functions are the ones ' 487 'Used when an attribute required for modules is missing.'),
276 'like map, or filter , where Python offers now some cleaner '
277 'alternative like list comprehension.'),
278 'W0142': ('Used * or ** magic',
279 'Used when a function or method is called using `*args` or '
280 '`**kwargs` to dispatch arguments. This doesn\'t improve '
281 'readability and should be used with care.'),
282 'W0150': ("%s statement in finally block may swallow exception",
283 "Used when a break or a return statement is found inside the \
284 finally clause of a try...finally block: the exceptions raised \
285 in the try clause will be silently swallowed instead of being \
286 re-raised."),
287 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?',
288 'A call of assert on a tuple will always evaluate to true if '
289 'the tuple is not empty, and will always evaluate to false if '
290 'it is.'),
291 488
292 'C0121': ('Missing required attribute "%s"', # W0103 489 'E0109': ('Missing argument to reversed()',
293 'Used when an attribute required for modules is missing.'), 490 'missing-reversed-argument',
491 'Used when reversed() builtin didn\'t receive an argument.'),
492 'E0111': ('The first reversed() argument is not a sequence',
493 'bad-reversed-sequence',
494 'Used when the first argument to reversed() builtin '
495 'isn\'t a sequence (does not implement __reversed__, '
496 'nor __getitem__ and __len__'),
294 497
295 } 498 }
296 499
297 options = (('required-attributes', 500 options = (('required-attributes',
298 {'default' : (), 'type' : 'csv', 501 {'default' : (), 'type' : 'csv',
299 'metavar' : '<attributes>', 502 'metavar' : '<attributes>',
300 'help' : 'Required attributes for module, separated by a ' 503 'help' : 'Required attributes for module, separated by a '
301 'comma'} 504 'comma'}
302 ), 505 ),
303 ('bad-functions', 506 ('bad-functions',
304 {'default' : ('map', 'filter', 'apply', 'input'), 507 {'default' : BAD_FUNCTIONS,
305 'type' :'csv', 'metavar' : '<builtin function names>', 508 'type' :'csv', 'metavar' : '<builtin function names>',
306 'help' : 'List of builtins function names that should not be ' 509 'help' : 'List of builtins function names that should not be '
307 'used, separated by a comma'} 510 'used, separated by a comma'}
308 ), 511 ),
309 ) 512 )
310 reports = ( ('RP0101', 'Statistics by type', report_by_type_stats), ) 513 reports = (('RP0101', 'Statistics by type', report_by_type_stats),)
311 514
312 def __init__(self, linter): 515 def __init__(self, linter):
313 _BasicChecker.__init__(self, linter) 516 _BasicChecker.__init__(self, linter)
314 self.stats = None 517 self.stats = None
315 self._tryfinallys = None 518 self._tryfinallys = None
316 519
317 def open(self): 520 def open(self):
318 """initialize visit variables and statistics 521 """initialize visit variables and statistics
319 """ 522 """
320 self._tryfinallys = [] 523 self._tryfinallys = []
321 self.stats = self.linter.add_stats(module=0, function=0, 524 self.stats = self.linter.add_stats(module=0, function=0,
322 method=0, class_=0) 525 method=0, class_=0)
323 526 @check_messages('missing-module-attribute')
324 def visit_module(self, node): 527 def visit_module(self, node):
325 """check module name, docstring and required arguments 528 """check module name, docstring and required arguments
326 """ 529 """
327 self.stats['module'] += 1 530 self.stats['module'] += 1
328 for attr in self.config.required_attributes: 531 for attr in self.config.required_attributes:
329 if attr not in node: 532 if attr not in node:
330 self.add_message('C0121', node=node, args=attr) 533 self.add_message('missing-module-attribute', node=node, args=att r)
331 534
332 def visit_class(self, node): 535 def visit_class(self, node):
333 """check module name, docstring and redefinition 536 """check module name, docstring and redefinition
334 increment branch counter 537 increment branch counter
335 """ 538 """
336 self.stats['class'] += 1 539 self.stats['class'] += 1
337 540
338 @check_messages('W0104', 'W0105') 541 @check_messages('pointless-statement', 'pointless-string-statement',
542 'expression-not-assigned')
339 def visit_discard(self, node): 543 def visit_discard(self, node):
340 """check for various kind of statements without effect""" 544 """check for various kind of statements without effect"""
341 expr = node.value 545 expr = node.value
342 if isinstance(expr, astng.Const) and isinstance(expr.value, 546 if isinstance(expr, astroid.Const) and isinstance(expr.value,
343 basestring): 547 basestring):
344 # treat string statement in a separated message 548 # treat string statement in a separated message
345 self.add_message('W0105', node=node) 549 # Handle PEP-257 attribute docstrings.
550 # An attribute docstring is defined as being a string right after
551 # an assignment at the module level, class level or __init__ level.
552 scope = expr.scope()
553 if isinstance(scope, (astroid.Class, astroid.Module, astroid.Functio n)):
554 if isinstance(scope, astroid.Function) and scope.name != '__init __':
555 pass
556 else:
557 sibling = expr.previous_sibling()
558 if (sibling is not None and sibling.scope() is scope and
559 isinstance(sibling, astroid.Assign)):
560 return
561 self.add_message('pointless-string-statement', node=node)
346 return 562 return
347 # ignore if this is : 563 # ignore if this is :
348 # * a direct function call 564 # * a direct function call
349 # * the unique child of a try/except body 565 # * the unique child of a try/except body
350 # * a yield (which are wrapped by a discard node in _ast XXX) 566 # * a yield (which are wrapped by a discard node in _ast XXX)
351 # warn W0106 if we have any underlying function call (we can't predict 567 # warn W0106 if we have any underlying function call (we can't predict
352 # side effects), else W0104 568 # side effects), else pointless-statement
353 if (isinstance(expr, (astng.Yield, astng.CallFunc)) or 569 if (isinstance(expr, (astroid.Yield, astroid.CallFunc)) or
354 (isinstance(node.parent, astng.TryExcept) and 570 (isinstance(node.parent, astroid.TryExcept) and
355 node.parent.body == [node])): 571 node.parent.body == [node])):
356 return 572 return
357 if any(expr.nodes_of_class(astng.CallFunc)): 573 if any(expr.nodes_of_class(astroid.CallFunc)):
358 self.add_message('W0106', node=node, args=expr.as_string()) 574 self.add_message('expression-not-assigned', node=node,
575 args=expr.as_string())
359 else: 576 else:
360 self.add_message('W0104', node=node) 577 self.add_message('pointless-statement', node=node)
361 578
362 @check_messages('W0108') 579 @check_messages('unnecessary-lambda')
363 def visit_lambda(self, node): 580 def visit_lambda(self, node):
364 """check whether or not the lambda is suspicious 581 """check whether or not the lambda is suspicious
365 """ 582 """
366 # if the body of the lambda is a call expression with the same 583 # if the body of the lambda is a call expression with the same
367 # argument list as the lambda itself, then the lambda is 584 # argument list as the lambda itself, then the lambda is
368 # possibly unnecessary and at least suspicious. 585 # possibly unnecessary and at least suspicious.
369 if node.args.defaults: 586 if node.args.defaults:
370 # If the arguments of the lambda include defaults, then a 587 # If the arguments of the lambda include defaults, then a
371 # judgment cannot be made because there is no way to check 588 # judgment cannot be made because there is no way to check
372 # that the defaults defined by the lambda are the same as 589 # that the defaults defined by the lambda are the same as
373 # the defaults defined by the function called in the body 590 # the defaults defined by the function called in the body
374 # of the lambda. 591 # of the lambda.
375 return 592 return
376 call = node.body 593 call = node.body
377 if not isinstance(call, astng.CallFunc): 594 if not isinstance(call, astroid.CallFunc):
378 # The body of the lambda must be a function call expression 595 # The body of the lambda must be a function call expression
379 # for the lambda to be unnecessary. 596 # for the lambda to be unnecessary.
380 return 597 return
381 # XXX are lambda still different with astng >= 0.18 ? 598 # XXX are lambda still different with astroid >= 0.18 ?
382 # *args and **kwargs need to be treated specially, since they 599 # *args and **kwargs need to be treated specially, since they
383 # are structured differently between the lambda and the function 600 # are structured differently between the lambda and the function
384 # call (in the lambda they appear in the args.args list and are 601 # call (in the lambda they appear in the args.args list and are
385 # indicated as * and ** by two bits in the lambda's flags, but 602 # indicated as * and ** by two bits in the lambda's flags, but
386 # in the function call they are omitted from the args list and 603 # in the function call they are omitted from the args list and
387 # are indicated by separate attributes on the function call node). 604 # are indicated by separate attributes on the function call node).
388 ordinary_args = list(node.args.args) 605 ordinary_args = list(node.args.args)
389 if node.args.kwarg: 606 if node.args.kwarg:
390 if (not call.kwargs 607 if (not call.kwargs
391 or not isinstance(call.kwargs, astng.Name) 608 or not isinstance(call.kwargs, astroid.Name)
392 or node.args.kwarg != call.kwargs.name): 609 or node.args.kwarg != call.kwargs.name):
393 return 610 return
394 elif call.kwargs: 611 elif call.kwargs:
395 return 612 return
396 if node.args.vararg: 613 if node.args.vararg:
397 if (not call.starargs 614 if (not call.starargs
398 or not isinstance(call.starargs, astng.Name) 615 or not isinstance(call.starargs, astroid.Name)
399 or node.args.vararg != call.starargs.name): 616 or node.args.vararg != call.starargs.name):
400 return 617 return
401 elif call.starargs: 618 elif call.starargs:
402 return 619 return
403 # The "ordinary" arguments must be in a correspondence such that: 620 # The "ordinary" arguments must be in a correspondence such that:
404 # ordinary_args[i].name == call.args[i].name. 621 # ordinary_args[i].name == call.args[i].name.
405 if len(ordinary_args) != len(call.args): 622 if len(ordinary_args) != len(call.args):
406 return 623 return
407 for i in xrange(len(ordinary_args)): 624 for i in xrange(len(ordinary_args)):
408 if not isinstance(call.args[i], astng.Name): 625 if not isinstance(call.args[i], astroid.Name):
409 return 626 return
410 if node.args.args[i].name != call.args[i].name: 627 if node.args.args[i].name != call.args[i].name:
411 return 628 return
412 self.add_message('W0108', line=node.fromlineno, node=node) 629 if (isinstance(node.body.func, astroid.Getattr) and
630 isinstance(node.body.func.expr, astroid.CallFunc)):
631 # Chained call, the intermediate call might
632 # return something else (but we don't check that, yet).
633 return
634 self.add_message('unnecessary-lambda', line=node.fromlineno, node=node)
413 635
636 @check_messages('dangerous-default-value')
414 def visit_function(self, node): 637 def visit_function(self, node):
415 """check function name, docstring, arguments, redefinition, 638 """check function name, docstring, arguments, redefinition,
416 variable names, max locals 639 variable names, max locals
417 """ 640 """
418 self.stats[node.is_method() and 'method' or 'function'] += 1 641 self.stats[node.is_method() and 'method' or 'function'] += 1
419 # check for dangerous default values as arguments 642 # check for dangerous default values as arguments
420 for default in node.args.defaults: 643 for default in node.args.defaults:
421 try: 644 try:
422 value = default.infer().next() 645 value = default.infer().next()
423 except astng.InferenceError: 646 except astroid.InferenceError:
424 continue 647 continue
425 if isinstance(value, (astng.Dict, astng.List)): 648 builtins = astroid.bases.BUILTINS
649 if (isinstance(value, astroid.Instance) and
650 value.qname() in ['.'.join([builtins, x]) for x in ('set', ' dict', 'list')]):
426 if value is default: 651 if value is default:
427 msg = default.as_string() 652 msg = default.as_string()
653 elif type(value) is astroid.Instance:
654 msg = '%s (%s)' % (default.as_string(), value.qname())
428 else: 655 else:
429 msg = '%s (%s)' % (default.as_string(), value.as_string()) 656 msg = '%s (%s)' % (default.as_string(), value.as_string())
430 self.add_message('W0102', node=node, args=(msg,)) 657 self.add_message('dangerous-default-value', node=node, args=(msg ,))
431 658
432 @check_messages('W0101', 'W0150') 659 @check_messages('unreachable', 'lost-exception')
433 def visit_return(self, node): 660 def visit_return(self, node):
434 """1 - check is the node has a right sibling (if so, that's some 661 """1 - check is the node has a right sibling (if so, that's some
435 unreachable code) 662 unreachable code)
436 2 - check is the node is inside the finally clause of a try...finally 663 2 - check is the node is inside the finally clause of a try...finally
437 block 664 block
438 """ 665 """
439 self._check_unreachable(node) 666 self._check_unreachable(node)
440 # Is it inside final body of a try...finally bloc ? 667 # Is it inside final body of a try...finally bloc ?
441 self._check_not_in_finally(node, 'return', (astng.Function,)) 668 self._check_not_in_finally(node, 'return', (astroid.Function,))
442 669
443 @check_messages('W0101') 670 @check_messages('unreachable')
444 def visit_continue(self, node): 671 def visit_continue(self, node):
445 """check is the node has a right sibling (if so, that's some unreachable 672 """check is the node has a right sibling (if so, that's some unreachable
446 code) 673 code)
447 """ 674 """
448 self._check_unreachable(node) 675 self._check_unreachable(node)
449 676
450 @check_messages('W0101', 'W0150') 677 @check_messages('unreachable', 'lost-exception')
451 def visit_break(self, node): 678 def visit_break(self, node):
452 """1 - check is the node has a right sibling (if so, that's some 679 """1 - check is the node has a right sibling (if so, that's some
453 unreachable code) 680 unreachable code)
454 2 - check is the node is inside the finally clause of a try...finally 681 2 - check is the node is inside the finally clause of a try...finally
455 block 682 block
456 """ 683 """
457 # 1 - Is it right sibling ? 684 # 1 - Is it right sibling ?
458 self._check_unreachable(node) 685 self._check_unreachable(node)
459 # 2 - Is it inside final body of a try...finally bloc ? 686 # 2 - Is it inside final body of a try...finally bloc ?
460 self._check_not_in_finally(node, 'break', (astng.For, astng.While,)) 687 self._check_not_in_finally(node, 'break', (astroid.For, astroid.While,))
461 688
462 @check_messages('W0101') 689 @check_messages('unreachable', 'old-raise-syntax')
463 def visit_raise(self, node): 690 def visit_raise(self, node):
464 """check is the node has a right sibling (if so, that's some unreachable 691 """check if the node has a right sibling (if so, that's some unreachable
465 code) 692 code)
466 """ 693 """
467 self._check_unreachable(node) 694 self._check_unreachable(node)
695 if sys.version_info >= (3, 0):
696 return
697 if node.exc is not None and node.inst is not None and node.tback is None :
698 self.add_message('old-raise-syntax', node=node)
468 699
469 @check_messages('W0122') 700 @check_messages('exec-used')
470 def visit_exec(self, node): 701 def visit_exec(self, node):
471 """just print a warning on exec statements""" 702 """just print a warning on exec statements"""
472 self.add_message('W0122', node=node) 703 self.add_message('exec-used', node=node)
473 704
474 @check_messages('W0141', 'W0142') 705 @check_messages('bad-builtin', 'star-args', 'eval-used',
706 'exec-used', 'missing-reversed-argument',
707 'bad-reversed-sequence')
475 def visit_callfunc(self, node): 708 def visit_callfunc(self, node):
476 """visit a CallFunc node -> check if this is not a blacklisted builtin 709 """visit a CallFunc node -> check if this is not a blacklisted builtin
477 call and check for * or ** use 710 call and check for * or ** use
478 """ 711 """
479 if isinstance(node.func, astng.Name): 712 if isinstance(node.func, astroid.Name):
480 name = node.func.name 713 name = node.func.name
481 # ignore the name if it's not a builtin (i.e. not defined in the 714 # ignore the name if it's not a builtin (i.e. not defined in the
482 # locals nor globals scope) 715 # locals nor globals scope)
483 if not (name in node.frame() or 716 if not (name in node.frame() or
484 name in node.root()): 717 name in node.root()):
718 if name == 'exec':
719 self.add_message('exec-used', node=node)
720 elif name == 'reversed':
721 self._check_reversed(node)
722 elif name == 'eval':
723 self.add_message('eval-used', node=node)
485 if name in self.config.bad_functions: 724 if name in self.config.bad_functions:
486 self.add_message('W0141', node=node, args=name) 725 self.add_message('bad-builtin', node=node, args=name)
487 if node.starargs or node.kwargs: 726 if node.starargs or node.kwargs:
488 scope = node.scope() 727 scope = node.scope()
489 if isinstance(scope, astng.Function): 728 if isinstance(scope, astroid.Function):
490 toprocess = [(n, vn) for (n, vn) in ((node.starargs, scope.args. vararg), 729 toprocess = [(n, vn) for (n, vn) in ((node.starargs, scope.args. vararg),
491 (node.kwargs, scope.args.kw arg)) if n] 730 (node.kwargs, scope.args.kw arg)) if n]
492 if toprocess: 731 if toprocess:
493 for cfnode, fargname in toprocess[:]: 732 for cfnode, fargname in toprocess[:]:
494 if getattr(cfnode, 'name', None) == fargname: 733 if getattr(cfnode, 'name', None) == fargname:
495 toprocess.remove((cfnode, fargname)) 734 toprocess.remove((cfnode, fargname))
496 if not toprocess: 735 if not toprocess:
497 return # W0142 can be skipped 736 return # star-args can be skipped
498 self.add_message('W0142', node=node.func) 737 self.add_message('star-args', node=node.func)
499 738
500 @check_messages('W0199') 739 @check_messages('assert-on-tuple')
501 def visit_assert(self, node): 740 def visit_assert(self, node):
502 """check the use of an assert statement on a tuple.""" 741 """check the use of an assert statement on a tuple."""
503 if node.fail is None and isinstance(node.test, astng.Tuple) and \ 742 if node.fail is None and isinstance(node.test, astroid.Tuple) and \
504 len(node.test.elts) == 2: 743 len(node.test.elts) == 2:
505 self.add_message('W0199', line=node.fromlineno, node=node) 744 self.add_message('assert-on-tuple', node=node)
506 745
507 @check_messages('W0109') 746 @check_messages('duplicate-key')
508 def visit_dict(self, node): 747 def visit_dict(self, node):
509 """check duplicate key in dictionary""" 748 """check duplicate key in dictionary"""
510 keys = set() 749 keys = set()
511 for k, v in node.items: 750 for k, _ in node.items:
512 if isinstance(k, astng.Const): 751 if isinstance(k, astroid.Const):
513 key = k.value 752 key = k.value
514 if key in keys: 753 if key in keys:
515 self.add_message('W0109', node=node, args=key) 754 self.add_message('duplicate-key', node=node, args=key)
516 keys.add(key) 755 keys.add(key)
517 756
518 def visit_tryfinally(self, node): 757 def visit_tryfinally(self, node):
519 """update try...finally flag""" 758 """update try...finally flag"""
520 self._tryfinallys.append(node) 759 self._tryfinallys.append(node)
521 760
522 def leave_tryfinally(self, node): 761 def leave_tryfinally(self, node):
523 """update try...finally flag""" 762 """update try...finally flag"""
524 self._tryfinallys.pop() 763 self._tryfinallys.pop()
525 764
526 def _check_unreachable(self, node): 765 def _check_unreachable(self, node):
527 """check unreachable code""" 766 """check unreachable code"""
528 unreach_stmt = node.next_sibling() 767 unreach_stmt = node.next_sibling()
529 if unreach_stmt is not None: 768 if unreach_stmt is not None:
530 self.add_message('W0101', node=unreach_stmt) 769 self.add_message('unreachable', node=unreach_stmt)
531 770
532 def _check_not_in_finally(self, node, node_name, breaker_classes=()): 771 def _check_not_in_finally(self, node, node_name, breaker_classes=()):
533 """check that a node is not inside a finally clause of a 772 """check that a node is not inside a finally clause of a
534 try...finally statement. 773 try...finally statement.
535 If we found before a try...finally bloc a parent which its type is 774 If we found before a try...finally bloc a parent which its type is
536 in breaker_classes, we skip the whole check.""" 775 in breaker_classes, we skip the whole check."""
537 # if self._tryfinallys is empty, we're not a in try...finally bloc 776 # if self._tryfinallys is empty, we're not a in try...finally bloc
538 if not self._tryfinallys: 777 if not self._tryfinallys:
539 return 778 return
540 # the node could be a grand-grand...-children of the try...finally 779 # the node could be a grand-grand...-children of the try...finally
541 _parent = node.parent 780 _parent = node.parent
542 _node = node 781 _node = node
543 while _parent and not isinstance(_parent, breaker_classes): 782 while _parent and not isinstance(_parent, breaker_classes):
544 if hasattr(_parent, 'finalbody') and _node in _parent.finalbody: 783 if hasattr(_parent, 'finalbody') and _node in _parent.finalbody:
545 self.add_message('W0150', node=node, args=node_name) 784 self.add_message('lost-exception', node=node, args=node_name)
546 return 785 return
547 _node = _parent 786 _node = _parent
548 _parent = _node.parent 787 _parent = _node.parent
549 788
789 def _check_reversed(self, node):
790 """ check that the argument to `reversed` is a sequence """
791 try:
792 argument = safe_infer(get_argument_from_call(node, position=0))
793 except NoSuchArgumentError:
794 self.add_message('missing-reversed-argument', node=node)
795 else:
796 if argument is astroid.YES:
797 return
798 if argument is None:
799 # nothing was infered
800 # try to see if we have iter()
801 if isinstance(node.args[0], astroid.CallFunc):
802 try:
803 func = node.args[0].func.infer().next()
804 except InferenceError:
805 return
806 if (getattr(func, 'name', None) == 'iter' and
807 is_builtin_object(func)):
808 self.add_message('bad-reversed-sequence', node=node)
809 return
550 810
811 if isinstance(argument, astroid.Instance):
812 if (argument._proxied.name == 'dict' and
813 is_builtin_object(argument._proxied)):
814 self.add_message('bad-reversed-sequence', node=node)
815 return
816 elif any(ancestor.name == 'dict' and is_builtin_object(ancestor)
817 for ancestor in argument._proxied.ancestors()):
818 # mappings aren't accepted by reversed()
819 self.add_message('bad-reversed-sequence', node=node)
820 return
821
822 for methods in REVERSED_METHODS:
823 for meth in methods:
824 try:
825 argument.getattr(meth)
826 except astroid.NotFoundError:
827 break
828 else:
829 break
830 else:
831 # check if it is a .deque. It doesn't seem that
832 # we can retrieve special methods
833 # from C implemented constructs
834 if argument._proxied.qname().endswith(".deque"):
835 return
836 self.add_message('bad-reversed-sequence', node=node)
837 elif not isinstance(argument, (astroid.List, astroid.Tuple)):
838 # everything else is not a proper sequence for reversed()
839 self.add_message('bad-reversed-sequence', node=node)
840
841 _NAME_TYPES = {
842 'module': (MOD_NAME_RGX, 'module'),
843 'const': (CONST_NAME_RGX, 'constant'),
844 'class': (CLASS_NAME_RGX, 'class'),
845 'function': (DEFAULT_NAME_RGX, 'function'),
846 'method': (DEFAULT_NAME_RGX, 'method'),
847 'attr': (DEFAULT_NAME_RGX, 'attribute'),
848 'argument': (DEFAULT_NAME_RGX, 'argument'),
849 'variable': (DEFAULT_NAME_RGX, 'variable'),
850 'class_attribute': (CLASS_ATTRIBUTE_RGX, 'class attribute'),
851 'inlinevar': (COMP_VAR_RGX, 'inline iteration'),
852 }
853
854 def _create_naming_options():
855 name_options = []
856 for name_type, (rgx, human_readable_name) in _NAME_TYPES.iteritems():
857 name_type = name_type.replace('_', '-')
858 name_options.append((
859 '%s-rgx' % (name_type,),
860 {'default': rgx, 'type': 'regexp', 'metavar': '<regexp>',
861 'help': 'Regular expression matching correct %s names' % (human_rea dable_name,)}))
862 name_options.append((
863 '%s-name-hint' % (name_type,),
864 {'default': rgx.pattern, 'type': 'string', 'metavar': '<string>',
865 'help': 'Naming hint for %s names' % (human_readable_name,)}))
866 return tuple(name_options)
551 867
552 class NameChecker(_BasicChecker): 868 class NameChecker(_BasicChecker):
553 msgs = { 869 msgs = {
554 'C0102': ('Black listed name "%s"', 870 'C0102': ('Black listed name "%s"',
555 'Used when the name is listed in the black list (unauthorized \ 871 'blacklisted-name',
556 names).'), 872 'Used when the name is listed in the black list (unauthorized '
557 'C0103': ('Invalid name "%s" (should match %s)', 873 'names).'),
558 'Used when the name doesn\'t match the regular expression \ 874 'C0103': ('Invalid %s name "%s"%s',
559 associated to its type (constant, variable, class...).'), 875 'invalid-name',
876 'Used when the name doesn\'t match the regular expression '
877 'associated to its type (constant, variable, class...).'),
878 }
560 879
561 } 880 options = (('good-names',
562 options = (('module-rgx',
563 {'default' : MOD_NAME_RGX,
564 'type' :'regexp', 'metavar' : '<regexp>',
565 'help' : 'Regular expression which should only match correct '
566 'module names'}
567 ),
568 ('const-rgx',
569 {'default' : CONST_NAME_RGX,
570 'type' :'regexp', 'metavar' : '<regexp>',
571 'help' : 'Regular expression which should only match correct '
572 'module level names'}
573 ),
574 ('class-rgx',
575 {'default' : CLASS_NAME_RGX,
576 'type' :'regexp', 'metavar' : '<regexp>',
577 'help' : 'Regular expression which should only match correct '
578 'class names'}
579 ),
580 ('function-rgx',
581 {'default' : DEFAULT_NAME_RGX,
582 'type' :'regexp', 'metavar' : '<regexp>',
583 'help' : 'Regular expression which should only match correct '
584 'function names'}
585 ),
586 ('method-rgx',
587 {'default' : DEFAULT_NAME_RGX,
588 'type' :'regexp', 'metavar' : '<regexp>',
589 'help' : 'Regular expression which should only match correct '
590 'method names'}
591 ),
592 ('attr-rgx',
593 {'default' : DEFAULT_NAME_RGX,
594 'type' :'regexp', 'metavar' : '<regexp>',
595 'help' : 'Regular expression which should only match correct '
596 'instance attribute names'}
597 ),
598 ('argument-rgx',
599 {'default' : DEFAULT_NAME_RGX,
600 'type' :'regexp', 'metavar' : '<regexp>',
601 'help' : 'Regular expression which should only match correct '
602 'argument names'}),
603 ('variable-rgx',
604 {'default' : DEFAULT_NAME_RGX,
605 'type' :'regexp', 'metavar' : '<regexp>',
606 'help' : 'Regular expression which should only match correct '
607 'variable names'}
608 ),
609 ('inlinevar-rgx',
610 {'default' : COMP_VAR_RGX,
611 'type' :'regexp', 'metavar' : '<regexp>',
612 'help' : 'Regular expression which should only match correct '
613 'list comprehension / generator expression variable \
614 names'}
615 ),
616 # XXX use set
617 ('good-names',
618 {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'), 881 {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'),
619 'type' :'csv', 'metavar' : '<names>', 882 'type' :'csv', 'metavar' : '<names>',
620 'help' : 'Good variable names which should always be accepted,' 883 'help' : 'Good variable names which should always be accepted,'
621 ' separated by a comma'} 884 ' separated by a comma'}
622 ), 885 ),
623 ('bad-names', 886 ('bad-names',
624 {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'), 887 {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'),
625 'type' :'csv', 'metavar' : '<names>', 888 'type' :'csv', 'metavar' : '<names>',
626 'help' : 'Bad variable names which should always be refused, ' 889 'help' : 'Bad variable names which should always be refused, '
627 'separated by a comma'} 890 'separated by a comma'}
628 ), 891 ),
629 ) 892 ('name-group',
893 {'default' : (),
894 'type' :'csv', 'metavar' : '<name1:name2>',
895 'help' : ('Colon-delimited sets of names that determine each'
896 ' other\'s naming style when the name regexes'
897 ' allow several styles.')}
898 ),
899 ('include-naming-hint',
900 {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>',
901 'help': 'Include a hint for the correct naming format with inva lid-name'}
902 ),
903 ) + _create_naming_options()
904
905
906 def __init__(self, linter):
907 _BasicChecker.__init__(self, linter)
908 self._name_category = {}
909 self._name_group = {}
630 910
631 def open(self): 911 def open(self):
632 self.stats = self.linter.add_stats(badname_module=0, 912 self.stats = self.linter.add_stats(badname_module=0,
633 badname_class=0, badname_function=0, 913 badname_class=0, badname_function=0,
634 badname_method=0, badname_attr=0, 914 badname_method=0, badname_attr=0,
635 badname_const=0, 915 badname_const=0,
636 badname_variable=0, 916 badname_variable=0,
637 badname_inlinevar=0, 917 badname_inlinevar=0,
638 badname_argument=0) 918 badname_argument=0,
919 badname_class_attribute=0)
920 for group in self.config.name_group:
921 for name_type in group.split(':'):
922 self._name_group[name_type] = 'group_%s' % (group,)
639 923
640 @check_messages('C0102', 'C0103') 924 @check_messages('blacklisted-name', 'invalid-name')
641 def visit_module(self, node): 925 def visit_module(self, node):
642 self._check_name('module', node.name.split('.')[-1], node) 926 self._check_name('module', node.name.split('.')[-1], node)
643 927
644 @check_messages('C0102', 'C0103') 928 @check_messages('blacklisted-name', 'invalid-name')
645 def visit_class(self, node): 929 def visit_class(self, node):
646 self._check_name('class', node.name, node) 930 self._check_name('class', node.name, node)
647 for attr, anodes in node.instance_attrs.items(): 931 for attr, anodes in node.instance_attrs.iteritems():
648 self._check_name('attr', attr, anodes[0]) 932 if not list(node.instance_attr_ancestors(attr)):
933 self._check_name('attr', attr, anodes[0])
649 934
650 @check_messages('C0102', 'C0103') 935 @check_messages('blacklisted-name', 'invalid-name')
651 def visit_function(self, node): 936 def visit_function(self, node):
652 self._check_name(node.is_method() and 'method' or 'function', 937 # Do not emit any warnings if the method is just an implementation
938 # of a base class method.
939 if node.is_method() and overrides_a_method(node.parent.frame(), node.nam e):
940 return
941 self._check_name(_determine_function_name_type(node),
653 node.name, node) 942 node.name, node)
654 # check arguments name 943 # Check argument names
655 args = node.args.args 944 args = node.args.args
656 if args is not None: 945 if args is not None:
657 self._recursive_check_names(args, node) 946 self._recursive_check_names(args, node)
658 947
659 @check_messages('C0102', 'C0103') 948 @check_messages('blacklisted-name', 'invalid-name')
949 def visit_global(self, node):
950 for name in node.names:
951 self._check_name('const', name, node)
952
953 @check_messages('blacklisted-name', 'invalid-name')
660 def visit_assname(self, node): 954 def visit_assname(self, node):
661 """check module level assigned names""" 955 """check module level assigned names"""
662 frame = node.frame() 956 frame = node.frame()
663 ass_type = node.ass_type() 957 ass_type = node.ass_type()
664 if isinstance(ass_type, (astng.Comprehension, astng.Comprehension)): 958 if isinstance(ass_type, astroid.Comprehension):
665 self._check_name('inlinevar', node.name, node) 959 self._check_name('inlinevar', node.name, node)
666 elif isinstance(frame, astng.Module): 960 elif isinstance(frame, astroid.Module):
667 if isinstance(ass_type, astng.Assign) and not in_loop(ass_type): 961 if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type):
668 self._check_name('const', node.name, node) 962 if isinstance(safe_infer(ass_type.value), astroid.Class):
669 elif isinstance(ass_type, astng.ExceptHandler): 963 self._check_name('class', node.name, node)
964 else:
965 self._check_name('const', node.name, node)
966 elif isinstance(ass_type, astroid.ExceptHandler):
670 self._check_name('variable', node.name, node) 967 self._check_name('variable', node.name, node)
671 elif isinstance(frame, astng.Function): 968 elif isinstance(frame, astroid.Function):
672 # global introduced variable aren't in the function locals 969 # global introduced variable aren't in the function locals
673 if node.name in frame: 970 if node.name in frame and node.name not in frame.argnames():
674 self._check_name('variable', node.name, node) 971 self._check_name('variable', node.name, node)
972 elif isinstance(frame, astroid.Class):
973 if not list(frame.local_attr_ancestors(node.name)):
974 self._check_name('class_attribute', node.name, node)
675 975
676 def _recursive_check_names(self, args, node): 976 def _recursive_check_names(self, args, node):
677 """check names in a possibly recursive list <arg>""" 977 """check names in a possibly recursive list <arg>"""
678 for arg in args: 978 for arg in args:
679 if isinstance(arg, astng.AssName): 979 if isinstance(arg, astroid.AssName):
680 self._check_name('argument', arg.name, node) 980 self._check_name('argument', arg.name, node)
681 else: 981 else:
682 self._recursive_check_names(arg.elts, node) 982 self._recursive_check_names(arg.elts, node)
683 983
984 def _find_name_group(self, node_type):
985 return self._name_group.get(node_type, node_type)
986
987 def _is_multi_naming_match(self, match):
988 return (match is not None and
989 match.lastgroup is not None and
990 match.lastgroup not in EXEMPT_NAME_CATEGORIES)
991
684 def _check_name(self, node_type, name, node): 992 def _check_name(self, node_type, name, node):
685 """check for a name using the type's regexp""" 993 """check for a name using the type's regexp"""
686 if is_inside_except(node): 994 if is_inside_except(node):
687 clobbering, _ = clobber_in_except(node) 995 clobbering, _ = clobber_in_except(node)
688 if clobbering: 996 if clobbering:
689 return 997 return
690
691 if name in self.config.good_names: 998 if name in self.config.good_names:
692 return 999 return
693 if name in self.config.bad_names: 1000 if name in self.config.bad_names:
694 self.stats['badname_' + node_type] += 1 1001 self.stats['badname_' + node_type] += 1
695 self.add_message('C0102', node=node, args=name) 1002 self.add_message('blacklisted-name', node=node, args=name)
696 return 1003 return
697 regexp = getattr(self.config, node_type + '_rgx') 1004 regexp = getattr(self.config, node_type + '_rgx')
698 if regexp.match(name) is None: 1005 match = regexp.match(name)
699 self.add_message('C0103', node=node, args=(name, regexp.pattern)) 1006
1007 if self._is_multi_naming_match(match):
1008 name_group = self._find_name_group(node_type)
1009 if name_group not in self._name_category:
1010 self._name_category[name_group] = match.lastgroup
1011 elif self._name_category[name_group] != match.lastgroup:
1012 match = None
1013
1014 if match is None:
1015 type_label = _NAME_TYPES[node_type][1]
1016 hint = ''
1017 if self.config.include_naming_hint:
1018 hint = ' (hint: %s)' % (getattr(self.config, node_type + '_name_ hint'))
1019 self.add_message('invalid-name', node=node, args=(type_label, name, hint))
700 self.stats['badname_' + node_type] += 1 1020 self.stats['badname_' + node_type] += 1
701 1021
702 1022
703 class DocStringChecker(_BasicChecker): 1023 class DocStringChecker(_BasicChecker):
704 msgs = { 1024 msgs = {
705 'C0111': ('Missing docstring', # W0131 1025 'C0111': ('Missing %s docstring', # W0131
706 'Used when a module, function, class or method has no docstring.\ 1026 'missing-docstring',
707 Some special methods like __init__ doesn\'t necessary require a \ 1027 'Used when a module, function, class or method has no docstrin g.'
708 docstring.'), 1028 'Some special methods like __init__ doesn\'t necessary require a '
709 'C0112': ('Empty docstring', # W0132 1029 'docstring.'),
710 'Used when a module, function, class or method has an empty \ 1030 'C0112': ('Empty %s docstring', # W0132
711 docstring (it would be too easy ;).'), 1031 'empty-docstring',
712 } 1032 'Used when a module, function, class or method has an empty '
1033 'docstring (it would be too easy ;).'),
1034 }
713 options = (('no-docstring-rgx', 1035 options = (('no-docstring-rgx',
714 {'default' : NO_REQUIRED_DOC_RGX, 1036 {'default' : NO_REQUIRED_DOC_RGX,
715 'type' : 'regexp', 'metavar' : '<regexp>', 1037 'type' : 'regexp', 'metavar' : '<regexp>',
716 'help' : 'Regular expression which should only match ' 1038 'help' : 'Regular expression which should only match '
717 'functions or classes name which do not require a ' 1039 'function or class names that do not require a '
718 'docstring'} 1040 'docstring.'}
719 ), 1041 ),
720 ) 1042 ('docstring-min-length',
1043 {'default' : -1,
1044 'type' : 'int', 'metavar' : '<int>',
1045 'help': ('Minimum line length for functions/classes that'
1046 ' require docstrings, shorter ones are exempt.')}
1047 ),
1048 )
1049
721 1050
722 def open(self): 1051 def open(self):
723 self.stats = self.linter.add_stats(undocumented_module=0, 1052 self.stats = self.linter.add_stats(undocumented_module=0,
724 undocumented_function=0, 1053 undocumented_function=0,
725 undocumented_method=0, 1054 undocumented_method=0,
726 undocumented_class=0) 1055 undocumented_class=0)
727 1056 @check_messages('missing-docstring', 'empty-docstring')
728 def visit_module(self, node): 1057 def visit_module(self, node):
729 self._check_docstring('module', node) 1058 self._check_docstring('module', node)
730 1059
1060 @check_messages('missing-docstring', 'empty-docstring')
731 def visit_class(self, node): 1061 def visit_class(self, node):
732 if self.config.no_docstring_rgx.match(node.name) is None: 1062 if self.config.no_docstring_rgx.match(node.name) is None:
733 self._check_docstring('class', node) 1063 self._check_docstring('class', node)
734 1064 @check_messages('missing-docstring', 'empty-docstring')
735 def visit_function(self, node): 1065 def visit_function(self, node):
736 if self.config.no_docstring_rgx.match(node.name) is None: 1066 if self.config.no_docstring_rgx.match(node.name) is None:
737 ftype = node.is_method() and 'method' or 'function' 1067 ftype = node.is_method() and 'method' or 'function'
738 if isinstance(node.parent.frame(), astng.Class): 1068 if isinstance(node.parent.frame(), astroid.Class):
739 overridden = False 1069 overridden = False
740 # check if node is from a method overridden by its ancestor 1070 # check if node is from a method overridden by its ancestor
741 for ancestor in node.parent.frame().ancestors(): 1071 for ancestor in node.parent.frame().ancestors():
742 if node.name in ancestor and \ 1072 if node.name in ancestor and \
743 isinstance(ancestor[node.name], astng.Function): 1073 isinstance(ancestor[node.name], astroid.Function):
744 overridden = True 1074 overridden = True
745 break 1075 break
746 if not overridden: 1076 self._check_docstring(ftype, node,
747 self._check_docstring(ftype, node) 1077 report_missing=not overridden)
748 else: 1078 else:
749 self._check_docstring(ftype, node) 1079 self._check_docstring(ftype, node)
750 1080
751 def _check_docstring(self, node_type, node): 1081 def _check_docstring(self, node_type, node, report_missing=True):
752 """check the node has a non empty docstring""" 1082 """check the node has a non empty docstring"""
753 docstring = node.doc 1083 docstring = node.doc
754 if docstring is None: 1084 if docstring is None:
1085 if not report_missing:
1086 return
1087 if node.body:
1088 lines = node.body[-1].lineno - node.body[0].lineno + 1
1089 else:
1090 lines = 0
1091 max_lines = self.config.docstring_min_length
1092
1093 if node_type != 'module' and max_lines > -1 and lines < max_lines:
1094 return
755 self.stats['undocumented_'+node_type] += 1 1095 self.stats['undocumented_'+node_type] += 1
756 self.add_message('C0111', node=node) 1096 if (node.body and isinstance(node.body[0], astroid.Discard) and
1097 isinstance(node.body[0].value, astroid.CallFunc)):
1098 # Most likely a string with a format call. Let's see.
1099 func = safe_infer(node.body[0].value.func)
1100 if (isinstance(func, astroid.BoundMethod)
1101 and isinstance(func.bound, astroid.Instance)):
1102 # Strings in Python 3, others in Python 2.
1103 if PY3K and func.bound.name == 'str':
1104 return
1105 elif func.bound.name in ('str', 'unicode', 'bytes'):
1106 return
1107 self.add_message('missing-docstring', node=node, args=(node_type,))
757 elif not docstring.strip(): 1108 elif not docstring.strip():
758 self.stats['undocumented_'+node_type] += 1 1109 self.stats['undocumented_'+node_type] += 1
759 self.add_message('C0112', node=node) 1110 self.add_message('empty-docstring', node=node, args=(node_type,))
760 1111
761 1112
762 class PassChecker(_BasicChecker): 1113 class PassChecker(_BasicChecker):
763 """check is the pass statement is really necessary""" 1114 """check if the pass statement is really necessary"""
764 msgs = {'W0107': ('Unnecessary pass statement', 1115 msgs = {'W0107': ('Unnecessary pass statement',
1116 'unnecessary-pass',
765 'Used when a "pass" statement that can be avoided is ' 1117 'Used when a "pass" statement that can be avoided is '
766 'encountered.)'), 1118 'encountered.'),
767 } 1119 }
768 1120 @check_messages('unnecessary-pass')
769 def visit_pass(self, node): 1121 def visit_pass(self, node):
770 if len(node.parent.child_sequence(node)) > 1: 1122 if len(node.parent.child_sequence(node)) > 1:
771 self.add_message('W0107', node=node) 1123 self.add_message('unnecessary-pass', node=node)
1124
1125
1126 class LambdaForComprehensionChecker(_BasicChecker):
1127 """check for using a lambda where a comprehension would do.
1128
1129 See <http://www.artima.com/weblogs/viewpost.jsp?thread=98196>
1130 where GvR says comprehensions would be clearer.
1131 """
1132
1133 msgs = {'W0110': ('map/filter on lambda could be replaced by comprehension',
1134 'deprecated-lambda',
1135 'Used when a lambda is the first argument to "map" or '
1136 '"filter". It could be clearer as a list '
1137 'comprehension or generator expression.',
1138 {'maxversion': (3, 0)}),
1139 }
1140
1141 @check_messages('deprecated-lambda')
1142 def visit_callfunc(self, node):
1143 """visit a CallFunc node, check if map or filter are called with a
1144 lambda
1145 """
1146 if not node.args:
1147 return
1148 if not isinstance(node.args[0], astroid.Lambda):
1149 return
1150 infered = safe_infer(node.func)
1151 if (is_builtin_object(infered)
1152 and infered.name in ['map', 'filter']):
1153 self.add_message('deprecated-lambda', node=node)
772 1154
773 1155
774 def register(linter): 1156 def register(linter):
775 """required method to auto register this checker""" 1157 """required method to auto register this checker"""
776 linter.register_checker(BasicErrorChecker(linter)) 1158 linter.register_checker(BasicErrorChecker(linter))
777 linter.register_checker(BasicChecker(linter)) 1159 linter.register_checker(BasicChecker(linter))
778 linter.register_checker(NameChecker(linter)) 1160 linter.register_checker(NameChecker(linter))
779 linter.register_checker(DocStringChecker(linter)) 1161 linter.register_checker(DocStringChecker(linter))
780 linter.register_checker(PassChecker(linter)) 1162 linter.register_checker(PassChecker(linter))
1163 linter.register_checker(LambdaForComprehensionChecker(linter))
OLDNEW
« no previous file with comments | « third_party/pylint/checkers/__init__.py ('k') | third_party/pylint/checkers/classes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698