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

Side by Side Diff: third_party/pylint/checkers/variables.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/utils.py ('k') | third_party/pylint/config.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-2014 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # 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
5 # 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
6 # 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
7 # version. 7 # version.
8 # 8 #
9 # 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
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 # 12 #
13 # 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
14 # this program; if not, write to the Free Software Foundation, Inc., 14 # this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 """variables checkers for Python code 16 """variables checkers for Python code
17 """ 17 """
18 import os 18 import os
19 import sys 19 import sys
20 import re
20 from copy import copy 21 from copy import copy
21 22
22 import astroid 23 import astroid
23 from astroid import are_exclusive, builtin_lookup, AstroidBuildingException 24 from astroid import are_exclusive, builtin_lookup
25 from astroid import modutils
24 26
25 from logilab.common.modutils import file_from_modpath 27 from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE, HIG H
26
27 from pylint.interfaces import IAstroidChecker
28 from pylint.utils import get_global_option 28 from pylint.utils import get_global_option
29 from pylint.checkers import BaseChecker 29 from pylint.checkers import BaseChecker
30 from pylint.checkers.utils import ( 30 from pylint.checkers.utils import (
31 PYMETHODS, is_ancestor_name, is_builtin, 31 PYMETHODS, is_ancestor_name, is_builtin,
32 is_defined_before, is_error, is_func_default, is_func_decorator, 32 is_defined_before, is_error, is_func_default, is_func_decorator,
33 assign_parent, check_messages, is_inside_except, clobber_in_except, 33 assign_parent, check_messages, is_inside_except, clobber_in_except,
34 get_all_elements) 34 get_all_elements, has_known_bases)
35 import six
35 36
37 SPECIAL_OBJ = re.compile("^_{2}[a-z]+_{2}$")
38
39 PY3K = sys.version_info >= (3, 0)
36 40
37 def in_for_else_branch(parent, stmt): 41 def in_for_else_branch(parent, stmt):
38 """Returns True if stmt in inside the else branch for a parent For stmt.""" 42 """Returns True if stmt in inside the else branch for a parent For stmt."""
39 return (isinstance(parent, astroid.For) and 43 return (isinstance(parent, astroid.For) and
40 any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse)) 44 any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse))
41 45
42 def overridden_method(klass, name): 46 def overridden_method(klass, name):
43 """get overridden method if any""" 47 """get overridden method if any"""
44 try: 48 try:
45 parent = klass.local_attr_ancestors(name).next() 49 parent = next(klass.local_attr_ancestors(name))
46 except (StopIteration, KeyError): 50 except (StopIteration, KeyError):
47 return None 51 return None
48 try: 52 try:
49 meth_node = parent[name] 53 meth_node = parent[name]
50 except KeyError: 54 except KeyError:
51 # We have found an ancestor defining <name> but it's not in the local 55 # We have found an ancestor defining <name> but it's not in the local
52 # dictionary. This may happen with astroid built from living objects. 56 # dictionary. This may happen with astroid built from living objects.
53 return None 57 return None
54 if isinstance(meth_node, astroid.Function): 58 if isinstance(meth_node, astroid.Function):
55 return meth_node 59 return meth_node
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 # If the stored scopes are, in fact, the very same, then it means 131 # If the stored scopes are, in fact, the very same, then it means
128 # that the two frames (frame and defframe) shares the same scope, 132 # that the two frames (frame and defframe) shares the same scope,
129 # and we could apply our lineno analysis over them. 133 # and we could apply our lineno analysis over them.
130 # For instance, this works when they are inside a function, the node 134 # For instance, this works when they are inside a function, the node
131 # that uses a definition and the definition itself. 135 # that uses a definition and the definition itself.
132 return False 136 return False
133 # At this point, we are certain that frame and defframe shares a scope 137 # At this point, we are certain that frame and defframe shares a scope
134 # and the definition of the first depends on the second. 138 # and the definition of the first depends on the second.
135 return frame.lineno < defframe.lineno 139 return frame.lineno < defframe.lineno
136 140
141 def _fix_dot_imports(not_consumed):
142 """ Try to fix imports with multiple dots, by returning a dictionary
143 with the import names expanded. The function unflattens root imports,
144 like 'xml' (when we have both 'xml.etree' and 'xml.sax'), to 'xml.etree'
145 and 'xml.sax' respectively.
146 """
147 # TODO: this should be improved in issue astroid #46
148 names = {}
149 for name, stmts in six.iteritems(not_consumed):
150 if any(isinstance(stmt, astroid.AssName)
151 and isinstance(stmt.ass_type(), astroid.AugAssign)
152 for stmt in stmts):
153 continue
154 for stmt in stmts:
155 if not isinstance(stmt, (astroid.From, astroid.Import)):
156 continue
157 for imports in stmt.names:
158 second_name = None
159 if imports[0] == "*":
160 # In case of wildcard imports,
161 # pick the name from inside the imported module.
162 second_name = name
163 else:
164 if imports[0].find(".") > -1 or name in imports:
165 # Most likely something like 'xml.etree',
166 # which will appear in the .locals as 'xml'.
167 # Only pick the name if it wasn't consumed.
168 second_name = imports[0]
169 if second_name and second_name not in names:
170 names[second_name] = stmt
171 return sorted(names.items(), key=lambda a: a[1].fromlineno)
172
173 def _find_frame_imports(name, frame):
174 """
175 Detect imports in the frame, with the required
176 *name*. Such imports can be considered assignments.
177 Returns True if an import for the given name was found.
178 """
179 imports = frame.nodes_of_class((astroid.Import, astroid.From))
180 for import_node in imports:
181 for import_name, import_alias in import_node.names:
182 # If the import uses an alias, check only that.
183 # Otherwise, check only the import name.
184 if import_alias:
185 if import_alias == name:
186 return True
187 elif import_name and import_name == name:
188 return True
189
137 190
138 MSGS = { 191 MSGS = {
139 'E0601': ('Using variable %r before assignment', 192 'E0601': ('Using variable %r before assignment',
140 'used-before-assignment', 193 'used-before-assignment',
141 'Used when a local variable is accessed before it\'s \ 194 'Used when a local variable is accessed before it\'s \
142 assignment.'), 195 assignment.'),
143 'E0602': ('Undefined variable %r', 196 'E0602': ('Undefined variable %r',
144 'undefined-variable', 197 'undefined-variable',
145 'Used when an undefined variable is accessed.'), 198 'Used when an undefined variable is accessed.'),
146 'E0603': ('Undefined variable name %r in __all__', 199 'E0603': ('Undefined variable name %r in __all__',
(...skipping 10 matching lines...) Expand all
157 'global-variable-undefined', 210 'global-variable-undefined',
158 'Used when a variable is defined through the "global" statement \ 211 'Used when a variable is defined through the "global" statement \
159 but the variable is not defined in the module scope.'), 212 but the variable is not defined in the module scope.'),
160 'W0602': ('Using global for %r but no assignment is done', 213 'W0602': ('Using global for %r but no assignment is done',
161 'global-variable-not-assigned', 214 'global-variable-not-assigned',
162 'Used when a variable is defined through the "global" statement \ 215 'Used when a variable is defined through the "global" statement \
163 but no assignment to this variable is done.'), 216 but no assignment to this variable is done.'),
164 'W0603': ('Using the global statement', # W0121 217 'W0603': ('Using the global statement', # W0121
165 'global-statement', 218 'global-statement',
166 'Used when you use the "global" statement to update a global \ 219 'Used when you use the "global" statement to update a global \
167 variable. PyLint just try to discourage this \ 220 variable. Pylint just try to discourage this \
168 usage. That doesn\'t mean you can not use it !'), 221 usage. That doesn\'t mean you can not use it !'),
169 'W0604': ('Using the global statement at the module level', # W0103 222 'W0604': ('Using the global statement at the module level', # W0103
170 'global-at-module-level', 223 'global-at-module-level',
171 'Used when you use the "global" statement at the module level \ 224 'Used when you use the "global" statement at the module level \
172 since it has no effect'), 225 since it has no effect'),
173 'W0611': ('Unused import %s', 226 'W0611': ('Unused %s',
174 'unused-import', 227 'unused-import',
175 'Used when an imported module or variable is not used.'), 228 'Used when an imported module or variable is not used.'),
176 'W0612': ('Unused variable %r', 229 'W0612': ('Unused variable %r',
177 'unused-variable', 230 'unused-variable',
178 'Used when a variable is defined but not used.'), 231 'Used when a variable is defined but not used.'),
179 'W0613': ('Unused argument %r', 232 'W0613': ('Unused argument %r',
180 'unused-argument', 233 'unused-argument',
181 'Used when a function or method argument is not used.'), 234 'Used when a function or method argument is not used.'),
182 'W0614': ('Unused import %s from wildcard import', 235 'W0614': ('Unused import %s from wildcard import',
183 'unused-wildcard-import', 236 'unused-wildcard-import',
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 {'default': ('_$|dummy'), 296 {'default': ('_$|dummy'),
244 'type' :'regexp', 'metavar' : '<regexp>', 297 'type' :'regexp', 'metavar' : '<regexp>',
245 'help' : 'A regular expression matching the name of dummy \ 298 'help' : 'A regular expression matching the name of dummy \
246 variables (i.e. expectedly not used).'}), 299 variables (i.e. expectedly not used).'}),
247 ("additional-builtins", 300 ("additional-builtins",
248 {'default': (), 'type' : 'csv', 301 {'default': (), 'type' : 'csv',
249 'metavar' : '<comma separated list>', 302 'metavar' : '<comma separated list>',
250 'help' : 'List of additional names supposed to be defined in \ 303 'help' : 'List of additional names supposed to be defined in \
251 builtins. Remember that you should avoid to define new builtins when possible.' 304 builtins. Remember that you should avoid to define new builtins when possible.'
252 }), 305 }),
306 ("callbacks",
307 {'default' : ('cb_', '_cb'), 'type' : 'csv',
308 'metavar' : '<callbacks>',
309 'help' : 'List of strings which can identify a callback '
310 'function by name. A callback name must start or '
311 'end with one of those strings.'}
312 )
253 ) 313 )
254 def __init__(self, linter=None): 314 def __init__(self, linter=None):
255 BaseChecker.__init__(self, linter) 315 BaseChecker.__init__(self, linter)
256 self._to_consume = None 316 self._to_consume = None
257 self._checking_mod_attr = None 317 self._checking_mod_attr = None
258 318
259 def visit_module(self, node): 319 def visit_module(self, node):
260 """visit module : update consumption analysis variable 320 """visit module : update consumption analysis variable
261 checks globals doesn't overrides builtins 321 checks globals doesn't overrides builtins
262 """ 322 """
263 self._to_consume = [(copy(node.locals), {}, 'module')] 323 self._to_consume = [(copy(node.locals), {}, 'module')]
264 for name, stmts in node.locals.iteritems(): 324 for name, stmts in six.iteritems(node.locals):
265 if is_builtin(name) and not is_inside_except(stmts[0]): 325 if is_builtin(name) and not is_inside_except(stmts[0]):
266 # do not print Redefining builtin for additional builtins 326 # do not print Redefining builtin for additional builtins
267 self.add_message('redefined-builtin', args=name, node=stmts[0]) 327 self.add_message('redefined-builtin', args=name, node=stmts[0])
268 328
269 @check_messages('unused-import', 'unused-wildcard-import', 'redefined-builti n', 'undefined-all-variable', 'invalid-all-object') 329 @check_messages('unused-import', 'unused-wildcard-import',
330 'redefined-builtin', 'undefined-all-variable',
331 'invalid-all-object')
270 def leave_module(self, node): 332 def leave_module(self, node):
271 """leave module: check globals 333 """leave module: check globals
272 """ 334 """
273 assert len(self._to_consume) == 1 335 assert len(self._to_consume) == 1
274 not_consumed = self._to_consume.pop()[0] 336 not_consumed = self._to_consume.pop()[0]
275 # attempt to check for __all__ if defined 337 # attempt to check for __all__ if defined
276 if '__all__' in node.locals: 338 if '__all__' in node.locals:
277 assigned = node.igetattr('__all__').next() 339 assigned = next(node.igetattr('__all__'))
278 if assigned is not astroid.YES: 340 if assigned is not astroid.YES:
279 for elt in getattr(assigned, 'elts', ()): 341 for elt in getattr(assigned, 'elts', ()):
280 try: 342 try:
281 elt_name = elt.infer().next() 343 elt_name = next(elt.infer())
282 except astroid.InferenceError: 344 except astroid.InferenceError:
283 continue 345 continue
284 346
285 if not isinstance(elt_name, astroid.Const) \ 347 if not isinstance(elt_name, astroid.Const) \
286 or not isinstance(elt_name.value, basestring): 348 or not isinstance(elt_name.value, six.string_types) :
287 self.add_message('invalid-all-object', args=elt.as_strin g(), node=elt) 349 self.add_message('invalid-all-object',
350 args=elt.as_string(), node=elt)
288 continue 351 continue
289 elt_name = elt_name.value 352 elt_name = elt_name.value
290 # If elt is in not_consumed, remove it from not_consumed 353 # If elt is in not_consumed, remove it from not_consumed
291 if elt_name in not_consumed: 354 if elt_name in not_consumed:
292 del not_consumed[elt_name] 355 del not_consumed[elt_name]
293 continue 356 continue
294 if elt_name not in node.locals: 357 if elt_name not in node.locals:
295 if not node.package: 358 if not node.package:
296 self.add_message('undefined-all-variable', 359 self.add_message('undefined-all-variable',
297 args=elt_name, 360 args=elt_name,
298 node=elt) 361 node=elt)
299 else: 362 else:
300 basename = os.path.splitext(node.file)[0] 363 basename = os.path.splitext(node.file)[0]
301 if os.path.basename(basename) == '__init__': 364 if os.path.basename(basename) == '__init__':
302 name = node.name + "." + elt_name 365 name = node.name + "." + elt_name
303 try: 366 try:
304 file_from_modpath(name.split(".")) 367 modutils.file_from_modpath(name.split("."))
305 except ImportError: 368 except ImportError:
306 self.add_message('undefined-all-variable', 369 self.add_message('undefined-all-variable',
307 args=elt_name, 370 args=elt_name,
308 node=elt) 371 node=elt)
309 except SyntaxError: 372 except SyntaxError:
310 # don't yield an syntax-error warning, 373 # don't yield an syntax-error warning,
311 # because it will be later yielded 374 # because it will be later yielded
312 # when the file will be checked 375 # when the file will be checked
313 pass 376 pass
314 # don't check unused imports in __init__ files 377 # don't check unused imports in __init__ files
315 if not self.config.init_import and node.package: 378 if not self.config.init_import and node.package:
316 return 379 return
317 for name, stmts in not_consumed.iteritems(): 380
318 if any(isinstance(stmt, astroid.AssName) 381 self._check_imports(not_consumed)
319 and isinstance(stmt.ass_type(), astroid.AugAssign) 382
320 for stmt in stmts): 383 def _check_imports(self, not_consumed):
321 continue 384 local_names = _fix_dot_imports(not_consumed)
322 stmt = stmts[0] 385 checked = set()
323 if isinstance(stmt, astroid.Import): 386 for name, stmt in local_names:
324 self.add_message('unused-import', args=name, node=stmt) 387 for imports in stmt.names:
325 elif isinstance(stmt, astroid.From) and stmt.modname != '__future__' : 388 real_name = imported_name = imports[0]
326 if stmt.names[0][0] == '*': 389 if imported_name == "*":
327 self.add_message('unused-wildcard-import', args=name, node=s tmt) 390 real_name = name
328 else: 391 as_name = imports[1]
329 self.add_message('unused-import', args=name, node=stmt) 392 if real_name in checked:
393 continue
394 if name not in (real_name, as_name):
395 continue
396 checked.add(real_name)
397
398 if (isinstance(stmt, astroid.Import) or
399 (isinstance(stmt, astroid.From) and
400 not stmt.modname)):
401 if (isinstance(stmt, astroid.From) and
402 SPECIAL_OBJ.search(imported_name)):
403 # Filter special objects (__doc__, __all__) etc.,
404 # because they can be imported for exporting.
405 continue
406 if as_name is None:
407 msg = "import %s" % imported_name
408 else:
409 msg = "%s imported as %s" % (imported_name, as_name)
410 self.add_message('unused-import', args=msg, node=stmt)
411 elif isinstance(stmt, astroid.From) and stmt.modname != '__futur e__':
412 if SPECIAL_OBJ.search(imported_name):
413 # Filter special objects (__doc__, __all__) etc.,
414 # because they can be imported for exporting.
415 continue
416 if imported_name == '*':
417 self.add_message('unused-wildcard-import',
418 args=name, node=stmt)
419 else:
420 if as_name is None:
421 msg = "%s imported from %s" % (imported_name, stmt.m odname)
422 else:
423 fields = (imported_name, stmt.modname, as_name)
424 msg = "%s imported from %s as %s" % fields
425 self.add_message('unused-import', args=msg, node=stmt)
330 del self._to_consume 426 del self._to_consume
331 427
332 def visit_class(self, node): 428 def visit_class(self, node):
333 """visit class: update consumption analysis variable 429 """visit class: update consumption analysis variable
334 """ 430 """
335 self._to_consume.append((copy(node.locals), {}, 'class')) 431 self._to_consume.append((copy(node.locals), {}, 'class'))
336 432
337 def leave_class(self, _): 433 def leave_class(self, _):
338 """leave class: update consumption analysis variable 434 """leave class: update consumption analysis variable
339 """ 435 """
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 self.linter.is_message_enabled('unused-argument')): 507 self.linter.is_message_enabled('unused-argument')):
412 return 508 return
413 # don't check arguments of function which are only raising an exception 509 # don't check arguments of function which are only raising an exception
414 if is_error(node): 510 if is_error(node):
415 return 511 return
416 # don't check arguments of abstract methods or within an interface 512 # don't check arguments of abstract methods or within an interface
417 is_method = node.is_method() 513 is_method = node.is_method()
418 klass = node.parent.frame() 514 klass = node.parent.frame()
419 if is_method and (klass.type == 'interface' or node.is_abstract()): 515 if is_method and (klass.type == 'interface' or node.is_abstract()):
420 return 516 return
517 if is_method and isinstance(klass, astroid.Class):
518 confidence = INFERENCE if has_known_bases(klass) else INFERENCE_FAIL URE
519 else:
520 confidence = HIGH
421 authorized_rgx = self.config.dummy_variables_rgx 521 authorized_rgx = self.config.dummy_variables_rgx
422 called_overridden = False 522 called_overridden = False
423 argnames = node.argnames() 523 argnames = node.argnames()
424 global_names = set() 524 global_names = set()
425 nonlocal_names = set() 525 nonlocal_names = set()
426 for global_stmt in node.nodes_of_class(astroid.Global): 526 for global_stmt in node.nodes_of_class(astroid.Global):
427 global_names.update(set(global_stmt.names)) 527 global_names.update(set(global_stmt.names))
428 for nonlocal_stmt in node.nodes_of_class(astroid.Nonlocal): 528 for nonlocal_stmt in node.nodes_of_class(astroid.Nonlocal):
429 nonlocal_names.update(set(nonlocal_stmt.names)) 529 nonlocal_names.update(set(nonlocal_stmt.names))
430 530
431 for name, stmts in not_consumed.iteritems(): 531 for name, stmts in six.iteritems(not_consumed):
432 # ignore some special names specified by user configuration 532 # ignore some special names specified by user configuration
433 if authorized_rgx.match(name): 533 if authorized_rgx.match(name):
434 continue 534 continue
435 # ignore names imported by the global statement 535 # ignore names imported by the global statement
436 # FIXME: should only ignore them if it's assigned latter 536 # FIXME: should only ignore them if it's assigned latter
437 stmt = stmts[0] 537 stmt = stmts[0]
438 if isinstance(stmt, astroid.Global): 538 if isinstance(stmt, astroid.Global):
439 continue 539 continue
440 if isinstance(stmt, (astroid.Import, astroid.From)): 540 if isinstance(stmt, (astroid.Import, astroid.From)):
441 # Detect imports, assigned to global statements. 541 # Detect imports, assigned to global statements.
(...skipping 19 matching lines...) Expand all
461 if node.type != 'staticmethod' and name == argnames[0]: 561 if node.type != 'staticmethod' and name == argnames[0]:
462 continue 562 continue
463 # don't warn for argument of an overridden method 563 # don't warn for argument of an overridden method
464 if not called_overridden: 564 if not called_overridden:
465 overridden = overridden_method(klass, node.name) 565 overridden = overridden_method(klass, node.name)
466 called_overridden = True 566 called_overridden = True
467 if overridden is not None and name in overridden.argnames(): 567 if overridden is not None and name in overridden.argnames():
468 continue 568 continue
469 if node.name in PYMETHODS and node.name not in ('__init__', '__new__'): 569 if node.name in PYMETHODS and node.name not in ('__init__', '__new__'):
470 continue 570 continue
471 # don't check callback arguments XXX should be configurable 571 # don't check callback arguments
472 if node.name.startswith('cb_') or node.name.endswith('_cb'): 572 if any(node.name.startswith(cb) or node.name.endswith(cb)
573 for cb in self.config.callbacks):
473 continue 574 continue
474 self.add_message('unused-argument', args=name, node=stmt) 575 self.add_message('unused-argument', args=name, node=stmt,
576 confidence=confidence)
475 else: 577 else:
476 if stmt.parent and isinstance(stmt.parent, astroid.Assign): 578 if stmt.parent and isinstance(stmt.parent, astroid.Assign):
477 if name in nonlocal_names: 579 if name in nonlocal_names:
478 continue 580 continue
479 self.add_message('unused-variable', args=name, node=stmt) 581 self.add_message('unused-variable', args=name, node=stmt)
480 582
481 @check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement', 583 @check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement',
482 'global-at-module-level', 'redefined-builtin') 584 'global-at-module-level', 'redefined-builtin')
483 def visit_global(self, node): 585 def visit_global(self, node):
484 """check names imported exists in the global scope""" 586 """check names imported exists in the global scope"""
(...skipping 11 matching lines...) Expand all
496 assign_nodes = [] 598 assign_nodes = []
497 for anode in assign_nodes: 599 for anode in assign_nodes:
498 if anode.parent is None: 600 if anode.parent is None:
499 # node returned for builtin attribute such as __file__, 601 # node returned for builtin attribute such as __file__,
500 # __doc__, etc... 602 # __doc__, etc...
501 continue 603 continue
502 if anode.frame() is frame: 604 if anode.frame() is frame:
503 # same scope level assignment 605 # same scope level assignment
504 break 606 break
505 else: 607 else:
506 # global but no assignment 608 if not _find_frame_imports(name, frame):
507 # Detect imports in the current frame, with the required
508 # name. Such imports can be considered assignments.
509 imports = frame.nodes_of_class((astroid.Import, astroid.From))
510 for import_node in imports:
511 found = False
512 for import_name, import_alias in import_node.names:
513 # If the import uses an alias, check only that.
514 # Otherwise, check only the import name.
515 if import_alias:
516 if import_alias == name:
517 found = True
518 break
519 elif import_name and import_name == name:
520 found = True
521 break
522 if found:
523 break
524 else:
525 self.add_message('global-variable-not-assigned', 609 self.add_message('global-variable-not-assigned',
526 args=name, node=node) 610 args=name, node=node)
527 default_message = False 611 default_message = False
528 if not assign_nodes: 612 if not assign_nodes:
529 continue 613 continue
530 for anode in assign_nodes: 614 for anode in assign_nodes:
531 if anode.parent is None: 615 if anode.parent is None:
532 self.add_message('redefined-builtin', args=name, node=node) 616 self.add_message('redefined-builtin', args=name, node=node)
533 break 617 break
534 if anode.frame() is module: 618 if anode.frame() is module:
535 # module level assignment 619 # module level assignment
536 break 620 break
537 else: 621 else:
538 # global undefined at the module scope 622 # global undefined at the module scope
539 self.add_message('global-variable-undefined', args=name, node=no de) 623 self.add_message('global-variable-undefined', args=name, node=no de)
540 default_message = False 624 default_message = False
541 if default_message: 625 if default_message:
542 self.add_message('global-statement', node=node) 626 self.add_message('global-statement', node=node)
543 627
544 def _check_late_binding_closure(self, node, assignment_node, scope_type): 628 def _check_late_binding_closure(self, node, assignment_node):
545 def _is_direct_lambda_call(): 629 def _is_direct_lambda_call():
546 return (isinstance(node_scope.parent, astroid.CallFunc) 630 return (isinstance(node_scope.parent, astroid.CallFunc)
547 and node_scope.parent.func is node_scope) 631 and node_scope.parent.func is node_scope)
548 632
549 node_scope = node.scope() 633 node_scope = node.scope()
550 if not isinstance(node_scope, (astroid.Lambda, astroid.Function)): 634 if not isinstance(node_scope, (astroid.Lambda, astroid.Function)):
551 return 635 return
552 if isinstance(node.parent, astroid.Arguments): 636 if isinstance(node.parent, astroid.Arguments):
553 return 637 return
554 638
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 to_consume, consumed, scope_type = self._to_consume[i] 728 to_consume, consumed, scope_type = self._to_consume[i]
645 # if the current scope is a class scope but it's not the inner 729 # if the current scope is a class scope but it's not the inner
646 # scope, ignore it. This prevents to access this scope instead of 730 # scope, ignore it. This prevents to access this scope instead of
647 # the globals one in function members when there are some common 731 # the globals one in function members when there are some common
648 # names. The only exception is when the starting scope is a 732 # names. The only exception is when the starting scope is a
649 # comprehension and its direct outer scope is a class 733 # comprehension and its direct outer scope is a class
650 if scope_type == 'class' and i != start_index and not ( 734 if scope_type == 'class' and i != start_index and not (
651 base_scope_type == 'comprehension' and i == start_index-1): 735 base_scope_type == 'comprehension' and i == start_index-1):
652 # Detect if we are in a local class scope, as an assignment. 736 # Detect if we are in a local class scope, as an assignment.
653 # For example, the following is fair game. 737 # For example, the following is fair game.
738 #
654 # class A: 739 # class A:
655 # b = 1 740 # b = 1
656 # c = lambda b=b: b * b 741 # c = lambda b=b: b * b
657 class_assignment = (isinstance(frame, astroid.Class) and 742 #
658 name in frame.locals) 743 # class B:
659 if not class_assignment: 744 # tp = 1
745 # def func(self, arg: tp):
746 # ...
747
748 in_annotation = (
749 PY3K and isinstance(frame, astroid.Function)
750 and node.statement() is frame and
751 (node in frame.args.annotations
752 or node is frame.args.varargannotation
753 or node is frame.args.kwargannotation))
754 if in_annotation:
755 frame_locals = frame.parent.scope().locals
756 else:
757 frame_locals = frame.locals
758 if not ((isinstance(frame, astroid.Class) or in_annotation)
759 and name in frame_locals):
660 continue 760 continue
661 # the name has already been consumed, only check it's not a loop 761 # the name has already been consumed, only check it's not a loop
662 # variable used outside the loop 762 # variable used outside the loop
663 if name in consumed: 763 if name in consumed:
664 defnode = assign_parent(consumed[name][0]) 764 defnode = assign_parent(consumed[name][0])
665 self._check_late_binding_closure(node, defnode, scope_type) 765 self._check_late_binding_closure(node, defnode)
666 self._loopvar_name(node, name) 766 self._loopvar_name(node, name)
667 break 767 break
668 # mark the name as consumed if it's defined in this scope 768 # mark the name as consumed if it's defined in this scope
669 # (i.e. no KeyError is raised by "to_consume[name]") 769 # (i.e. no KeyError is raised by "to_consume[name]")
670 try: 770 try:
671 consumed[name] = to_consume[name] 771 consumed[name] = to_consume[name]
672 except KeyError: 772 except KeyError:
673 continue 773 continue
674 # checks for use before assignment 774 # checks for use before assignment
675 defnode = assign_parent(to_consume[name][0]) 775 defnode = assign_parent(to_consume[name][0])
676 if defnode is not None: 776 if defnode is not None:
677 self._check_late_binding_closure(node, defnode, scope_type) 777 self._check_late_binding_closure(node, defnode)
678 defstmt = defnode.statement() 778 defstmt = defnode.statement()
679 defframe = defstmt.frame() 779 defframe = defstmt.frame()
680 maybee0601 = True 780 maybee0601 = True
681 if not frame is defframe: 781 if not frame is defframe:
682 maybee0601 = _detect_global_scope(node, frame, defframe) 782 maybee0601 = _detect_global_scope(node, frame, defframe)
683 elif defframe.parent is None: 783 elif defframe.parent is None:
684 # we are at the module level, check the name is not 784 # we are at the module level, check the name is not
685 # defined in builtins 785 # defined in builtins
686 if name in defframe.scope_attrs or builtin_lookup(name)[1]: 786 if name in defframe.scope_attrs or builtin_lookup(name)[1]:
687 maybee0601 = False 787 maybee0601 = False
688 else: 788 else:
689 # we are in a local scope, check the name is not 789 # we are in a local scope, check the name is not
690 # defined in global or builtin scope 790 # defined in global or builtin scope
691 if defframe.root().lookup(name)[1]: 791 if defframe.root().lookup(name)[1]:
692 maybee0601 = False 792 maybee0601 = False
693 else: 793 else:
694 # check if we have a nonlocal 794 # check if we have a nonlocal
695 if name in defframe.locals: 795 if name in defframe.locals:
696 maybee0601 = not any(isinstance(child, astroid.Nonlo cal) 796 maybee0601 = not any(isinstance(child, astroid.Nonlo cal)
697 and name in child.names 797 and name in child.names
698 for child in defframe.get_child ren()) 798 for child in defframe.get_child ren())
799
800 # Handle a couple of class scoping issues.
801 annotation_return = False
802 # The class reuses itself in the class scope.
803 recursive_klass = (frame is defframe and
804 defframe.parent_of(node) and
805 isinstance(defframe, astroid.Class) and
806 node.name == defframe.name)
699 if (self._to_consume[-1][-1] == 'lambda' and 807 if (self._to_consume[-1][-1] == 'lambda' and
700 isinstance(frame, astroid.Class) 808 isinstance(frame, astroid.Class)
701 and name in frame.locals): 809 and name in frame.locals):
702 maybee0601 = True 810 maybee0601 = True
811 elif (isinstance(defframe, astroid.Class) and
812 isinstance(frame, astroid.Function)):
813 # Special rule for function return annotations,
814 # which uses the same name as the class where
815 # the function lives.
816 if (PY3K and node is frame.returns and
817 defframe.parent_of(frame.returns)):
818 maybee0601 = annotation_return = True
819
820 if (maybee0601 and defframe.name in defframe.locals and
821 defframe.locals[name][0].lineno < frame.lineno):
822 # Detect class assignments with the same
823 # name as the class. In this case, no warning
824 # should be raised.
825 maybee0601 = False
826 elif recursive_klass:
827 maybee0601 = True
703 else: 828 else:
704 maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.froml ineno 829 maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.froml ineno
705 830
706 if (maybee0601 831 if (maybee0601
707 and not is_defined_before(node) 832 and not is_defined_before(node)
708 and not are_exclusive(stmt, defstmt, ('NameError', 833 and not are_exclusive(stmt, defstmt, ('NameError',
709 'Exception', 834 'Exception',
710 'BaseException'))) : 835 'BaseException'))) :
711 if defstmt is stmt and isinstance(node, (astroid.DelName, 836 if recursive_klass or (defstmt is stmt and
712 astroid.AssName)): 837 isinstance(node, (astroid.DelName,
838 astroid.AssName))):
839 self.add_message('undefined-variable', args=name, node=n ode)
840 elif annotation_return:
713 self.add_message('undefined-variable', args=name, node=n ode) 841 self.add_message('undefined-variable', args=name, node=n ode)
714 elif self._to_consume[-1][-1] != 'lambda': 842 elif self._to_consume[-1][-1] != 'lambda':
715 # E0601 may *not* occurs in lambda scope. 843 # E0601 may *not* occurs in lambda scope.
716 self.add_message('used-before-assignment', args=name, no de=node) 844 self.add_message('used-before-assignment', args=name, no de=node)
717 elif self._to_consume[-1][-1] == 'lambda': 845 elif self._to_consume[-1][-1] == 'lambda':
718 # E0601 can occur in class-level scope in lambdas, as in 846 # E0601 can occur in class-level scope in lambdas, as in
719 # the following example: 847 # the following example:
720 # class A: 848 # class A:
721 # x = lambda attr: f + attr 849 # x = lambda attr: f + attr
722 # f = 42 850 # f = 42
(...skipping 23 matching lines...) Expand all
746 if not (name in astroid.Module.scope_attrs or is_builtin(name) 874 if not (name in astroid.Module.scope_attrs or is_builtin(name)
747 or name in self.config.additional_builtins): 875 or name in self.config.additional_builtins):
748 self.add_message('undefined-variable', args=name, node=node) 876 self.add_message('undefined-variable', args=name, node=node)
749 877
750 @check_messages('no-name-in-module') 878 @check_messages('no-name-in-module')
751 def visit_import(self, node): 879 def visit_import(self, node):
752 """check modules attribute accesses""" 880 """check modules attribute accesses"""
753 for name, _ in node.names: 881 for name, _ in node.names:
754 parts = name.split('.') 882 parts = name.split('.')
755 try: 883 try:
756 module = node.infer_name_module(parts[0]).next() 884 module = next(node.infer_name_module(parts[0]))
757 except astroid.ResolveError: 885 except astroid.ResolveError:
758 continue 886 continue
759 self._check_module_attrs(node, module, parts[1:]) 887 self._check_module_attrs(node, module, parts[1:])
760 888
761 @check_messages('no-name-in-module') 889 @check_messages('no-name-in-module')
762 def visit_from(self, node): 890 def visit_from(self, node):
763 """check modules attribute accesses""" 891 """check modules attribute accesses"""
764 name_parts = node.modname.split('.') 892 name_parts = node.modname.split('.')
765 level = getattr(node, 'level', None) 893 level = getattr(node, 'level', None)
766 try: 894 try:
767 module = node.root().import_module(name_parts[0], level=level) 895 module = node.root().import_module(name_parts[0], level=level)
768 except AstroidBuildingException: 896 except Exception: # pylint: disable=broad-except
769 return
770 except Exception, exc:
771 print 'Unhandled exception in VariablesChecker:', exc
772 return 897 return
773 module = self._check_module_attrs(node, module, name_parts[1:]) 898 module = self._check_module_attrs(node, module, name_parts[1:])
774 if not module: 899 if not module:
775 return 900 return
776 for name, _ in node.names: 901 for name, _ in node.names:
777 if name == '*': 902 if name == '*':
778 continue 903 continue
779 self._check_module_attrs(node, module, name.split('.')) 904 self._check_module_attrs(node, module, name.split('.'))
780 905
781 @check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence') 906 @check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence')
(...skipping 10 matching lines...) Expand all
792 self._check_unpacking(infered, node, targets) 917 self._check_unpacking(infered, node, targets)
793 except astroid.InferenceError: 918 except astroid.InferenceError:
794 return 919 return
795 920
796 def _check_unpacking(self, infered, node, targets): 921 def _check_unpacking(self, infered, node, targets):
797 """ Check for unbalanced tuple unpacking 922 """ Check for unbalanced tuple unpacking
798 and unpacking non sequences. 923 and unpacking non sequences.
799 """ 924 """
800 if infered is astroid.YES: 925 if infered is astroid.YES:
801 return 926 return
927 if (isinstance(infered.parent, astroid.Arguments) and
928 isinstance(node.value, astroid.Name) and
929 node.value.name == infered.parent.vararg):
930 # Variable-length argument, we can't determine the length.
931 return
802 if isinstance(infered, (astroid.Tuple, astroid.List)): 932 if isinstance(infered, (astroid.Tuple, astroid.List)):
803 # attempt to check unpacking is properly balanced 933 # attempt to check unpacking is properly balanced
804 values = infered.itered() 934 values = infered.itered()
805 if len(targets) != len(values): 935 if len(targets) != len(values):
806 # Check if we have starred nodes. 936 # Check if we have starred nodes.
807 if any(isinstance(target, astroid.Starred) 937 if any(isinstance(target, astroid.Starred)
808 for target in targets): 938 for target in targets):
809 return 939 return
810 self.add_message('unbalanced-tuple-unpacking', node=node, 940 self.add_message('unbalanced-tuple-unpacking', node=node,
811 args=(_get_unpacking_extra_info(node, infered), 941 args=(_get_unpacking_extra_info(node, infered),
(...skipping 22 matching lines...) Expand all
834 """ 964 """
835 assert isinstance(module, astroid.Module), module 965 assert isinstance(module, astroid.Module), module
836 ignored_modules = get_global_option(self, 'ignored-modules', 966 ignored_modules = get_global_option(self, 'ignored-modules',
837 default=[]) 967 default=[])
838 while module_names: 968 while module_names:
839 name = module_names.pop(0) 969 name = module_names.pop(0)
840 if name == '__dict__': 970 if name == '__dict__':
841 module = None 971 module = None
842 break 972 break
843 try: 973 try:
844 module = module.getattr(name)[0].infer().next() 974 module = next(module.getattr(name)[0].infer())
845 if module is astroid.YES: 975 if module is astroid.YES:
846 return None 976 return None
847 except astroid.NotFoundError: 977 except astroid.NotFoundError:
848 if module.name in ignored_modules: 978 if module.name in ignored_modules:
849 return None 979 return None
850 self.add_message('no-name-in-module', 980 self.add_message('no-name-in-module',
851 args=(name, module.name), node=node) 981 args=(name, module.name), node=node)
852 return None 982 return None
853 except astroid.InferenceError: 983 except astroid.InferenceError:
854 return None 984 return None
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 module_locals.pop(name, None) 1060 module_locals.pop(name, None)
931 super(VariablesChecker3k, self).leave_module(node) 1061 super(VariablesChecker3k, self).leave_module(node)
932 1062
933 if sys.version_info >= (3, 0): 1063 if sys.version_info >= (3, 0):
934 VariablesChecker = VariablesChecker3k 1064 VariablesChecker = VariablesChecker3k
935 1065
936 1066
937 def register(linter): 1067 def register(linter):
938 """required method to auto register this checker""" 1068 """required method to auto register this checker"""
939 linter.register_checker(VariablesChecker(linter)) 1069 linter.register_checker(VariablesChecker(linter))
OLDNEW
« no previous file with comments | « third_party/pylint/checkers/utils.py ('k') | third_party/pylint/config.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698