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

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

Issue 753543006: pylint: upgrade to 1.4.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View 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-2013 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # Copyright (c) 2009-2010 Arista Networks, Inc. 3 # Copyright (c) 2009-2010 Arista Networks, Inc.
4 # 4 #
5 # 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
6 # 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
7 # 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
8 # version. 8 # version.
9 # 9 #
10 # 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
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 # 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. 12 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 # 13 #
14 # 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
15 # this program; if not, write to the Free Software Foundation, Inc., 15 # this program; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 """basic checker for Python code""" 17 """basic checker for Python code"""
18 18
19 import collections
20 import itertools
19 import sys 21 import sys
22 import re
23
24 import six
25 from six.moves import zip # pylint: disable=redefined-builtin
26
27 from logilab.common.ureports import Table
28
20 import astroid 29 import astroid
21 from logilab.common.ureports import Table 30 import astroid.bases
22 from astroid import are_exclusive, InferenceError 31 from astroid import are_exclusive, InferenceError
23 import astroid.bases
24 32
25 from pylint.interfaces import IAstroidChecker 33 from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE, HIG H
26 from pylint.utils import EmptyReport 34 from pylint.utils import EmptyReport
27 from pylint.reporters import diff_string 35 from pylint.reporters import diff_string
28 from pylint.checkers import BaseChecker 36 from pylint.checkers import BaseChecker
29 from pylint.checkers.utils import ( 37 from pylint.checkers.utils import (
30 check_messages, 38 check_messages,
31 clobber_in_except, 39 clobber_in_except,
32 is_builtin_object, 40 is_builtin_object,
33 is_inside_except, 41 is_inside_except,
34 overrides_a_method, 42 overrides_a_method,
35 safe_infer, 43 safe_infer,
36 get_argument_from_call, 44 get_argument_from_call,
45 has_known_bases,
37 NoSuchArgumentError, 46 NoSuchArgumentError,
47 is_import_error,
38 ) 48 )
39 49
40 50
41 import re
42
43 # regex for class/function/variable/constant name 51 # regex for class/function/variable/constant name
44 CLASS_NAME_RGX = re.compile('[A-Z_][a-zA-Z0-9]+$') 52 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]+))$') 53 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_]*)|(__.*__))$') 54 CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$')
47 COMP_VAR_RGX = re.compile('[A-Za-z_][A-Za-z0-9_]*$') 55 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}$') 56 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}|(__.*__))$') 57 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 58 # do not require a doc string on system methods
51 NO_REQUIRED_DOC_RGX = re.compile('__.*__') 59 NO_REQUIRED_DOC_RGX = re.compile('__.*__')
52 REVERSED_METHODS = (('__getitem__', '__len__'), 60 REVERSED_METHODS = (('__getitem__', '__len__'),
53 ('__reversed__', )) 61 ('__reversed__', ))
54 62
55 PY33 = sys.version_info >= (3, 3) 63 PY33 = sys.version_info >= (3, 3)
56 PY3K = sys.version_info >= (3, 0) 64 PY3K = sys.version_info >= (3, 0)
57 BAD_FUNCTIONS = ['map', 'filter', 'apply'] 65 BAD_FUNCTIONS = ['map', 'filter']
58 if sys.version_info < (3, 0): 66 if sys.version_info < (3, 0):
59 BAD_FUNCTIONS.append('input') 67 BAD_FUNCTIONS.append('input')
60 BAD_FUNCTIONS.append('file')
61 68
62 # Name categories that are always consistent with all naming conventions. 69 # Name categories that are always consistent with all naming conventions.
63 EXEMPT_NAME_CATEGORIES = set(('exempt', 'ignore')) 70 EXEMPT_NAME_CATEGORIES = set(('exempt', 'ignore'))
64 71
72 # A mapping from builtin-qname -> symbol, to be used when generating messages
73 # about dangerous default values as arguments
74 DEFAULT_ARGUMENT_SYMBOLS = dict(
75 zip(['.'.join([astroid.bases.BUILTINS, x]) for x in ('set', 'dict', 'list')] ,
76 ['set()', '{}', '[]'])
77 )
78
65 del re 79 del re
66 80
81 def _redefines_import(node):
82 """ Detect that the given node (AssName) is inside an
83 exception handler and redefines an import from the tryexcept body.
84 Returns True if the node redefines an import, False otherwise.
85 """
86 current = node
87 while current and not isinstance(current.parent, astroid.ExceptHandler):
88 current = current.parent
89 if not current or not is_import_error(current.parent):
90 return False
91 try_block = current.parent.parent
92 for import_node in try_block.nodes_of_class((astroid.From, astroid.Import)):
93 for name, alias in import_node.names:
94 if alias:
95 if alias == node.name:
96 return True
97 elif name == node.name:
98 return True
99 return False
100
67 def in_loop(node): 101 def in_loop(node):
68 """return True if the node is inside a kind of for loop""" 102 """return True if the node is inside a kind of for loop"""
69 parent = node.parent 103 parent = node.parent
70 while parent is not None: 104 while parent is not None:
71 if isinstance(parent, (astroid.For, astroid.ListComp, astroid.SetComp, 105 if isinstance(parent, (astroid.For, astroid.ListComp, astroid.SetComp,
72 astroid.DictComp, astroid.GenExpr)): 106 astroid.DictComp, astroid.GenExpr)):
73 return True 107 return True
74 parent = parent.parent 108 parent = parent.parent
75 return False 109 return False
76 110
(...skipping 10 matching lines...) Expand all
87 return False 121 return False
88 122
89 def _loop_exits_early(loop): 123 def _loop_exits_early(loop):
90 """Returns true if a loop has a break statement in its body.""" 124 """Returns true if a loop has a break statement in its body."""
91 loop_nodes = (astroid.For, astroid.While) 125 loop_nodes = (astroid.For, astroid.While)
92 # Loop over body explicitly to avoid matching break statements 126 # Loop over body explicitly to avoid matching break statements
93 # in orelse. 127 # in orelse.
94 for child in loop.body: 128 for child in loop.body:
95 if isinstance(child, loop_nodes): 129 if isinstance(child, loop_nodes):
96 # break statement may be in orelse of child loop. 130 # break statement may be in orelse of child loop.
131 # pylint: disable=superfluous-parens
97 for orelse in (child.orelse or ()): 132 for orelse in (child.orelse or ()):
98 for _ in orelse.nodes_of_class(astroid.Break, skip_klass=loop_no des): 133 for _ in orelse.nodes_of_class(astroid.Break, skip_klass=loop_no des):
99 return True 134 return True
100 continue 135 continue
101 for _ in child.nodes_of_class(astroid.Break, skip_klass=loop_nodes): 136 for _ in child.nodes_of_class(astroid.Break, skip_klass=loop_nodes):
102 return True 137 return True
103 return False 138 return False
104 139
140 def _is_multi_naming_match(match, node_type, confidence):
141 return (match is not None and
142 match.lastgroup is not None and
143 match.lastgroup not in EXEMPT_NAME_CATEGORIES
144 and (node_type != 'method' or confidence != INFERENCE_FAILURE))
145
146
105 if sys.version_info < (3, 0): 147 if sys.version_info < (3, 0):
106 PROPERTY_CLASSES = set(('__builtin__.property', 'abc.abstractproperty')) 148 PROPERTY_CLASSES = set(('__builtin__.property', 'abc.abstractproperty'))
107 else: 149 else:
108 PROPERTY_CLASSES = set(('builtins.property', 'abc.abstractproperty')) 150 PROPERTY_CLASSES = set(('builtins.property', 'abc.abstractproperty'))
109 ABC_METHODS = set(('abc.abstractproperty', 'abc.abstractmethod', 151 ABC_METHODS = set(('abc.abstractproperty', 'abc.abstractmethod',
110 'abc.abstractclassmethod', 'abc.abstractstaticmethod')) 152 'abc.abstractclassmethod', 'abc.abstractstaticmethod'))
111 153
112 def _determine_function_name_type(node): 154 def _determine_function_name_type(node):
113 """Determine the name type whose regex the a function's name should match. 155 """Determine the name type whose regex the a function's name should match.
114 156
(...skipping 22 matching lines...) Expand all
137 return 'attr' 179 return 'attr'
138 return 'method' 180 return 'method'
139 181
140 def decorated_with_abc(func): 182 def decorated_with_abc(func):
141 """ Determine if the `func` node is decorated 183 """ Determine if the `func` node is decorated
142 with `abc` decorators (abstractmethod et co.) 184 with `abc` decorators (abstractmethod et co.)
143 """ 185 """
144 if func.decorators: 186 if func.decorators:
145 for node in func.decorators.nodes: 187 for node in func.decorators.nodes:
146 try: 188 try:
147 infered = node.infer().next() 189 infered = next(node.infer())
148 except InferenceError: 190 except InferenceError:
149 continue 191 continue
150 if infered and infered.qname() in ABC_METHODS: 192 if infered and infered.qname() in ABC_METHODS:
151 return True 193 return True
152 194
153 def has_abstract_methods(node): 195 def has_abstract_methods(node):
154 """ Determine if the given `node` has 196 """
197 Determine if the given `node` has
155 abstract methods, defined with `abc` module. 198 abstract methods, defined with `abc` module.
156 """ 199 """
157 return any(decorated_with_abc(meth) 200 return any(decorated_with_abc(meth)
158 for meth in node.mymethods()) 201 for meth in node.methods())
159 202
160 def report_by_type_stats(sect, stats, old_stats): 203 def report_by_type_stats(sect, stats, old_stats):
161 """make a report of 204 """make a report of
162 205
163 * percentage of different types documented 206 * percentage of different types documented
164 * percentage of different types with a bad name 207 * percentage of different types with a bad name
165 """ 208 """
166 # percentage of different types documented and/or with a bad name 209 # percentage of different types documented and/or with a bad name
167 nice_stats = {} 210 nice_stats = {}
168 for node_type in ('module', 'class', 'method', 'function'): 211 for node_type in ('module', 'class', 'method', 'function'):
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 'nonexistent-operator', 294 'nonexistent-operator',
252 "Used when you attempt to use the C-style pre-increment or" 295 "Used when you attempt to use the C-style pre-increment or"
253 "pre-decrement operator -- and ++, which doesn't exist in Pyth on."), 296 "pre-decrement operator -- and ++, which doesn't exist in Pyth on."),
254 'E0108': ('Duplicate argument name %s in function definition', 297 'E0108': ('Duplicate argument name %s in function definition',
255 'duplicate-argument-name', 298 'duplicate-argument-name',
256 'Duplicate argument names in function definitions are syntax' 299 'Duplicate argument names in function definitions are syntax'
257 ' errors.'), 300 ' errors.'),
258 'E0110': ('Abstract class with abstract methods instantiated', 301 'E0110': ('Abstract class with abstract methods instantiated',
259 'abstract-class-instantiated', 302 'abstract-class-instantiated',
260 'Used when an abstract class with `abc.ABCMeta` as metaclass ' 303 'Used when an abstract class with `abc.ABCMeta` as metaclass '
261 'has abstract methods and is instantiated.', 304 'has abstract methods and is instantiated.'),
262 {'minversion': (3, 0)}),
263 'W0120': ('Else clause on loop without a break statement', 305 'W0120': ('Else clause on loop without a break statement',
264 'useless-else-on-loop', 306 'useless-else-on-loop',
265 'Loops should only have an else clause if they can exit early ' 307 'Loops should only have an else clause if they can exit early '
266 'with a break statement, otherwise the statements under else ' 308 'with a break statement, otherwise the statements under else '
267 'should be on the same scope as the loop itself.'), 309 'should be on the same scope as the loop itself.'),
268 } 310 }
269 311
270 @check_messages('function-redefined') 312 @check_messages('function-redefined')
271 def visit_class(self, node): 313 def visit_class(self, node):
272 self._check_redefinition('class', node) 314 self._check_redefinition('class', node)
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 isinstance(node.operand, astroid.UnaryOp) and 384 isinstance(node.operand, astroid.UnaryOp) and
343 (node.operand.op == node.op)): 385 (node.operand.op == node.op)):
344 self.add_message('nonexistent-operator', node=node, args=node.op*2) 386 self.add_message('nonexistent-operator', node=node, args=node.op*2)
345 387
346 @check_messages('abstract-class-instantiated') 388 @check_messages('abstract-class-instantiated')
347 def visit_callfunc(self, node): 389 def visit_callfunc(self, node):
348 """ Check instantiating abstract class with 390 """ Check instantiating abstract class with
349 abc.ABCMeta as metaclass. 391 abc.ABCMeta as metaclass.
350 """ 392 """
351 try: 393 try:
352 infered = node.func.infer().next() 394 infered = next(node.func.infer())
353 except astroid.InferenceError: 395 except astroid.InferenceError:
354 return 396 return
355 if not isinstance(infered, astroid.Class): 397 if not isinstance(infered, astroid.Class):
356 return 398 return
357 # __init__ was called 399 # __init__ was called
358 metaclass = infered.metaclass() 400 metaclass = infered.metaclass()
401 abstract_methods = has_abstract_methods(infered)
359 if metaclass is None: 402 if metaclass is None:
360 # Python 3.4 has `abc.ABC`, which won't be detected 403 # Python 3.4 has `abc.ABC`, which won't be detected
361 # by ClassNode.metaclass() 404 # by ClassNode.metaclass()
362 for ancestor in infered.ancestors(): 405 for ancestor in infered.ancestors():
363 if (ancestor.qname() == 'abc.ABC' and 406 if ancestor.qname() == 'abc.ABC' and abstract_methods:
364 has_abstract_methods(infered)):
365 self.add_message('abstract-class-instantiated', node=node) 407 self.add_message('abstract-class-instantiated', node=node)
366 break 408 break
367 return 409 return
368 if (metaclass.qname() == 'abc.ABCMeta' and 410 if metaclass.qname() == 'abc.ABCMeta' and abstract_methods:
369 has_abstract_methods(infered)):
370 self.add_message('abstract-class-instantiated', node=node) 411 self.add_message('abstract-class-instantiated', node=node)
371 412
372 def _check_else_on_loop(self, node): 413 def _check_else_on_loop(self, node):
373 """Check that any loop with an else clause has a break statement.""" 414 """Check that any loop with an else clause has a break statement."""
374 if node.orelse and not _loop_exits_early(node): 415 if node.orelse and not _loop_exits_early(node):
375 self.add_message('useless-else-on-loop', node=node, 416 self.add_message('useless-else-on-loop', node=node,
376 # This is not optimal, but the line previous 417 # This is not optimal, but the line previous
377 # to the first statement in the else clause 418 # to the first statement in the else clause
378 # will usually be the one that contains the else:. 419 # will usually be the one that contains the else:.
379 line=node.orelse[0].lineno - 1) 420 line=node.orelse[0].lineno - 1)
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 'Used when the body of a lambda expression is a function call ' 480 'Used when the body of a lambda expression is a function call '
440 'on the same argument list as the lambda itself; such lambda ' 481 'on the same argument list as the lambda itself; such lambda '
441 'expressions are in all but a few cases replaceable with the ' 482 'expressions are in all but a few cases replaceable with the '
442 'function being called in the body of the lambda.'), 483 'function being called in the body of the lambda.'),
443 'W0109': ("Duplicate key %r in dictionary", 484 'W0109': ("Duplicate key %r in dictionary",
444 'duplicate-key', 485 'duplicate-key',
445 'Used when a dictionary expression binds the same key multiple ' 486 'Used when a dictionary expression binds the same key multiple '
446 'times.'), 487 'times.'),
447 'W0122': ('Use of exec', 488 'W0122': ('Use of exec',
448 'exec-used', 489 'exec-used',
449 'Used when you use the "exec" statement (function for Python 3 ), to discourage its ' 490 'Used when you use the "exec" statement (function for Python '
450 'usage. That doesn\'t mean you can not use it !'), 491 '3), to discourage its usage. That doesn\'t '
492 'mean you can not use it !'),
451 'W0123': ('Use of eval', 493 'W0123': ('Use of eval',
452 'eval-used', 494 'eval-used',
453 'Used when you use the "eval" function, to discourage its ' 495 'Used when you use the "eval" function, to discourage its '
454 'usage. Consider using `ast.literal_eval` for safely evaluatin g ' 496 'usage. Consider using `ast.literal_eval` for safely evaluatin g '
455 'strings containing Python expressions ' 497 'strings containing Python expressions '
456 'from untrusted sources. '), 498 'from untrusted sources. '),
457 'W0141': ('Used builtin function %r', 499 'W0141': ('Used builtin function %r',
458 'bad-builtin', 500 'bad-builtin',
459 'Used when a black listed builtin function is used (see the ' 501 'Used when a black listed builtin function is used (see the '
460 'bad-function option). Usual black listed functions are the on es ' 502 'bad-function option). Usual black listed functions are the on es '
461 'like map, or filter , where Python offers now some cleaner ' 503 'like map, or filter , where Python offers now some cleaner '
462 'alternative like list comprehension.'), 504 'alternative like list comprehension.'),
463 'W0142': ('Used * or ** magic', 505 'W0142': ('Used * or ** magic',
464 'star-args', 506 'star-args',
465 'Used when a function or method is called using `*args` or ' 507 'Used when a function or method is called using `*args` or '
466 '`**kwargs` to dispatch arguments. This doesn\'t improve ' 508 '`**kwargs` to dispatch arguments. This doesn\'t improve '
467 'readability and should be used with care.'), 509 'readability and should be used with care.'),
468 'W0150': ("%s statement in finally block may swallow exception", 510 'W0150': ("%s statement in finally block may swallow exception",
469 'lost-exception', 511 'lost-exception',
470 'Used when a break or a return statement is found inside the ' 512 'Used when a break or a return statement is found inside the '
471 'finally clause of a try...finally block: the exceptions raise d ' 513 'finally clause of a try...finally block: the exceptions raise d '
472 'in the try clause will be silently swallowed instead of being ' 514 'in the try clause will be silently swallowed instead of being '
473 're-raised.'), 515 're-raised.'),
474 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?', 516 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?',
475 'assert-on-tuple', 517 'assert-on-tuple',
476 'A call of assert on a tuple will always evaluate to true if ' 518 '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 ' 519 'the tuple is not empty, and will always evaluate to false if '
478 'it is.'), 520 '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
485 'C0121': ('Missing required attribute "%s"', # W0103 521 'C0121': ('Missing required attribute "%s"', # W0103
486 'missing-module-attribute', 522 'missing-module-attribute',
487 'Used when an attribute required for modules is missing.'), 523 'Used when an attribute required for modules is missing.'),
488 524
489 'E0109': ('Missing argument to reversed()', 525 'E0109': ('Missing argument to reversed()',
490 'missing-reversed-argument', 526 'missing-reversed-argument',
491 'Used when reversed() builtin didn\'t receive an argument.'), 527 'Used when reversed() builtin didn\'t receive an argument.'),
492 'E0111': ('The first reversed() argument is not a sequence', 528 'E0111': ('The first reversed() argument is not a sequence',
493 'bad-reversed-sequence', 529 'bad-reversed-sequence',
494 'Used when the first argument to reversed() builtin ' 530 'Used when the first argument to reversed() builtin '
(...skipping 21 matching lines...) Expand all
516 _BasicChecker.__init__(self, linter) 552 _BasicChecker.__init__(self, linter)
517 self.stats = None 553 self.stats = None
518 self._tryfinallys = None 554 self._tryfinallys = None
519 555
520 def open(self): 556 def open(self):
521 """initialize visit variables and statistics 557 """initialize visit variables and statistics
522 """ 558 """
523 self._tryfinallys = [] 559 self._tryfinallys = []
524 self.stats = self.linter.add_stats(module=0, function=0, 560 self.stats = self.linter.add_stats(module=0, function=0,
525 method=0, class_=0) 561 method=0, class_=0)
562
526 @check_messages('missing-module-attribute') 563 @check_messages('missing-module-attribute')
527 def visit_module(self, node): 564 def visit_module(self, node):
528 """check module name, docstring and required arguments 565 """check module name, docstring and required arguments
529 """ 566 """
530 self.stats['module'] += 1 567 self.stats['module'] += 1
531 for attr in self.config.required_attributes: 568 for attr in self.config.required_attributes:
532 if attr not in node: 569 if attr not in node:
533 self.add_message('missing-module-attribute', node=node, args=att r) 570 self.add_message('missing-module-attribute', node=node, args=att r)
534 571
535 def visit_class(self, node): 572 def visit_class(self, node): # pylint: disable=unused-argument
536 """check module name, docstring and redefinition 573 """check module name, docstring and redefinition
537 increment branch counter 574 increment branch counter
538 """ 575 """
539 self.stats['class'] += 1 576 self.stats['class'] += 1
540 577
541 @check_messages('pointless-statement', 'pointless-string-statement', 578 @check_messages('pointless-statement', 'pointless-string-statement',
542 'expression-not-assigned') 579 'expression-not-assigned')
543 def visit_discard(self, node): 580 def visit_discard(self, node):
544 """check for various kind of statements without effect""" 581 """check for various kind of statements without effect"""
545 expr = node.value 582 expr = node.value
546 if isinstance(expr, astroid.Const) and isinstance(expr.value, 583 if isinstance(expr, astroid.Const) and isinstance(expr.value,
547 basestring): 584 six.string_types):
548 # treat string statement in a separated message 585 # treat string statement in a separated message
549 # Handle PEP-257 attribute docstrings. 586 # Handle PEP-257 attribute docstrings.
550 # An attribute docstring is defined as being a string right after 587 # An attribute docstring is defined as being a string right after
551 # an assignment at the module level, class level or __init__ level. 588 # an assignment at the module level, class level or __init__ level.
552 scope = expr.scope() 589 scope = expr.scope()
553 if isinstance(scope, (astroid.Class, astroid.Module, astroid.Functio n)): 590 if isinstance(scope, (astroid.Class, astroid.Module, astroid.Functio n)):
554 if isinstance(scope, astroid.Function) and scope.name != '__init __': 591 if isinstance(scope, astroid.Function) and scope.name != '__init __':
555 pass 592 pass
556 else: 593 else:
557 sibling = expr.previous_sibling() 594 sibling = expr.previous_sibling()
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 if (not call.starargs 651 if (not call.starargs
615 or not isinstance(call.starargs, astroid.Name) 652 or not isinstance(call.starargs, astroid.Name)
616 or node.args.vararg != call.starargs.name): 653 or node.args.vararg != call.starargs.name):
617 return 654 return
618 elif call.starargs: 655 elif call.starargs:
619 return 656 return
620 # The "ordinary" arguments must be in a correspondence such that: 657 # The "ordinary" arguments must be in a correspondence such that:
621 # ordinary_args[i].name == call.args[i].name. 658 # ordinary_args[i].name == call.args[i].name.
622 if len(ordinary_args) != len(call.args): 659 if len(ordinary_args) != len(call.args):
623 return 660 return
624 for i in xrange(len(ordinary_args)): 661 for i in range(len(ordinary_args)):
625 if not isinstance(call.args[i], astroid.Name): 662 if not isinstance(call.args[i], astroid.Name):
626 return 663 return
627 if node.args.args[i].name != call.args[i].name: 664 if node.args.args[i].name != call.args[i].name:
628 return 665 return
629 if (isinstance(node.body.func, astroid.Getattr) and 666 if (isinstance(node.body.func, astroid.Getattr) and
630 isinstance(node.body.func.expr, astroid.CallFunc)): 667 isinstance(node.body.func.expr, astroid.CallFunc)):
631 # Chained call, the intermediate call might 668 # Chained call, the intermediate call might
632 # return something else (but we don't check that, yet). 669 # return something else (but we don't check that, yet).
633 return 670 return
634 self.add_message('unnecessary-lambda', line=node.fromlineno, node=node) 671 self.add_message('unnecessary-lambda', line=node.fromlineno, node=node)
635 672
636 @check_messages('dangerous-default-value') 673 @check_messages('dangerous-default-value')
637 def visit_function(self, node): 674 def visit_function(self, node):
638 """check function name, docstring, arguments, redefinition, 675 """check function name, docstring, arguments, redefinition,
639 variable names, max locals 676 variable names, max locals
640 """ 677 """
641 self.stats[node.is_method() and 'method' or 'function'] += 1 678 self.stats[node.is_method() and 'method' or 'function'] += 1
642 # check for dangerous default values as arguments 679 # check for dangerous default values as arguments
643 for default in node.args.defaults: 680 for default in node.args.defaults:
644 try: 681 try:
645 value = default.infer().next() 682 value = next(default.infer())
646 except astroid.InferenceError: 683 except astroid.InferenceError:
647 continue 684 continue
648 builtins = astroid.bases.BUILTINS 685
649 if (isinstance(value, astroid.Instance) and 686 if (isinstance(value, astroid.Instance) and
650 value.qname() in ['.'.join([builtins, x]) for x in ('set', ' dict', 'list')]): 687 value.qname() in DEFAULT_ARGUMENT_SYMBOLS):
651 if value is default: 688 if value is default:
652 msg = default.as_string() 689 msg = DEFAULT_ARGUMENT_SYMBOLS[value.qname()]
653 elif type(value) is astroid.Instance: 690 elif type(value) is astroid.Instance:
654 msg = '%s (%s)' % (default.as_string(), value.qname()) 691 if isinstance(default, astroid.CallFunc):
692 # this argument is direct call to list() or dict() etc
693 msg = '%s() (%s)' % (value.name, value.qname())
694 else:
695 # this argument is a variable from somewhere else which turns
696 # out to be a list or dict
697 msg = '%s (%s)' % (default.as_string(), value.qname())
655 else: 698 else:
656 msg = '%s (%s)' % (default.as_string(), value.as_string()) 699 # this argument is a name
700 msg = '%s (%s)' % (default.as_string(),
701 DEFAULT_ARGUMENT_SYMBOLS[value.qname()])
657 self.add_message('dangerous-default-value', node=node, args=(msg ,)) 702 self.add_message('dangerous-default-value', node=node, args=(msg ,))
658 703
659 @check_messages('unreachable', 'lost-exception') 704 @check_messages('unreachable', 'lost-exception')
660 def visit_return(self, node): 705 def visit_return(self, node):
661 """1 - check is the node has a right sibling (if so, that's some 706 """1 - check is the node has a right sibling (if so, that's some
662 unreachable code) 707 unreachable code)
663 2 - check is the node is inside the finally clause of a try...finally 708 2 - check is the node is inside the finally clause of a try...finally
664 block 709 block
665 """ 710 """
666 self._check_unreachable(node) 711 self._check_unreachable(node)
(...skipping 12 matching lines...) Expand all
679 """1 - check is the node has a right sibling (if so, that's some 724 """1 - check is the node has a right sibling (if so, that's some
680 unreachable code) 725 unreachable code)
681 2 - check is the node is inside the finally clause of a try...finally 726 2 - check is the node is inside the finally clause of a try...finally
682 block 727 block
683 """ 728 """
684 # 1 - Is it right sibling ? 729 # 1 - Is it right sibling ?
685 self._check_unreachable(node) 730 self._check_unreachable(node)
686 # 2 - Is it inside final body of a try...finally bloc ? 731 # 2 - Is it inside final body of a try...finally bloc ?
687 self._check_not_in_finally(node, 'break', (astroid.For, astroid.While,)) 732 self._check_not_in_finally(node, 'break', (astroid.For, astroid.While,))
688 733
689 @check_messages('unreachable', 'old-raise-syntax') 734 @check_messages('unreachable')
690 def visit_raise(self, node): 735 def visit_raise(self, node):
691 """check if the node has a right sibling (if so, that's some unreachable 736 """check if the node has a right sibling (if so, that's some unreachable
692 code) 737 code)
693 """ 738 """
694 self._check_unreachable(node) 739 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 740
700 @check_messages('exec-used') 741 @check_messages('exec-used')
701 def visit_exec(self, node): 742 def visit_exec(self, node):
702 """just print a warning on exec statements""" 743 """just print a warning on exec statements"""
703 self.add_message('exec-used', node=node) 744 self.add_message('exec-used', node=node)
704 745
705 @check_messages('bad-builtin', 'star-args', 'eval-used', 746 @check_messages('bad-builtin', 'star-args', 'eval-used',
706 'exec-used', 'missing-reversed-argument', 747 'exec-used', 'missing-reversed-argument',
707 'bad-reversed-sequence') 748 'bad-reversed-sequence')
708 def visit_callfunc(self, node): 749 def visit_callfunc(self, node):
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 if isinstance(k, astroid.Const): 792 if isinstance(k, astroid.Const):
752 key = k.value 793 key = k.value
753 if key in keys: 794 if key in keys:
754 self.add_message('duplicate-key', node=node, args=key) 795 self.add_message('duplicate-key', node=node, args=key)
755 keys.add(key) 796 keys.add(key)
756 797
757 def visit_tryfinally(self, node): 798 def visit_tryfinally(self, node):
758 """update try...finally flag""" 799 """update try...finally flag"""
759 self._tryfinallys.append(node) 800 self._tryfinallys.append(node)
760 801
761 def leave_tryfinally(self, node): 802 def leave_tryfinally(self, node): # pylint: disable=unused-argument
762 """update try...finally flag""" 803 """update try...finally flag"""
763 self._tryfinallys.pop() 804 self._tryfinallys.pop()
764 805
765 def _check_unreachable(self, node): 806 def _check_unreachable(self, node):
766 """check unreachable code""" 807 """check unreachable code"""
767 unreach_stmt = node.next_sibling() 808 unreach_stmt = node.next_sibling()
768 if unreach_stmt is not None: 809 if unreach_stmt is not None:
769 self.add_message('unreachable', node=unreach_stmt) 810 self.add_message('unreachable', node=unreach_stmt)
770 811
771 def _check_not_in_finally(self, node, node_name, breaker_classes=()): 812 def _check_not_in_finally(self, node, node_name, breaker_classes=()):
(...skipping 17 matching lines...) Expand all
789 def _check_reversed(self, node): 830 def _check_reversed(self, node):
790 """ check that the argument to `reversed` is a sequence """ 831 """ check that the argument to `reversed` is a sequence """
791 try: 832 try:
792 argument = safe_infer(get_argument_from_call(node, position=0)) 833 argument = safe_infer(get_argument_from_call(node, position=0))
793 except NoSuchArgumentError: 834 except NoSuchArgumentError:
794 self.add_message('missing-reversed-argument', node=node) 835 self.add_message('missing-reversed-argument', node=node)
795 else: 836 else:
796 if argument is astroid.YES: 837 if argument is astroid.YES:
797 return 838 return
798 if argument is None: 839 if argument is None:
799 # nothing was infered 840 # Nothing was infered.
800 # try to see if we have iter() 841 # Try to see if we have iter().
801 if isinstance(node.args[0], astroid.CallFunc): 842 if isinstance(node.args[0], astroid.CallFunc):
802 try: 843 try:
803 func = node.args[0].func.infer().next() 844 func = next(node.args[0].func.infer())
804 except InferenceError: 845 except InferenceError:
805 return 846 return
806 if (getattr(func, 'name', None) == 'iter' and 847 if (getattr(func, 'name', None) == 'iter' and
807 is_builtin_object(func)): 848 is_builtin_object(func)):
808 self.add_message('bad-reversed-sequence', node=node) 849 self.add_message('bad-reversed-sequence', node=node)
809 return 850 return
810 851
811 if isinstance(argument, astroid.Instance): 852 if isinstance(argument, astroid.Instance):
812 if (argument._proxied.name == 'dict' and 853 if (argument._proxied.name == 'dict' and
813 is_builtin_object(argument._proxied)): 854 is_builtin_object(argument._proxied)):
814 self.add_message('bad-reversed-sequence', node=node) 855 self.add_message('bad-reversed-sequence', node=node)
815 return 856 return
816 elif any(ancestor.name == 'dict' and is_builtin_object(ancestor) 857 elif any(ancestor.name == 'dict' and is_builtin_object(ancestor)
817 for ancestor in argument._proxied.ancestors()): 858 for ancestor in argument._proxied.ancestors()):
818 # mappings aren't accepted by reversed() 859 # mappings aren't accepted by reversed()
819 self.add_message('bad-reversed-sequence', node=node) 860 self.add_message('bad-reversed-sequence', node=node)
820 return 861 return
821 862
822 for methods in REVERSED_METHODS: 863 for methods in REVERSED_METHODS:
823 for meth in methods: 864 for meth in methods:
824 try: 865 try:
825 argument.getattr(meth) 866 argument.getattr(meth)
826 except astroid.NotFoundError: 867 except astroid.NotFoundError:
827 break 868 break
828 else: 869 else:
829 break 870 break
830 else: 871 else:
831 # check if it is a .deque. It doesn't seem that 872 # Check if it is a .deque. It doesn't seem that
832 # we can retrieve special methods 873 # we can retrieve special methods
833 # from C implemented constructs 874 # from C implemented constructs.
834 if argument._proxied.qname().endswith(".deque"): 875 if argument._proxied.qname().endswith(".deque"):
835 return 876 return
836 self.add_message('bad-reversed-sequence', node=node) 877 self.add_message('bad-reversed-sequence', node=node)
837 elif not isinstance(argument, (astroid.List, astroid.Tuple)): 878 elif not isinstance(argument, (astroid.List, astroid.Tuple)):
838 # everything else is not a proper sequence for reversed() 879 # everything else is not a proper sequence for reversed()
839 self.add_message('bad-reversed-sequence', node=node) 880 self.add_message('bad-reversed-sequence', node=node)
840 881
841 _NAME_TYPES = { 882 _NAME_TYPES = {
842 'module': (MOD_NAME_RGX, 'module'), 883 'module': (MOD_NAME_RGX, 'module'),
843 'const': (CONST_NAME_RGX, 'constant'), 884 'const': (CONST_NAME_RGX, 'constant'),
844 'class': (CLASS_NAME_RGX, 'class'), 885 'class': (CLASS_NAME_RGX, 'class'),
845 'function': (DEFAULT_NAME_RGX, 'function'), 886 'function': (DEFAULT_NAME_RGX, 'function'),
846 'method': (DEFAULT_NAME_RGX, 'method'), 887 'method': (DEFAULT_NAME_RGX, 'method'),
847 'attr': (DEFAULT_NAME_RGX, 'attribute'), 888 'attr': (DEFAULT_NAME_RGX, 'attribute'),
848 'argument': (DEFAULT_NAME_RGX, 'argument'), 889 'argument': (DEFAULT_NAME_RGX, 'argument'),
849 'variable': (DEFAULT_NAME_RGX, 'variable'), 890 'variable': (DEFAULT_NAME_RGX, 'variable'),
850 'class_attribute': (CLASS_ATTRIBUTE_RGX, 'class attribute'), 891 'class_attribute': (CLASS_ATTRIBUTE_RGX, 'class attribute'),
851 'inlinevar': (COMP_VAR_RGX, 'inline iteration'), 892 'inlinevar': (COMP_VAR_RGX, 'inline iteration'),
852 } 893 }
853 894
854 def _create_naming_options(): 895 def _create_naming_options():
855 name_options = [] 896 name_options = []
856 for name_type, (rgx, human_readable_name) in _NAME_TYPES.iteritems(): 897 for name_type, (rgx, human_readable_name) in six.iteritems(_NAME_TYPES):
857 name_type = name_type.replace('_', '-') 898 name_type = name_type.replace('_', '-')
858 name_options.append(( 899 name_options.append((
859 '%s-rgx' % (name_type,), 900 '%s-rgx' % (name_type,),
860 {'default': rgx, 'type': 'regexp', 'metavar': '<regexp>', 901 {'default': rgx, 'type': 'regexp', 'metavar': '<regexp>',
861 'help': 'Regular expression matching correct %s names' % (human_rea dable_name,)})) 902 'help': 'Regular expression matching correct %s names' % (human_rea dable_name,)}))
862 name_options.append(( 903 name_options.append((
863 '%s-name-hint' % (name_type,), 904 '%s-name-hint' % (name_type,),
864 {'default': rgx.pattern, 'type': 'string', 'metavar': '<string>', 905 {'default': rgx.pattern, 'type': 'string', 'metavar': '<string>',
865 'help': 'Naming hint for %s names' % (human_readable_name,)})) 906 'help': 'Naming hint for %s names' % (human_readable_name,)}))
866 return tuple(name_options) 907 return tuple(name_options)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>', 941 {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>',
901 'help': 'Include a hint for the correct naming format with inva lid-name'} 942 'help': 'Include a hint for the correct naming format with inva lid-name'}
902 ), 943 ),
903 ) + _create_naming_options() 944 ) + _create_naming_options()
904 945
905 946
906 def __init__(self, linter): 947 def __init__(self, linter):
907 _BasicChecker.__init__(self, linter) 948 _BasicChecker.__init__(self, linter)
908 self._name_category = {} 949 self._name_category = {}
909 self._name_group = {} 950 self._name_group = {}
951 self._bad_names = {}
910 952
911 def open(self): 953 def open(self):
912 self.stats = self.linter.add_stats(badname_module=0, 954 self.stats = self.linter.add_stats(badname_module=0,
913 badname_class=0, badname_function=0, 955 badname_class=0, badname_function=0,
914 badname_method=0, badname_attr=0, 956 badname_method=0, badname_attr=0,
915 badname_const=0, 957 badname_const=0,
916 badname_variable=0, 958 badname_variable=0,
917 badname_inlinevar=0, 959 badname_inlinevar=0,
918 badname_argument=0, 960 badname_argument=0,
919 badname_class_attribute=0) 961 badname_class_attribute=0)
920 for group in self.config.name_group: 962 for group in self.config.name_group:
921 for name_type in group.split(':'): 963 for name_type in group.split(':'):
922 self._name_group[name_type] = 'group_%s' % (group,) 964 self._name_group[name_type] = 'group_%s' % (group,)
923 965
924 @check_messages('blacklisted-name', 'invalid-name') 966 @check_messages('blacklisted-name', 'invalid-name')
925 def visit_module(self, node): 967 def visit_module(self, node):
926 self._check_name('module', node.name.split('.')[-1], node) 968 self._check_name('module', node.name.split('.')[-1], node)
969 self._bad_names = {}
970
971 def leave_module(self, node): # pylint: disable=unused-argument
972 for all_groups in six.itervalues(self._bad_names):
973 if len(all_groups) < 2:
974 continue
975 groups = collections.defaultdict(list)
976 min_warnings = sys.maxsize
977 for group in six.itervalues(all_groups):
978 groups[len(group)].append(group)
979 min_warnings = min(len(group), min_warnings)
980 if len(groups[min_warnings]) > 1:
981 by_line = sorted(groups[min_warnings],
982 key=lambda group: min(warning[0].lineno for war ning in group))
983 warnings = itertools.chain(*by_line[1:])
984 else:
985 warnings = groups[min_warnings][0]
986 for args in warnings:
987 self._raise_name_warning(*args)
927 988
928 @check_messages('blacklisted-name', 'invalid-name') 989 @check_messages('blacklisted-name', 'invalid-name')
929 def visit_class(self, node): 990 def visit_class(self, node):
930 self._check_name('class', node.name, node) 991 self._check_name('class', node.name, node)
931 for attr, anodes in node.instance_attrs.iteritems(): 992 for attr, anodes in six.iteritems(node.instance_attrs):
932 if not list(node.instance_attr_ancestors(attr)): 993 if not list(node.instance_attr_ancestors(attr)):
933 self._check_name('attr', attr, anodes[0]) 994 self._check_name('attr', attr, anodes[0])
934 995
935 @check_messages('blacklisted-name', 'invalid-name') 996 @check_messages('blacklisted-name', 'invalid-name')
936 def visit_function(self, node): 997 def visit_function(self, node):
937 # Do not emit any warnings if the method is just an implementation 998 # Do not emit any warnings if the method is just an implementation
938 # of a base class method. 999 # of a base class method.
939 if node.is_method() and overrides_a_method(node.parent.frame(), node.nam e): 1000 confidence = HIGH
940 return 1001 if node.is_method():
1002 if overrides_a_method(node.parent.frame(), node.name):
1003 return
1004 confidence = (INFERENCE if has_known_bases(node.parent.frame())
1005 else INFERENCE_FAILURE)
1006
941 self._check_name(_determine_function_name_type(node), 1007 self._check_name(_determine_function_name_type(node),
942 node.name, node) 1008 node.name, node, confidence)
943 # Check argument names 1009 # Check argument names
944 args = node.args.args 1010 args = node.args.args
945 if args is not None: 1011 if args is not None:
946 self._recursive_check_names(args, node) 1012 self._recursive_check_names(args, node)
947 1013
948 @check_messages('blacklisted-name', 'invalid-name') 1014 @check_messages('blacklisted-name', 'invalid-name')
949 def visit_global(self, node): 1015 def visit_global(self, node):
950 for name in node.names: 1016 for name in node.names:
951 self._check_name('const', name, node) 1017 self._check_name('const', name, node)
952 1018
953 @check_messages('blacklisted-name', 'invalid-name') 1019 @check_messages('blacklisted-name', 'invalid-name')
954 def visit_assname(self, node): 1020 def visit_assname(self, node):
955 """check module level assigned names""" 1021 """check module level assigned names"""
956 frame = node.frame() 1022 frame = node.frame()
957 ass_type = node.ass_type() 1023 ass_type = node.ass_type()
958 if isinstance(ass_type, astroid.Comprehension): 1024 if isinstance(ass_type, astroid.Comprehension):
959 self._check_name('inlinevar', node.name, node) 1025 self._check_name('inlinevar', node.name, node)
960 elif isinstance(frame, astroid.Module): 1026 elif isinstance(frame, astroid.Module):
961 if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type): 1027 if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type):
962 if isinstance(safe_infer(ass_type.value), astroid.Class): 1028 if isinstance(safe_infer(ass_type.value), astroid.Class):
963 self._check_name('class', node.name, node) 1029 self._check_name('class', node.name, node)
964 else: 1030 else:
965 self._check_name('const', node.name, node) 1031 if not _redefines_import(node):
1032 # Don't emit if the name redefines an import
1033 # in an ImportError except handler.
1034 self._check_name('const', node.name, node)
966 elif isinstance(ass_type, astroid.ExceptHandler): 1035 elif isinstance(ass_type, astroid.ExceptHandler):
967 self._check_name('variable', node.name, node) 1036 self._check_name('variable', node.name, node)
968 elif isinstance(frame, astroid.Function): 1037 elif isinstance(frame, astroid.Function):
969 # global introduced variable aren't in the function locals 1038 # global introduced variable aren't in the function locals
970 if node.name in frame and node.name not in frame.argnames(): 1039 if node.name in frame and node.name not in frame.argnames():
971 self._check_name('variable', node.name, node) 1040 if not _redefines_import(node):
1041 self._check_name('variable', node.name, node)
972 elif isinstance(frame, astroid.Class): 1042 elif isinstance(frame, astroid.Class):
973 if not list(frame.local_attr_ancestors(node.name)): 1043 if not list(frame.local_attr_ancestors(node.name)):
974 self._check_name('class_attribute', node.name, node) 1044 self._check_name('class_attribute', node.name, node)
975 1045
976 def _recursive_check_names(self, args, node): 1046 def _recursive_check_names(self, args, node):
977 """check names in a possibly recursive list <arg>""" 1047 """check names in a possibly recursive list <arg>"""
978 for arg in args: 1048 for arg in args:
979 if isinstance(arg, astroid.AssName): 1049 if isinstance(arg, astroid.AssName):
980 self._check_name('argument', arg.name, node) 1050 self._check_name('argument', arg.name, node)
981 else: 1051 else:
982 self._recursive_check_names(arg.elts, node) 1052 self._recursive_check_names(arg.elts, node)
983 1053
984 def _find_name_group(self, node_type): 1054 def _find_name_group(self, node_type):
985 return self._name_group.get(node_type, node_type) 1055 return self._name_group.get(node_type, node_type)
986 1056
987 def _is_multi_naming_match(self, match): 1057 def _raise_name_warning(self, node, node_type, name, confidence):
988 return (match is not None and 1058 type_label = _NAME_TYPES[node_type][1]
989 match.lastgroup is not None and 1059 hint = ''
990 match.lastgroup not in EXEMPT_NAME_CATEGORIES) 1060 if self.config.include_naming_hint:
1061 hint = ' (hint: %s)' % (getattr(self.config, node_type + '_name_hint '))
1062 self.add_message('invalid-name', node=node, args=(type_label, name, hint ),
1063 confidence=confidence)
1064 self.stats['badname_' + node_type] += 1
991 1065
992 def _check_name(self, node_type, name, node): 1066 def _check_name(self, node_type, name, node, confidence=HIGH):
993 """check for a name using the type's regexp""" 1067 """check for a name using the type's regexp"""
994 if is_inside_except(node): 1068 if is_inside_except(node):
995 clobbering, _ = clobber_in_except(node) 1069 clobbering, _ = clobber_in_except(node)
996 if clobbering: 1070 if clobbering:
997 return 1071 return
998 if name in self.config.good_names: 1072 if name in self.config.good_names:
999 return 1073 return
1000 if name in self.config.bad_names: 1074 if name in self.config.bad_names:
1001 self.stats['badname_' + node_type] += 1 1075 self.stats['badname_' + node_type] += 1
1002 self.add_message('blacklisted-name', node=node, args=name) 1076 self.add_message('blacklisted-name', node=node, args=name)
1003 return 1077 return
1004 regexp = getattr(self.config, node_type + '_rgx') 1078 regexp = getattr(self.config, node_type + '_rgx')
1005 match = regexp.match(name) 1079 match = regexp.match(name)
1006 1080
1007 if self._is_multi_naming_match(match): 1081 if _is_multi_naming_match(match, node_type, confidence):
1008 name_group = self._find_name_group(node_type) 1082 name_group = self._find_name_group(node_type)
1009 if name_group not in self._name_category: 1083 bad_name_group = self._bad_names.setdefault(name_group, {})
1010 self._name_category[name_group] = match.lastgroup 1084 warnings = bad_name_group.setdefault(match.lastgroup, [])
1011 elif self._name_category[name_group] != match.lastgroup: 1085 warnings.append((node, node_type, name, confidence))
1012 match = None
1013 1086
1014 if match is None: 1087 if match is None:
1015 type_label = _NAME_TYPES[node_type][1] 1088 self._raise_name_warning(node, node_type, name, confidence)
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
1021 1089
1022 1090
1023 class DocStringChecker(_BasicChecker): 1091 class DocStringChecker(_BasicChecker):
1024 msgs = { 1092 msgs = {
1025 'C0111': ('Missing %s docstring', # W0131 1093 'C0111': ('Missing %s docstring', # W0131
1026 'missing-docstring', 1094 'missing-docstring',
1027 'Used when a module, function, class or method has no docstrin g.' 1095 'Used when a module, function, class or method has no docstrin g.'
1028 'Some special methods like __init__ doesn\'t necessary require a ' 1096 'Some special methods like __init__ doesn\'t necessary require a '
1029 'docstring.'), 1097 'docstring.'),
1030 'C0112': ('Empty %s docstring', # W0132 1098 'C0112': ('Empty %s docstring', # W0132
(...skipping 23 matching lines...) Expand all
1054 undocumented_method=0, 1122 undocumented_method=0,
1055 undocumented_class=0) 1123 undocumented_class=0)
1056 @check_messages('missing-docstring', 'empty-docstring') 1124 @check_messages('missing-docstring', 'empty-docstring')
1057 def visit_module(self, node): 1125 def visit_module(self, node):
1058 self._check_docstring('module', node) 1126 self._check_docstring('module', node)
1059 1127
1060 @check_messages('missing-docstring', 'empty-docstring') 1128 @check_messages('missing-docstring', 'empty-docstring')
1061 def visit_class(self, node): 1129 def visit_class(self, node):
1062 if self.config.no_docstring_rgx.match(node.name) is None: 1130 if self.config.no_docstring_rgx.match(node.name) is None:
1063 self._check_docstring('class', node) 1131 self._check_docstring('class', node)
1132
1064 @check_messages('missing-docstring', 'empty-docstring') 1133 @check_messages('missing-docstring', 'empty-docstring')
1065 def visit_function(self, node): 1134 def visit_function(self, node):
1066 if self.config.no_docstring_rgx.match(node.name) is None: 1135 if self.config.no_docstring_rgx.match(node.name) is None:
1067 ftype = node.is_method() and 'method' or 'function' 1136 ftype = node.is_method() and 'method' or 'function'
1068 if isinstance(node.parent.frame(), astroid.Class): 1137 if isinstance(node.parent.frame(), astroid.Class):
1069 overridden = False 1138 overridden = False
1139 confidence = (INFERENCE if has_known_bases(node.parent.frame())
1140 else INFERENCE_FAILURE)
1070 # check if node is from a method overridden by its ancestor 1141 # check if node is from a method overridden by its ancestor
1071 for ancestor in node.parent.frame().ancestors(): 1142 for ancestor in node.parent.frame().ancestors():
1072 if node.name in ancestor and \ 1143 if node.name in ancestor and \
1073 isinstance(ancestor[node.name], astroid.Function): 1144 isinstance(ancestor[node.name], astroid.Function):
1074 overridden = True 1145 overridden = True
1075 break 1146 break
1076 self._check_docstring(ftype, node, 1147 self._check_docstring(ftype, node,
1077 report_missing=not overridden) 1148 report_missing=not overridden,
1149 confidence=confidence)
1078 else: 1150 else:
1079 self._check_docstring(ftype, node) 1151 self._check_docstring(ftype, node)
1080 1152
1081 def _check_docstring(self, node_type, node, report_missing=True): 1153 def _check_docstring(self, node_type, node, report_missing=True,
1154 confidence=HIGH):
1082 """check the node has a non empty docstring""" 1155 """check the node has a non empty docstring"""
1083 docstring = node.doc 1156 docstring = node.doc
1084 if docstring is None: 1157 if docstring is None:
1085 if not report_missing: 1158 if not report_missing:
1086 return 1159 return
1087 if node.body: 1160 if node.body:
1088 lines = node.body[-1].lineno - node.body[0].lineno + 1 1161 lines = node.body[-1].lineno - node.body[0].lineno + 1
1089 else: 1162 else:
1090 lines = 0 1163 lines = 0
1091 max_lines = self.config.docstring_min_length 1164 max_lines = self.config.docstring_min_length
1092 1165
1093 if node_type != 'module' and max_lines > -1 and lines < max_lines: 1166 if node_type != 'module' and max_lines > -1 and lines < max_lines:
1094 return 1167 return
1095 self.stats['undocumented_'+node_type] += 1 1168 self.stats['undocumented_'+node_type] += 1
1096 if (node.body and isinstance(node.body[0], astroid.Discard) and 1169 if (node.body and isinstance(node.body[0], astroid.Discard) and
1097 isinstance(node.body[0].value, astroid.CallFunc)): 1170 isinstance(node.body[0].value, astroid.CallFunc)):
1098 # Most likely a string with a format call. Let's see. 1171 # Most likely a string with a format call. Let's see.
1099 func = safe_infer(node.body[0].value.func) 1172 func = safe_infer(node.body[0].value.func)
1100 if (isinstance(func, astroid.BoundMethod) 1173 if (isinstance(func, astroid.BoundMethod)
1101 and isinstance(func.bound, astroid.Instance)): 1174 and isinstance(func.bound, astroid.Instance)):
1102 # Strings in Python 3, others in Python 2. 1175 # Strings in Python 3, others in Python 2.
1103 if PY3K and func.bound.name == 'str': 1176 if PY3K and func.bound.name == 'str':
1104 return 1177 return
1105 elif func.bound.name in ('str', 'unicode', 'bytes'): 1178 elif func.bound.name in ('str', 'unicode', 'bytes'):
1106 return 1179 return
1107 self.add_message('missing-docstring', node=node, args=(node_type,)) 1180 self.add_message('missing-docstring', node=node, args=(node_type,),
1181 confidence=confidence)
1108 elif not docstring.strip(): 1182 elif not docstring.strip():
1109 self.stats['undocumented_'+node_type] += 1 1183 self.stats['undocumented_'+node_type] += 1
1110 self.add_message('empty-docstring', node=node, args=(node_type,)) 1184 self.add_message('empty-docstring', node=node, args=(node_type,),
1185 confidence=confidence)
1111 1186
1112 1187
1113 class PassChecker(_BasicChecker): 1188 class PassChecker(_BasicChecker):
1114 """check if the pass statement is really necessary""" 1189 """check if the pass statement is really necessary"""
1115 msgs = {'W0107': ('Unnecessary pass statement', 1190 msgs = {'W0107': ('Unnecessary pass statement',
1116 'unnecessary-pass', 1191 'unnecessary-pass',
1117 'Used when a "pass" statement that can be avoided is ' 1192 'Used when a "pass" statement that can be avoided is '
1118 'encountered.'), 1193 'encountered.'),
1119 } 1194 }
1120 @check_messages('unnecessary-pass') 1195 @check_messages('unnecessary-pass')
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 1229
1155 1230
1156 def register(linter): 1231 def register(linter):
1157 """required method to auto register this checker""" 1232 """required method to auto register this checker"""
1158 linter.register_checker(BasicErrorChecker(linter)) 1233 linter.register_checker(BasicErrorChecker(linter))
1159 linter.register_checker(BasicChecker(linter)) 1234 linter.register_checker(BasicChecker(linter))
1160 linter.register_checker(NameChecker(linter)) 1235 linter.register_checker(NameChecker(linter))
1161 linter.register_checker(DocStringChecker(linter)) 1236 linter.register_checker(DocStringChecker(linter))
1162 linter.register_checker(PassChecker(linter)) 1237 linter.register_checker(PassChecker(linter))
1163 linter.register_checker(LambdaForComprehensionChecker(linter)) 1238 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