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

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

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
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
« 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-2013 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
2 # Copyright (c) 2009-2010 Arista Networks, Inc.
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 3 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # Copyright (c) 2009-2010 Arista Networks, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify it under 4 # This program is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software 5 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later 6 # Foundation; either version 2 of the License, or (at your option) any later
8 # version. 7 # version.
9 # 8 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT 9 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 # 12 #
14 # You should have received a copy of the GNU General Public License along with 13 # You should have received a copy of the GNU General Public License along with
15 # this program; if not, write to the Free Software Foundation, Inc., 14 # this program; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 """basic checker for Python code""" 16 """basic checker for Python code"""
18 17
19 import sys 18
20 import astroid 19 from logilab import astng
21 from logilab.common.ureports import Table 20 from logilab.common.ureports import Table
22 from astroid import are_exclusive, InferenceError 21 from logilab.astng import are_exclusive
23 import astroid.bases
24 22
25 from pylint.interfaces import IAstroidChecker 23 from pylint.interfaces import IASTNGChecker
26 from pylint.utils import EmptyReport
27 from pylint.reporters import diff_string 24 from pylint.reporters import diff_string
28 from pylint.checkers import BaseChecker 25 from pylint.checkers import BaseChecker, EmptyReport
29 from pylint.checkers.utils import ( 26 from pylint.checkers.utils import check_messages, clobber_in_except, is_inside_e xcept
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 )
39 27
40 28
41 import re 29 import re
42 30
43 # regex for class/function/variable/constant name 31 # regex for class/function/variable/constant name
44 CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$') 32 CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$')
45 MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$') 33 MOD_NAME_RGX = re.compile('(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$')
46 CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$') 34 CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$')
47 COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$') 35 COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$')
48 DEFAULT_NAME_RGX = re.compile('[a-z_][a-z0-9_]{2,30}$') 36 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}|(__.*__))$')
50 # do not require a doc string on system methods 37 # do not require a doc string on system methods
51 NO_REQUIRED_DOC_RGX = re.compile('__.*__') 38 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'))
64 39
65 del re 40 del re
66 41
67 def in_loop(node): 42 def in_loop(node):
68 """return True if the node is inside a kind of for loop""" 43 """return True if the node is inside a kind of for loop"""
69 parent = node.parent 44 parent = node.parent
70 while parent is not None: 45 while parent is not None:
71 if isinstance(parent, (astroid.For, astroid.ListComp, astroid.SetComp, 46 if isinstance(parent, (astng.For, astng.ListComp, astng.SetComp,
72 astroid.DictComp, astroid.GenExpr)): 47 astng.DictComp, astng.GenExpr)):
73 return True 48 return True
74 parent = parent.parent 49 parent = parent.parent
75 return False 50 return False
76 51
77 def in_nested_list(nested_list, obj): 52 def in_nested_list(nested_list, obj):
78 """return true if the object is an element of <nested_list> or of a nested 53 """return true if the object is an element of <nested_list> or of a nested
79 list 54 list
80 """ 55 """
81 for elmt in nested_list: 56 for elmt in nested_list:
82 if isinstance(elmt, (list, tuple)): 57 if isinstance(elmt, (list, tuple)):
83 if in_nested_list(elmt, obj): 58 if in_nested_list(elmt, obj):
84 return True 59 return True
85 elif elmt == obj: 60 elif elmt == obj:
86 return True 61 return True
87 return False 62 return False
88 63
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
160 def report_by_type_stats(sect, stats, old_stats): 64 def report_by_type_stats(sect, stats, old_stats):
161 """make a report of 65 """make a report of
162 66
163 * percentage of different types documented 67 * percentage of different types documented
164 * percentage of different types with a bad name 68 * percentage of different types with a bad name
165 """ 69 """
166 # percentage of different types documented and/or with a bad name 70 # percentage of different types documented and/or with a bad name
167 nice_stats = {} 71 nice_stats = {}
168 for node_type in ('module', 'class', 'method', 'function'): 72 for node_type in ('module', 'class', 'method', 'function'):
169 try: 73 try:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 """return True if the object is a method redefined via decorator. 105 """return True if the object is a method redefined via decorator.
202 106
203 For example: 107 For example:
204 @property 108 @property
205 def x(self): return self._x 109 def x(self): return self._x
206 @x.setter 110 @x.setter
207 def x(self, value): self._x = value 111 def x(self, value): self._x = value
208 """ 112 """
209 if node.decorators: 113 if node.decorators:
210 for decorator in node.decorators.nodes: 114 for decorator in node.decorators.nodes:
211 if (isinstance(decorator, astroid.Getattr) and 115 if (isinstance(decorator, astng.Getattr) and
212 getattr(decorator.expr, 'name', None) == node.name): 116 decorator.expr.name == node.name):
213 return True 117 return True
214 return False 118 return False
215 119
216 class _BasicChecker(BaseChecker): 120 class _BasicChecker(BaseChecker):
217 __implements__ = IAstroidChecker 121 __implements__ = IASTNGChecker
218 name = 'basic' 122 name = 'basic'
219 123
220 class BasicErrorChecker(_BasicChecker): 124 class BasicErrorChecker(_BasicChecker):
221 msgs = { 125 msgs = {
222 'E0100': ('__init__ method is a generator', 126 'E0100': ('__init__ method is a generator',
223 'init-is-generator', 127 'Used when the special class method __init__ is turned into a '
224 'Used when the special class method __init__ is turned into a ' 128 'generator by a yield in its body.'),
225 'generator by a yield in its body.'), 129 'E0101': ('Explicit return in __init__',
226 'E0101': ('Explicit return in __init__', 130 'Used when the special class method __init__ has an explicit \
227 'return-in-init', 131 return value.'),
228 'Used when the special class method __init__ has an explicit ' 132 'E0102': ('%s already defined line %s',
229 'return value.'), 133 'Used when a function / class / method is redefined.'),
230 'E0102': ('%s already defined line %s', 134 'E0103': ('%r not properly in loop',
231 'function-redefined', 135 'Used when break or continue keywords are used outside a loop.'),
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 }
269 136
270 @check_messages('function-redefined') 137 'E0104': ('Return outside function',
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')
271 def visit_class(self, node): 156 def visit_class(self, node):
272 self._check_redefinition('class', node) 157 self._check_redefinition('class', node)
273 158
274 @check_messages('init-is-generator', 'return-in-init', 159 @check_messages('E0100', 'E0101', 'E0102', 'E0106')
275 'function-redefined', 'return-arg-in-generator',
276 'duplicate-argument-name')
277 def visit_function(self, node): 160 def visit_function(self, node):
278 if not redefined_by_decorator(node): 161 if not redefined_by_decorator(node):
279 self._check_redefinition(node.is_method() and 'method' or 'function' , node) 162 self._check_redefinition(node.is_method() and 'method' or 'function' , node)
280 # checks for max returns, branch, return in __init__ 163 # checks for max returns, branch, return in __init__
281 returns = node.nodes_of_class(astroid.Return, 164 returns = node.nodes_of_class(astng.Return,
282 skip_klass=(astroid.Function, astroid.Clas s)) 165 skip_klass=(astng.Function, astng.Class))
283 if node.is_method() and node.name == '__init__': 166 if node.is_method() and node.name == '__init__':
284 if node.is_generator(): 167 if node.is_generator():
285 self.add_message('init-is-generator', node=node) 168 self.add_message('E0100', node=node)
286 else: 169 else:
287 values = [r.value for r in returns] 170 values = [r.value for r in returns]
288 # Are we returning anything but None from constructors 171 if [v for v in values if not (v is None or
289 if [v for v in values 172 (isinstance(v, astng.Const) and v.value is None)
290 if not (v is None or 173 or (isinstance(v, astng.Name) and v.name == 'None'))]:
291 (isinstance(v, astroid.Const) and v.value is Non e) or 174 self.add_message('E0101', node=node)
292 (isinstance(v, astroid.Name) and v.name == 'Non e')
293 )]:
294 self.add_message('return-in-init', node=node)
295 elif node.is_generator(): 175 elif node.is_generator():
296 # make sure we don't mix non-None returns and yields 176 # make sure we don't mix non-None returns and yields
297 if not PY33: 177 for retnode in returns:
298 for retnode in returns: 178 if isinstance(retnode.value, astng.Const) and \
299 if isinstance(retnode.value, astroid.Const) and \ 179 retnode.value.value is not None:
300 retnode.value.value is not None: 180 self.add_message('E0106', node=node,
301 self.add_message('return-arg-in-generator', node=node, 181 line=retnode.fromlineno)
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)
310 182
183 @check_messages('E0104')
184 def visit_return(self, node):
185 if not isinstance(node.frame(), astng.Function):
186 self.add_message('E0104', node=node)
311 187
312 @check_messages('return-outside-function') 188 @check_messages('E0105')
313 def visit_return(self, node): 189 def visit_yield(self, node):
314 if not isinstance(node.frame(), astroid.Function): 190 if not isinstance(node.frame(), astng.Function):
315 self.add_message('return-outside-function', node=node) 191 self.add_message('E0105', node=node)
316 192
317 @check_messages('yield-outside-function') 193 @check_messages('E0103')
318 def visit_yield(self, node):
319 if not isinstance(node.frame(), (astroid.Function, astroid.Lambda)):
320 self.add_message('yield-outside-function', node=node)
321
322 @check_messages('not-in-loop')
323 def visit_continue(self, node): 194 def visit_continue(self, node):
324 self._check_in_loop(node, 'continue') 195 self._check_in_loop(node, 'continue')
325 196
326 @check_messages('not-in-loop') 197 @check_messages('E0103')
327 def visit_break(self, node): 198 def visit_break(self, node):
328 self._check_in_loop(node, 'break') 199 self._check_in_loop(node, 'break')
329 200
330 @check_messages('useless-else-on-loop') 201 @check_messages('E0107')
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')
339 def visit_unaryop(self, node): 202 def visit_unaryop(self, node):
340 """check use of the non-existent ++ and -- operator operator""" 203 """check use of the non-existent ++ adn -- operator operator"""
341 if ((node.op in '+-') and 204 if ((node.op in '+-') and
342 isinstance(node.operand, astroid.UnaryOp) and 205 isinstance(node.operand, astng.UnaryOp) and
343 (node.operand.op == node.op)): 206 (node.operand.op == node.op)):
344 self.add_message('nonexistent-operator', node=node, args=node.op*2) 207 self.add_message('E0107', 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)
380 208
381 def _check_in_loop(self, node, node_name): 209 def _check_in_loop(self, node, node_name):
382 """check that a node is inside a for or while loop""" 210 """check that a node is inside a for or while loop"""
383 _node = node.parent 211 _node = node.parent
384 while _node: 212 while _node:
385 if isinstance(_node, (astroid.For, astroid.While)): 213 if isinstance(_node, (astng.For, astng.While)):
386 break 214 break
387 _node = _node.parent 215 _node = _node.parent
388 else: 216 else:
389 self.add_message('not-in-loop', node=node, args=node_name) 217 self.add_message('E0103', node=node, args=node_name)
390 218
391 def _check_redefinition(self, redeftype, node): 219 def _check_redefinition(self, redeftype, node):
392 """check for redefinition of a function / method / class name""" 220 """check for redefinition of a function / method / class name"""
393 defined_self = node.parent.frame()[node.name] 221 defined_self = node.parent.frame()[node.name]
394 if defined_self is not node and not are_exclusive(node, defined_self): 222 if defined_self is not node and not are_exclusive(node, defined_self):
395 self.add_message('function-redefined', node=node, 223 self.add_message('E0102', node=node,
396 args=(redeftype, defined_self.fromlineno)) 224 args=(redeftype, defined_self.fromlineno))
397 225
398 226
399 227
400 class BasicChecker(_BasicChecker): 228 class BasicChecker(_BasicChecker):
401 """checks for : 229 """checks for :
402 * doc strings 230 * doc strings
231 * modules / classes / functions / methods / arguments / variables name
403 * number of arguments, local variables, branches, returns and statements in 232 * number of arguments, local variables, branches, returns and statements in
404 functions, methods 233 functions, methods
405 * required module attributes 234 * required module attributes
406 * dangerous default values as arguments 235 * dangerous default values as arguments
407 * redefinition of function / method / class 236 * redefinition of function / method / class
408 * uses of the global statement 237 * uses of the global statement
409 """ 238 """
410 239
411 __implements__ = IAstroidChecker 240 __implements__ = IASTNGChecker
412 241
413 name = 'basic' 242 name = 'basic'
414 msgs = { 243 msgs = {
415 'W0101': ('Unreachable code', 244 'W0101': ('Unreachable code',
416 'unreachable', 245 'Used when there is some code behind a "return" or "raise" \
417 'Used when there is some code behind a "return" or "raise" ' 246 statement, which will never be accessed.'),
418 'statement, which will never be accessed.'), 247 'W0102': ('Dangerous default value %s as argument',
419 'W0102': ('Dangerous default value %s as argument', 248 'Used when a mutable value as list or dictionary is detected in \
420 'dangerous-default-value', 249 a default value for an argument.'),
421 'Used when a mutable value as list or dictionary is detected i n ' 250 'W0104': ('Statement seems to have no effect',
422 'a default value for an argument.'), 251 'Used when a statement doesn\'t have (or at least seems to) \
423 'W0104': ('Statement seems to have no effect', 252 any effect.'),
424 'pointless-statement', 253 'W0105': ('String statement has no effect',
425 'Used when a statement doesn\'t have (or at least seems to) ' 254 'Used when a string is used as a statement (which of course \
426 'any effect.'), 255 has no effect). This is a particular case of W0104 with its \
427 'W0105': ('String statement has no effect', 256 own message so you can easily disable it if you\'re using \
428 'pointless-string-statement', 257 those strings as documentation, instead of comments.'),
429 'Used when a string is used as a statement (which of course ' 258 'W0106': ('Expression "%s" is assigned to nothing',
430 'has no effect). This is a particular case of W0104 with its ' 259 'Used when an expression that is not a function call is assigned\
431 'own message so you can easily disable it if you\'re using ' 260 to nothing. Probably something else was intended.'),
432 'those strings as documentation, instead of comments.'), 261 'W0108': ('Lambda may not be necessary',
433 'W0106': ('Expression "%s" is assigned to nothing', 262 'Used when the body of a lambda expression is a function call \
434 'expression-not-assigned', 263 on the same argument list as the lambda itself; such lambda \
435 'Used when an expression that is not a function call is assign ed ' 264 expressions are in all but a few cases replaceable with the \
436 'to nothing. Probably something else was intended.'), 265 function being called in the body of the lambda.'),
437 'W0108': ('Lambda may not be necessary', 266 'W0109': ("Duplicate key %r in dictionary",
438 'unnecessary-lambda', 267 "Used when a dictionary expression binds the same key multiple \
439 'Used when the body of a lambda expression is a function call ' 268 times."),
440 'on the same argument list as the lambda itself; such lambda ' 269 'W0122': ('Use of the exec statement',
441 'expressions are in all but a few cases replaceable with the ' 270 'Used when you use the "exec" statement, to discourage its \
442 'function being called in the body of the lambda.'), 271 usage. That doesn\'t mean you can not use it !'),
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)}),
484 272
485 'C0121': ('Missing required attribute "%s"', # W0103 273 'W0141': ('Used builtin function %r',
486 'missing-module-attribute', 274 'Used when a black listed builtin function is used (see the '
487 'Used when an attribute required for modules is missing.'), 275 'bad-function option). Usual black listed functions are the ones '
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.'),
488 291
489 'E0109': ('Missing argument to reversed()', 292 'C0121': ('Missing required attribute "%s"', # W0103
490 'missing-reversed-argument', 293 'Used when an attribute required for modules is missing.'),
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__'),
497 294
498 } 295 }
499 296
500 options = (('required-attributes', 297 options = (('required-attributes',
501 {'default' : (), 'type' : 'csv', 298 {'default' : (), 'type' : 'csv',
502 'metavar' : '<attributes>', 299 'metavar' : '<attributes>',
503 'help' : 'Required attributes for module, separated by a ' 300 'help' : 'Required attributes for module, separated by a '
504 'comma'} 301 'comma'}
505 ), 302 ),
506 ('bad-functions', 303 ('bad-functions',
507 {'default' : BAD_FUNCTIONS, 304 {'default' : ('map', 'filter', 'apply', 'input'),
508 'type' :'csv', 'metavar' : '<builtin function names>', 305 'type' :'csv', 'metavar' : '<builtin function names>',
509 'help' : 'List of builtins function names that should not be ' 306 'help' : 'List of builtins function names that should not be '
510 'used, separated by a comma'} 307 'used, separated by a comma'}
511 ), 308 ),
512 ) 309 )
513 reports = (('RP0101', 'Statistics by type', report_by_type_stats),) 310 reports = ( ('RP0101', 'Statistics by type', report_by_type_stats), )
514 311
515 def __init__(self, linter): 312 def __init__(self, linter):
516 _BasicChecker.__init__(self, linter) 313 _BasicChecker.__init__(self, linter)
517 self.stats = None 314 self.stats = None
518 self._tryfinallys = None 315 self._tryfinallys = None
519 316
520 def open(self): 317 def open(self):
521 """initialize visit variables and statistics 318 """initialize visit variables and statistics
522 """ 319 """
523 self._tryfinallys = [] 320 self._tryfinallys = []
524 self.stats = self.linter.add_stats(module=0, function=0, 321 self.stats = self.linter.add_stats(module=0, function=0,
525 method=0, class_=0) 322 method=0, class_=0)
526 @check_messages('missing-module-attribute') 323
527 def visit_module(self, node): 324 def visit_module(self, node):
528 """check module name, docstring and required arguments 325 """check module name, docstring and required arguments
529 """ 326 """
530 self.stats['module'] += 1 327 self.stats['module'] += 1
531 for attr in self.config.required_attributes: 328 for attr in self.config.required_attributes:
532 if attr not in node: 329 if attr not in node:
533 self.add_message('missing-module-attribute', node=node, args=att r) 330 self.add_message('C0121', node=node, args=attr)
534 331
535 def visit_class(self, node): 332 def visit_class(self, node):
536 """check module name, docstring and redefinition 333 """check module name, docstring and redefinition
537 increment branch counter 334 increment branch counter
538 """ 335 """
539 self.stats['class'] += 1 336 self.stats['class'] += 1
540 337
541 @check_messages('pointless-statement', 'pointless-string-statement', 338 @check_messages('W0104', 'W0105')
542 'expression-not-assigned')
543 def visit_discard(self, node): 339 def visit_discard(self, node):
544 """check for various kind of statements without effect""" 340 """check for various kind of statements without effect"""
545 expr = node.value 341 expr = node.value
546 if isinstance(expr, astroid.Const) and isinstance(expr.value, 342 if isinstance(expr, astng.Const) and isinstance(expr.value,
547 basestring): 343 basestring):
548 # treat string statement in a separated message 344 # treat string statement in a separated message
549 # Handle PEP-257 attribute docstrings. 345 self.add_message('W0105', node=node)
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)
562 return 346 return
563 # ignore if this is : 347 # ignore if this is :
564 # * a direct function call 348 # * a direct function call
565 # * the unique child of a try/except body 349 # * the unique child of a try/except body
566 # * a yield (which are wrapped by a discard node in _ast XXX) 350 # * a yield (which are wrapped by a discard node in _ast XXX)
567 # warn W0106 if we have any underlying function call (we can't predict 351 # warn W0106 if we have any underlying function call (we can't predict
568 # side effects), else pointless-statement 352 # side effects), else W0104
569 if (isinstance(expr, (astroid.Yield, astroid.CallFunc)) or 353 if (isinstance(expr, (astng.Yield, astng.CallFunc)) or
570 (isinstance(node.parent, astroid.TryExcept) and 354 (isinstance(node.parent, astng.TryExcept) and
571 node.parent.body == [node])): 355 node.parent.body == [node])):
572 return 356 return
573 if any(expr.nodes_of_class(astroid.CallFunc)): 357 if any(expr.nodes_of_class(astng.CallFunc)):
574 self.add_message('expression-not-assigned', node=node, 358 self.add_message('W0106', node=node, args=expr.as_string())
575 args=expr.as_string())
576 else: 359 else:
577 self.add_message('pointless-statement', node=node) 360 self.add_message('W0104', node=node)
578 361
579 @check_messages('unnecessary-lambda') 362 @check_messages('W0108')
580 def visit_lambda(self, node): 363 def visit_lambda(self, node):
581 """check whether or not the lambda is suspicious 364 """check whether or not the lambda is suspicious
582 """ 365 """
583 # if the body of the lambda is a call expression with the same 366 # if the body of the lambda is a call expression with the same
584 # argument list as the lambda itself, then the lambda is 367 # argument list as the lambda itself, then the lambda is
585 # possibly unnecessary and at least suspicious. 368 # possibly unnecessary and at least suspicious.
586 if node.args.defaults: 369 if node.args.defaults:
587 # If the arguments of the lambda include defaults, then a 370 # If the arguments of the lambda include defaults, then a
588 # judgment cannot be made because there is no way to check 371 # judgment cannot be made because there is no way to check
589 # that the defaults defined by the lambda are the same as 372 # that the defaults defined by the lambda are the same as
590 # the defaults defined by the function called in the body 373 # the defaults defined by the function called in the body
591 # of the lambda. 374 # of the lambda.
592 return 375 return
593 call = node.body 376 call = node.body
594 if not isinstance(call, astroid.CallFunc): 377 if not isinstance(call, astng.CallFunc):
595 # The body of the lambda must be a function call expression 378 # The body of the lambda must be a function call expression
596 # for the lambda to be unnecessary. 379 # for the lambda to be unnecessary.
597 return 380 return
598 # XXX are lambda still different with astroid >= 0.18 ? 381 # XXX are lambda still different with astng >= 0.18 ?
599 # *args and **kwargs need to be treated specially, since they 382 # *args and **kwargs need to be treated specially, since they
600 # are structured differently between the lambda and the function 383 # are structured differently between the lambda and the function
601 # call (in the lambda they appear in the args.args list and are 384 # call (in the lambda they appear in the args.args list and are
602 # indicated as * and ** by two bits in the lambda's flags, but 385 # indicated as * and ** by two bits in the lambda's flags, but
603 # in the function call they are omitted from the args list and 386 # in the function call they are omitted from the args list and
604 # are indicated by separate attributes on the function call node). 387 # are indicated by separate attributes on the function call node).
605 ordinary_args = list(node.args.args) 388 ordinary_args = list(node.args.args)
606 if node.args.kwarg: 389 if node.args.kwarg:
607 if (not call.kwargs 390 if (not call.kwargs
608 or not isinstance(call.kwargs, astroid.Name) 391 or not isinstance(call.kwargs, astng.Name)
609 or node.args.kwarg != call.kwargs.name): 392 or node.args.kwarg != call.kwargs.name):
610 return 393 return
611 elif call.kwargs: 394 elif call.kwargs:
612 return 395 return
613 if node.args.vararg: 396 if node.args.vararg:
614 if (not call.starargs 397 if (not call.starargs
615 or not isinstance(call.starargs, astroid.Name) 398 or not isinstance(call.starargs, astng.Name)
616 or node.args.vararg != call.starargs.name): 399 or node.args.vararg != call.starargs.name):
617 return 400 return
618 elif call.starargs: 401 elif call.starargs:
619 return 402 return
620 # The "ordinary" arguments must be in a correspondence such that: 403 # The "ordinary" arguments must be in a correspondence such that:
621 # ordinary_args[i].name == call.args[i].name. 404 # ordinary_args[i].name == call.args[i].name.
622 if len(ordinary_args) != len(call.args): 405 if len(ordinary_args) != len(call.args):
623 return 406 return
624 for i in xrange(len(ordinary_args)): 407 for i in xrange(len(ordinary_args)):
625 if not isinstance(call.args[i], astroid.Name): 408 if not isinstance(call.args[i], astng.Name):
626 return 409 return
627 if node.args.args[i].name != call.args[i].name: 410 if node.args.args[i].name != call.args[i].name:
628 return 411 return
629 if (isinstance(node.body.func, astroid.Getattr) and 412 self.add_message('W0108', line=node.fromlineno, node=node)
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)
635 413
636 @check_messages('dangerous-default-value')
637 def visit_function(self, node): 414 def visit_function(self, node):
638 """check function name, docstring, arguments, redefinition, 415 """check function name, docstring, arguments, redefinition,
639 variable names, max locals 416 variable names, max locals
640 """ 417 """
641 self.stats[node.is_method() and 'method' or 'function'] += 1 418 self.stats[node.is_method() and 'method' or 'function'] += 1
642 # check for dangerous default values as arguments 419 # check for dangerous default values as arguments
643 for default in node.args.defaults: 420 for default in node.args.defaults:
644 try: 421 try:
645 value = default.infer().next() 422 value = default.infer().next()
646 except astroid.InferenceError: 423 except astng.InferenceError:
647 continue 424 continue
648 builtins = astroid.bases.BUILTINS 425 if isinstance(value, (astng.Dict, astng.List)):
649 if (isinstance(value, astroid.Instance) and
650 value.qname() in ['.'.join([builtins, x]) for x in ('set', ' dict', 'list')]):
651 if value is default: 426 if value is default:
652 msg = default.as_string() 427 msg = default.as_string()
653 elif type(value) is astroid.Instance:
654 msg = '%s (%s)' % (default.as_string(), value.qname())
655 else: 428 else:
656 msg = '%s (%s)' % (default.as_string(), value.as_string()) 429 msg = '%s (%s)' % (default.as_string(), value.as_string())
657 self.add_message('dangerous-default-value', node=node, args=(msg ,)) 430 self.add_message('W0102', node=node, args=(msg,))
658 431
659 @check_messages('unreachable', 'lost-exception') 432 @check_messages('W0101', 'W0150')
660 def visit_return(self, node): 433 def visit_return(self, node):
661 """1 - check is the node has a right sibling (if so, that's some 434 """1 - check is the node has a right sibling (if so, that's some
662 unreachable code) 435 unreachable code)
663 2 - check is the node is inside the finally clause of a try...finally 436 2 - check is the node is inside the finally clause of a try...finally
664 block 437 block
665 """ 438 """
666 self._check_unreachable(node) 439 self._check_unreachable(node)
667 # Is it inside final body of a try...finally bloc ? 440 # Is it inside final body of a try...finally bloc ?
668 self._check_not_in_finally(node, 'return', (astroid.Function,)) 441 self._check_not_in_finally(node, 'return', (astng.Function,))
669 442
670 @check_messages('unreachable') 443 @check_messages('W0101')
671 def visit_continue(self, node): 444 def visit_continue(self, node):
672 """check is the node has a right sibling (if so, that's some unreachable 445 """check is the node has a right sibling (if so, that's some unreachable
673 code) 446 code)
674 """ 447 """
675 self._check_unreachable(node) 448 self._check_unreachable(node)
676 449
677 @check_messages('unreachable', 'lost-exception') 450 @check_messages('W0101', 'W0150')
678 def visit_break(self, node): 451 def visit_break(self, node):
679 """1 - check is the node has a right sibling (if so, that's some 452 """1 - check is the node has a right sibling (if so, that's some
680 unreachable code) 453 unreachable code)
681 2 - check is the node is inside the finally clause of a try...finally 454 2 - check is the node is inside the finally clause of a try...finally
682 block 455 block
683 """ 456 """
684 # 1 - Is it right sibling ? 457 # 1 - Is it right sibling ?
685 self._check_unreachable(node) 458 self._check_unreachable(node)
686 # 2 - Is it inside final body of a try...finally bloc ? 459 # 2 - Is it inside final body of a try...finally bloc ?
687 self._check_not_in_finally(node, 'break', (astroid.For, astroid.While,)) 460 self._check_not_in_finally(node, 'break', (astng.For, astng.While,))
688 461
689 @check_messages('unreachable', 'old-raise-syntax') 462 @check_messages('W0101')
690 def visit_raise(self, node): 463 def visit_raise(self, node):
691 """check if the node has a right sibling (if so, that's some unreachable 464 """check is the node has a right sibling (if so, that's some unreachable
692 code) 465 code)
693 """ 466 """
694 self._check_unreachable(node) 467 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)
699 468
700 @check_messages('exec-used') 469 @check_messages('W0122')
701 def visit_exec(self, node): 470 def visit_exec(self, node):
702 """just print a warning on exec statements""" 471 """just print a warning on exec statements"""
703 self.add_message('exec-used', node=node) 472 self.add_message('W0122', node=node)
704 473
705 @check_messages('bad-builtin', 'star-args', 'eval-used', 474 @check_messages('W0141', 'W0142')
706 'exec-used', 'missing-reversed-argument',
707 'bad-reversed-sequence')
708 def visit_callfunc(self, node): 475 def visit_callfunc(self, node):
709 """visit a CallFunc node -> check if this is not a blacklisted builtin 476 """visit a CallFunc node -> check if this is not a blacklisted builtin
710 call and check for * or ** use 477 call and check for * or ** use
711 """ 478 """
712 if isinstance(node.func, astroid.Name): 479 if isinstance(node.func, astng.Name):
713 name = node.func.name 480 name = node.func.name
714 # ignore the name if it's not a builtin (i.e. not defined in the 481 # ignore the name if it's not a builtin (i.e. not defined in the
715 # locals nor globals scope) 482 # locals nor globals scope)
716 if not (name in node.frame() or 483 if not (name in node.frame() or
717 name in node.root()): 484 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)
724 if name in self.config.bad_functions: 485 if name in self.config.bad_functions:
725 self.add_message('bad-builtin', node=node, args=name) 486 self.add_message('W0141', node=node, args=name)
726 if node.starargs or node.kwargs: 487 if node.starargs or node.kwargs:
727 scope = node.scope() 488 scope = node.scope()
728 if isinstance(scope, astroid.Function): 489 if isinstance(scope, astng.Function):
729 toprocess = [(n, vn) for (n, vn) in ((node.starargs, scope.args. vararg), 490 toprocess = [(n, vn) for (n, vn) in ((node.starargs, scope.args. vararg),
730 (node.kwargs, scope.args.kw arg)) if n] 491 (node.kwargs, scope.args.kw arg)) if n]
731 if toprocess: 492 if toprocess:
732 for cfnode, fargname in toprocess[:]: 493 for cfnode, fargname in toprocess[:]:
733 if getattr(cfnode, 'name', None) == fargname: 494 if getattr(cfnode, 'name', None) == fargname:
734 toprocess.remove((cfnode, fargname)) 495 toprocess.remove((cfnode, fargname))
735 if not toprocess: 496 if not toprocess:
736 return # star-args can be skipped 497 return # W0142 can be skipped
737 self.add_message('star-args', node=node.func) 498 self.add_message('W0142', node=node.func)
738 499
739 @check_messages('assert-on-tuple') 500 @check_messages('W0199')
740 def visit_assert(self, node): 501 def visit_assert(self, node):
741 """check the use of an assert statement on a tuple.""" 502 """check the use of an assert statement on a tuple."""
742 if node.fail is None and isinstance(node.test, astroid.Tuple) and \ 503 if node.fail is None and isinstance(node.test, astng.Tuple) and \
743 len(node.test.elts) == 2: 504 len(node.test.elts) == 2:
744 self.add_message('assert-on-tuple', node=node) 505 self.add_message('W0199', line=node.fromlineno, node=node)
745 506
746 @check_messages('duplicate-key') 507 @check_messages('W0109')
747 def visit_dict(self, node): 508 def visit_dict(self, node):
748 """check duplicate key in dictionary""" 509 """check duplicate key in dictionary"""
749 keys = set() 510 keys = set()
750 for k, _ in node.items: 511 for k, v in node.items:
751 if isinstance(k, astroid.Const): 512 if isinstance(k, astng.Const):
752 key = k.value 513 key = k.value
753 if key in keys: 514 if key in keys:
754 self.add_message('duplicate-key', node=node, args=key) 515 self.add_message('W0109', node=node, args=key)
755 keys.add(key) 516 keys.add(key)
756 517
757 def visit_tryfinally(self, node): 518 def visit_tryfinally(self, node):
758 """update try...finally flag""" 519 """update try...finally flag"""
759 self._tryfinallys.append(node) 520 self._tryfinallys.append(node)
760 521
761 def leave_tryfinally(self, node): 522 def leave_tryfinally(self, node):
762 """update try...finally flag""" 523 """update try...finally flag"""
763 self._tryfinallys.pop() 524 self._tryfinallys.pop()
764 525
765 def _check_unreachable(self, node): 526 def _check_unreachable(self, node):
766 """check unreachable code""" 527 """check unreachable code"""
767 unreach_stmt = node.next_sibling() 528 unreach_stmt = node.next_sibling()
768 if unreach_stmt is not None: 529 if unreach_stmt is not None:
769 self.add_message('unreachable', node=unreach_stmt) 530 self.add_message('W0101', node=unreach_stmt)
770 531
771 def _check_not_in_finally(self, node, node_name, breaker_classes=()): 532 def _check_not_in_finally(self, node, node_name, breaker_classes=()):
772 """check that a node is not inside a finally clause of a 533 """check that a node is not inside a finally clause of a
773 try...finally statement. 534 try...finally statement.
774 If we found before a try...finally bloc a parent which its type is 535 If we found before a try...finally bloc a parent which its type is
775 in breaker_classes, we skip the whole check.""" 536 in breaker_classes, we skip the whole check."""
776 # if self._tryfinallys is empty, we're not a in try...finally bloc 537 # if self._tryfinallys is empty, we're not a in try...finally bloc
777 if not self._tryfinallys: 538 if not self._tryfinallys:
778 return 539 return
779 # the node could be a grand-grand...-children of the try...finally 540 # the node could be a grand-grand...-children of the try...finally
780 _parent = node.parent 541 _parent = node.parent
781 _node = node 542 _node = node
782 while _parent and not isinstance(_parent, breaker_classes): 543 while _parent and not isinstance(_parent, breaker_classes):
783 if hasattr(_parent, 'finalbody') and _node in _parent.finalbody: 544 if hasattr(_parent, 'finalbody') and _node in _parent.finalbody:
784 self.add_message('lost-exception', node=node, args=node_name) 545 self.add_message('W0150', node=node, args=node_name)
785 return 546 return
786 _node = _parent 547 _node = _parent
787 _parent = _node.parent 548 _parent = _node.parent
788 549
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
810 550
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)
867 551
868 class NameChecker(_BasicChecker): 552 class NameChecker(_BasicChecker):
869 msgs = { 553 msgs = {
870 'C0102': ('Black listed name "%s"', 554 'C0102': ('Black listed name "%s"',
871 'blacklisted-name', 555 'Used when the name is listed in the black list (unauthorized \
872 'Used when the name is listed in the black list (unauthorized ' 556 names).'),
873 'names).'), 557 'C0103': ('Invalid name "%s" (should match %s)',
874 'C0103': ('Invalid %s name "%s"%s', 558 'Used when the name doesn\'t match the regular expression \
875 'invalid-name', 559 associated to its type (constant, variable, class...).'),
876 'Used when the name doesn\'t match the regular expression ' 560
877 'associated to its type (constant, variable, class...).'),
878 } 561 }
879 562 options = (('module-rgx',
880 options = (('good-names', 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',
881 {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'), 618 {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'),
882 'type' :'csv', 'metavar' : '<names>', 619 'type' :'csv', 'metavar' : '<names>',
883 'help' : 'Good variable names which should always be accepted,' 620 'help' : 'Good variable names which should always be accepted,'
884 ' separated by a comma'} 621 ' separated by a comma'}
885 ), 622 ),
886 ('bad-names', 623 ('bad-names',
887 {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'), 624 {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'),
888 'type' :'csv', 'metavar' : '<names>', 625 'type' :'csv', 'metavar' : '<names>',
889 'help' : 'Bad variable names which should always be refused, ' 626 'help' : 'Bad variable names which should always be refused, '
890 'separated by a comma'} 627 'separated by a comma'}
891 ), 628 ),
892 ('name-group', 629 )
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 = {}
910 630
911 def open(self): 631 def open(self):
912 self.stats = self.linter.add_stats(badname_module=0, 632 self.stats = self.linter.add_stats(badname_module=0,
913 badname_class=0, badname_function=0, 633 badname_class=0, badname_function=0,
914 badname_method=0, badname_attr=0, 634 badname_method=0, badname_attr=0,
915 badname_const=0, 635 badname_const=0,
916 badname_variable=0, 636 badname_variable=0,
917 badname_inlinevar=0, 637 badname_inlinevar=0,
918 badname_argument=0, 638 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,)
923 639
924 @check_messages('blacklisted-name', 'invalid-name') 640 @check_messages('C0102', 'C0103')
925 def visit_module(self, node): 641 def visit_module(self, node):
926 self._check_name('module', node.name.split('.')[-1], node) 642 self._check_name('module', node.name.split('.')[-1], node)
927 643
928 @check_messages('blacklisted-name', 'invalid-name') 644 @check_messages('C0102', 'C0103')
929 def visit_class(self, node): 645 def visit_class(self, node):
930 self._check_name('class', node.name, node) 646 self._check_name('class', node.name, node)
931 for attr, anodes in node.instance_attrs.iteritems(): 647 for attr, anodes in node.instance_attrs.items():
932 if not list(node.instance_attr_ancestors(attr)): 648 self._check_name('attr', attr, anodes[0])
933 self._check_name('attr', attr, anodes[0])
934 649
935 @check_messages('blacklisted-name', 'invalid-name') 650 @check_messages('C0102', 'C0103')
936 def visit_function(self, node): 651 def visit_function(self, node):
937 # Do not emit any warnings if the method is just an implementation 652 self._check_name(node.is_method() and 'method' or 'function',
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),
942 node.name, node) 653 node.name, node)
943 # Check argument names 654 # check arguments name
944 args = node.args.args 655 args = node.args.args
945 if args is not None: 656 if args is not None:
946 self._recursive_check_names(args, node) 657 self._recursive_check_names(args, node)
947 658
948 @check_messages('blacklisted-name', 'invalid-name') 659 @check_messages('C0102', 'C0103')
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')
954 def visit_assname(self, node): 660 def visit_assname(self, node):
955 """check module level assigned names""" 661 """check module level assigned names"""
956 frame = node.frame() 662 frame = node.frame()
957 ass_type = node.ass_type() 663 ass_type = node.ass_type()
958 if isinstance(ass_type, astroid.Comprehension): 664 if isinstance(ass_type, (astng.Comprehension, astng.Comprehension)):
959 self._check_name('inlinevar', node.name, node) 665 self._check_name('inlinevar', node.name, node)
960 elif isinstance(frame, astroid.Module): 666 elif isinstance(frame, astng.Module):
961 if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type): 667 if isinstance(ass_type, astng.Assign) and not in_loop(ass_type):
962 if isinstance(safe_infer(ass_type.value), astroid.Class): 668 self._check_name('const', node.name, node)
963 self._check_name('class', node.name, node) 669 elif isinstance(ass_type, astng.ExceptHandler):
964 else:
965 self._check_name('const', node.name, node)
966 elif isinstance(ass_type, astroid.ExceptHandler):
967 self._check_name('variable', node.name, node) 670 self._check_name('variable', node.name, node)
968 elif isinstance(frame, astroid.Function): 671 elif isinstance(frame, astng.Function):
969 # global introduced variable aren't in the function locals 672 # global introduced variable aren't in the function locals
970 if node.name in frame and node.name not in frame.argnames(): 673 if node.name in frame:
971 self._check_name('variable', node.name, node) 674 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)
975 675
976 def _recursive_check_names(self, args, node): 676 def _recursive_check_names(self, args, node):
977 """check names in a possibly recursive list <arg>""" 677 """check names in a possibly recursive list <arg>"""
978 for arg in args: 678 for arg in args:
979 if isinstance(arg, astroid.AssName): 679 if isinstance(arg, astng.AssName):
980 self._check_name('argument', arg.name, node) 680 self._check_name('argument', arg.name, node)
981 else: 681 else:
982 self._recursive_check_names(arg.elts, node) 682 self._recursive_check_names(arg.elts, node)
983 683
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
992 def _check_name(self, node_type, name, node): 684 def _check_name(self, node_type, name, node):
993 """check for a name using the type's regexp""" 685 """check for a name using the type's regexp"""
994 if is_inside_except(node): 686 if is_inside_except(node):
995 clobbering, _ = clobber_in_except(node) 687 clobbering, _ = clobber_in_except(node)
996 if clobbering: 688 if clobbering:
997 return 689 return
690
998 if name in self.config.good_names: 691 if name in self.config.good_names:
999 return 692 return
1000 if name in self.config.bad_names: 693 if name in self.config.bad_names:
1001 self.stats['badname_' + node_type] += 1 694 self.stats['badname_' + node_type] += 1
1002 self.add_message('blacklisted-name', node=node, args=name) 695 self.add_message('C0102', node=node, args=name)
1003 return 696 return
1004 regexp = getattr(self.config, node_type + '_rgx') 697 regexp = getattr(self.config, node_type + '_rgx')
1005 match = regexp.match(name) 698 if regexp.match(name) is None:
1006 699 self.add_message('C0103', node=node, args=(name, regexp.pattern))
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))
1020 self.stats['badname_' + node_type] += 1 700 self.stats['badname_' + node_type] += 1
1021 701
1022 702
1023 class DocStringChecker(_BasicChecker): 703 class DocStringChecker(_BasicChecker):
1024 msgs = { 704 msgs = {
1025 'C0111': ('Missing %s docstring', # W0131 705 'C0111': ('Missing docstring', # W0131
1026 'missing-docstring', 706 'Used when a module, function, class or method has no docstring.\
1027 'Used when a module, function, class or method has no docstrin g.' 707 Some special methods like __init__ doesn\'t necessary require a \
1028 'Some special methods like __init__ doesn\'t necessary require a ' 708 docstring.'),
1029 'docstring.'), 709 'C0112': ('Empty docstring', # W0132
1030 'C0112': ('Empty %s docstring', # W0132 710 'Used when a module, function, class or method has an empty \
1031 'empty-docstring', 711 docstring (it would be too easy ;).'),
1032 'Used when a module, function, class or method has an empty ' 712 }
1033 'docstring (it would be too easy ;).'),
1034 }
1035 options = (('no-docstring-rgx', 713 options = (('no-docstring-rgx',
1036 {'default' : NO_REQUIRED_DOC_RGX, 714 {'default' : NO_REQUIRED_DOC_RGX,
1037 'type' : 'regexp', 'metavar' : '<regexp>', 715 'type' : 'regexp', 'metavar' : '<regexp>',
1038 'help' : 'Regular expression which should only match ' 716 'help' : 'Regular expression which should only match '
1039 'function or class names that do not require a ' 717 'functions or classes name which do not require a '
1040 'docstring.'} 718 'docstring'}
1041 ), 719 ),
1042 ('docstring-min-length', 720 )
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
1050 721
1051 def open(self): 722 def open(self):
1052 self.stats = self.linter.add_stats(undocumented_module=0, 723 self.stats = self.linter.add_stats(undocumented_module=0,
1053 undocumented_function=0, 724 undocumented_function=0,
1054 undocumented_method=0, 725 undocumented_method=0,
1055 undocumented_class=0) 726 undocumented_class=0)
1056 @check_messages('missing-docstring', 'empty-docstring') 727
1057 def visit_module(self, node): 728 def visit_module(self, node):
1058 self._check_docstring('module', node) 729 self._check_docstring('module', node)
1059 730
1060 @check_messages('missing-docstring', 'empty-docstring')
1061 def visit_class(self, node): 731 def visit_class(self, node):
1062 if self.config.no_docstring_rgx.match(node.name) is None: 732 if self.config.no_docstring_rgx.match(node.name) is None:
1063 self._check_docstring('class', node) 733 self._check_docstring('class', node)
1064 @check_messages('missing-docstring', 'empty-docstring') 734
1065 def visit_function(self, node): 735 def visit_function(self, node):
1066 if self.config.no_docstring_rgx.match(node.name) is None: 736 if self.config.no_docstring_rgx.match(node.name) is None:
1067 ftype = node.is_method() and 'method' or 'function' 737 ftype = node.is_method() and 'method' or 'function'
1068 if isinstance(node.parent.frame(), astroid.Class): 738 if isinstance(node.parent.frame(), astng.Class):
1069 overridden = False 739 overridden = False
1070 # check if node is from a method overridden by its ancestor 740 # check if node is from a method overridden by its ancestor
1071 for ancestor in node.parent.frame().ancestors(): 741 for ancestor in node.parent.frame().ancestors():
1072 if node.name in ancestor and \ 742 if node.name in ancestor and \
1073 isinstance(ancestor[node.name], astroid.Function): 743 isinstance(ancestor[node.name], astng.Function):
1074 overridden = True 744 overridden = True
1075 break 745 break
1076 self._check_docstring(ftype, node, 746 if not overridden:
1077 report_missing=not overridden) 747 self._check_docstring(ftype, node)
1078 else: 748 else:
1079 self._check_docstring(ftype, node) 749 self._check_docstring(ftype, node)
1080 750
1081 def _check_docstring(self, node_type, node, report_missing=True): 751 def _check_docstring(self, node_type, node):
1082 """check the node has a non empty docstring""" 752 """check the node has a non empty docstring"""
1083 docstring = node.doc 753 docstring = node.doc
1084 if docstring is None: 754 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
1095 self.stats['undocumented_'+node_type] += 1 755 self.stats['undocumented_'+node_type] += 1
1096 if (node.body and isinstance(node.body[0], astroid.Discard) and 756 self.add_message('C0111', node=node)
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,))
1108 elif not docstring.strip(): 757 elif not docstring.strip():
1109 self.stats['undocumented_'+node_type] += 1 758 self.stats['undocumented_'+node_type] += 1
1110 self.add_message('empty-docstring', node=node, args=(node_type,)) 759 self.add_message('C0112', node=node)
1111 760
1112 761
1113 class PassChecker(_BasicChecker): 762 class PassChecker(_BasicChecker):
1114 """check if the pass statement is really necessary""" 763 """check is the pass statement is really necessary"""
1115 msgs = {'W0107': ('Unnecessary pass statement', 764 msgs = {'W0107': ('Unnecessary pass statement',
1116 'unnecessary-pass',
1117 'Used when a "pass" statement that can be avoided is ' 765 'Used when a "pass" statement that can be avoided is '
1118 'encountered.'), 766 'encountered.)'),
1119 } 767 }
1120 @check_messages('unnecessary-pass') 768
1121 def visit_pass(self, node): 769 def visit_pass(self, node):
1122 if len(node.parent.child_sequence(node)) > 1: 770 if len(node.parent.child_sequence(node)) > 1:
1123 self.add_message('unnecessary-pass', node=node) 771 self.add_message('W0107', 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)
1154 772
1155 773
1156 def register(linter): 774 def register(linter):
1157 """required method to auto register this checker""" 775 """required method to auto register this checker"""
1158 linter.register_checker(BasicErrorChecker(linter)) 776 linter.register_checker(BasicErrorChecker(linter))
1159 linter.register_checker(BasicChecker(linter)) 777 linter.register_checker(BasicChecker(linter))
1160 linter.register_checker(NameChecker(linter)) 778 linter.register_checker(NameChecker(linter))
1161 linter.register_checker(DocStringChecker(linter)) 779 linter.register_checker(DocStringChecker(linter))
1162 linter.register_checker(PassChecker(linter)) 780 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