20 import ast |
20 import ast |
21 iter_child_nodes = ast.iter_child_nodes |
21 iter_child_nodes = ast.iter_child_nodes |
22 except (ImportError, AttributeError): |
22 except (ImportError, AttributeError): |
23 def iter_child_nodes(node, astcls=_ast.AST): |
23 def iter_child_nodes(node, astcls=_ast.AST): |
24 """ |
24 """ |
25 Yield all direct child nodes of *node*, that is, all fields that are nodes |
25 Yield all direct child nodes of *node*, that is, all fields that are |
26 and all items of fields that are lists of nodes. |
26 nodes and all items of fields that are lists of nodes. |
27 """ |
27 """ |
28 for name in node._fields: |
28 for name in node._fields: |
29 field = getattr(node, name, None) |
29 field = getattr(node, name, None) |
30 if isinstance(field, astcls): |
30 if isinstance(field, astcls): |
31 yield field |
31 yield field |
289 node.parent = parent |
289 node.parent = parent |
290 if self.traceTree: |
290 if self.traceTree: |
291 print ' ' * self.nodeDepth + node.__class__.__name__ |
291 print ' ' * self.nodeDepth + node.__class__.__name__ |
292 self.nodeDepth += 1 |
292 self.nodeDepth += 1 |
293 if self.futuresAllowed and not \ |
293 if self.futuresAllowed and not \ |
294 (isinstance(node, _ast.ImportFrom) or self.isDocstring(node)): |
294 (isinstance(node, _ast.ImportFrom) or |
|
295 self.isDocstring(node)): |
295 self.futuresAllowed = False |
296 self.futuresAllowed = False |
296 nodeType = node.__class__.__name__.upper() |
297 nodeType = node.__class__.__name__.upper() |
297 try: |
298 try: |
298 handler = getattr(self, nodeType) |
299 handler = getattr(self, nodeType) |
299 handler(node) |
300 handler(node) |
335 |
336 |
336 def addBinding(self, lineno, value, reportRedef=True): |
337 def addBinding(self, lineno, value, reportRedef=True): |
337 ''' |
338 ''' |
338 Called when a binding is altered. |
339 Called when a binding is altered. |
339 |
340 |
340 @param lineno line of the statement responsible for the change (integer) |
341 @param lineno line of the statement responsible for the change |
|
342 (integer) |
341 @param value the optional new value, a Binding instance, associated |
343 @param value the optional new value, a Binding instance, associated |
342 with the binding; if None, the binding is deleted if it exists |
344 with the binding; if None, the binding is deleted if it exists |
343 @param reportRedef flag indicating if rebinding while unused will be |
345 @param reportRedef flag indicating if rebinding while unused will be |
344 reported (boolean) |
346 reported (boolean) |
345 ''' |
347 ''' |
346 if (isinstance(self.scope.get(value.name), FunctionDefinition) |
348 if (isinstance(self.scope.get(value.name), FunctionDefinition) |
347 and isinstance(value, FunctionDefinition)): |
349 and isinstance(value, FunctionDefinition)): |
348 self.report(messages.RedefinedFunction, |
350 self.report(messages.RedefinedFunction, |
349 lineno, value.name, self.scope[value.name].source.lineno) |
351 lineno, value.name, |
|
352 self.scope[value.name].source.lineno) |
350 |
353 |
351 if not isinstance(self.scope, ClassScope): |
354 if not isinstance(self.scope, ClassScope): |
352 for scope in self.scopeStack[::-1]: |
355 for scope in self.scopeStack[::-1]: |
353 existing = scope.get(value.name) |
356 existing = scope.get(value.name) |
354 if (isinstance(existing, Importation) |
357 if (isinstance(existing, Importation) |
356 and (not isinstance(value, Importation) or |
359 and (not isinstance(value, Importation) or |
357 value.fullName == existing.fullName) |
360 value.fullName == existing.fullName) |
358 and reportRedef): |
361 and reportRedef): |
359 |
362 |
360 self.report(messages.RedefinedWhileUnused, |
363 self.report(messages.RedefinedWhileUnused, |
361 lineno, value.name, scope[value.name].source.lineno) |
364 lineno, value.name, |
|
365 scope[value.name].source.lineno) |
362 |
366 |
363 if isinstance(value, UnBinding): |
367 if isinstance(value, UnBinding): |
364 try: |
368 try: |
365 del self.scope[value.name] |
369 del self.scope[value.name] |
366 except KeyError: |
370 except KeyError: |
454 if (os.path.basename(self.filename) == '__init__.py' and |
458 if (os.path.basename(self.filename) == '__init__.py' and |
455 node.id == '__path__'): |
459 node.id == '__path__'): |
456 # the special name __path__ is valid only in packages |
460 # the special name __path__ is valid only in packages |
457 pass |
461 pass |
458 else: |
462 else: |
459 self.report(messages.UndefinedName, node.lineno, node.id) |
463 self.report(messages.UndefinedName, |
|
464 node.lineno, node.id) |
460 elif isinstance(node.ctx, (_ast.Store, _ast.AugStore)): |
465 elif isinstance(node.ctx, (_ast.Store, _ast.AugStore)): |
461 # if the name hasn't already been defined in the current scope |
466 # if the name hasn't already been defined in the current scope |
462 if isinstance(self.scope, FunctionScope) and node.id not in self.scope: |
467 if isinstance(self.scope, FunctionScope) and \ |
|
468 node.id not in self.scope: |
463 # for each function or module scope above us |
469 # for each function or module scope above us |
464 for scope in self.scopeStack[:-1]: |
470 for scope in self.scopeStack[:-1]: |
465 if not isinstance(scope, (FunctionScope, ModuleScope)): |
471 if not isinstance(scope, (FunctionScope, ModuleScope)): |
466 continue |
472 continue |
467 # if the name was defined in that scope, and the name has |
473 # if the name was defined in that scope, and the name has |
477 node.id, |
483 node.id, |
478 scope[node.id].source.lineno) |
484 scope[node.id].source.lineno) |
479 break |
485 break |
480 |
486 |
481 if isinstance(node.parent, |
487 if isinstance(node.parent, |
482 (_ast.For, _ast.comprehension, _ast.Tuple, _ast.List)): |
488 (_ast.For, _ast.comprehension, _ast.Tuple, |
|
489 _ast.List)): |
483 binding = Binding(node.id, node) |
490 binding = Binding(node.id, node) |
484 elif (node.id == '__all__' and |
491 elif (node.id == '__all__' and |
485 isinstance(self.scope, ModuleScope)): |
492 isinstance(self.scope, ModuleScope)): |
486 binding = ExportBinding(node.id, node.parent.value) |
493 binding = ExportBinding(node.id, node.parent.value) |
487 else: |
494 else: |
494 node.id in self.scope.globals: |
501 node.id in self.scope.globals: |
495 del self.scope.globals[node.id] |
502 del self.scope.globals[node.id] |
496 else: |
503 else: |
497 self.addBinding(node.lineno, UnBinding(node.id, node)) |
504 self.addBinding(node.lineno, UnBinding(node.id, node)) |
498 else: |
505 else: |
499 # must be a Param context -- this only happens for names in function |
506 # must be a Param context -- this only happens for names in |
500 # arguments, but these aren't dispatched through here |
507 # function arguments, but these aren't dispatched through here |
501 raise RuntimeError( |
508 raise RuntimeError( |
502 "Got impossible expression context: %r" % (node.ctx,)) |
509 "Got impossible expression context: %r" % (node.ctx,)) |
503 |
510 |
504 def FUNCTIONDEF(self, node): |
511 def FUNCTIONDEF(self, node): |
505 if hasattr(node, 'decorators'): |
512 if hasattr(node, 'decorators'): |
522 for arg in arglist: |
529 for arg in arglist: |
523 if isinstance(arg, _ast.Tuple): |
530 if isinstance(arg, _ast.Tuple): |
524 addArgs(arg.elts) |
531 addArgs(arg.elts) |
525 else: |
532 else: |
526 if arg.id in args: |
533 if arg.id in args: |
527 self.report(messages.DuplicateArgument, node.lineno, arg.id) |
534 self.report(messages.DuplicateArgument, |
|
535 node.lineno, arg.id) |
528 args.append(arg.id) |
536 args.append(arg.id) |
529 |
537 |
530 self.pushFunctionScope() |
538 self.pushFunctionScope() |
531 addArgs(node.args.args) |
539 addArgs(node.args.args) |
532 # vararg/kwarg identifiers are not Name nodes |
540 # vararg/kwarg identifiers are not Name nodes |
533 if node.args.vararg: |
541 if node.args.vararg: |
534 args.append(node.args.vararg) |
542 args.append(node.args.vararg) |
535 if node.args.kwarg: |
543 if node.args.kwarg: |
536 args.append(node.args.kwarg) |
544 args.append(node.args.kwarg) |
537 for name in args: |
545 for name in args: |
538 self.addBinding(node.lineno, Argument(name, node), reportRedef=False) |
546 self.addBinding(node.lineno, Argument(name, node), |
|
547 reportRedef=False) |
539 if isinstance(node.body, list): |
548 if isinstance(node.body, list): |
540 # case for FunctionDefs |
549 # case for FunctionDefs |
541 for stmt in node.body: |
550 for stmt in node.body: |
542 self.handleNode(stmt, node) |
551 self.handleNode(stmt, node) |
543 else: |
552 else: |
579 self.handleNode(node.value, node) |
588 self.handleNode(node.value, node) |
580 for target in node.targets: |
589 for target in node.targets: |
581 self.handleNode(target, node) |
590 self.handleNode(target, node) |
582 |
591 |
583 def AUGASSIGN(self, node): |
592 def AUGASSIGN(self, node): |
584 # AugAssign is awkward: must set the context explicitly and visit twice, |
593 # AugAssign is awkward: must set the context explicitly and visit |
585 # once with AugLoad context, once with AugStore context |
594 # twice, once with AugLoad context, once with AugStore context |
586 node.target.ctx = _ast.AugLoad() |
595 node.target.ctx = _ast.AugLoad() |
587 self.handleNode(node.target, node) |
596 self.handleNode(node.target, node) |
588 self.handleNode(node.value, node) |
597 self.handleNode(node.value, node) |
589 node.target.ctx = _ast.AugStore() |
598 node.target.ctx = _ast.AugStore() |
590 self.handleNode(node.target, node) |
599 self.handleNode(node.target, node) |