UtilitiesPython2/pyflakes/checker.py

changeset 3246
4cd58a0d6c28
parent 3212
27a73942b8c8
equal deleted inserted replaced
3244:1a54f34202b8 3246:4cd58a0d6c28
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5 # Original (c) 2005-2010 Divmod, Inc.
6 #
7 # This module is based on pyflakes for Python2 and Python3, but was modified to
8 # be integrated into eric5
9
10 import doctest
11 import os
12 import sys
13 try:
14 builtin_vars = dir(__import__('builtins'))
15 PY2 = False
16 ## added for eric5
17 basestring = str
18 ## end added for eric5
19 except ImportError:
20 builtin_vars = dir(__import__('__builtin__'))
21 PY2 = True
22
23 try:
24 import ast
25 iter_child_nodes = ast.iter_child_nodes
26 except ImportError: # Python 2.5
27 import _ast as ast
28
29 if 'decorator_list' not in ast.ClassDef._fields:
30 # Patch the missing attribute 'decorator_list'
31 ast.ClassDef.decorator_list = ()
32 ast.FunctionDef.decorator_list = property(lambda s: s.decorators)
33
34 def iter_child_nodes(node):
35 """
36 Yield all direct child nodes of *node*, that is, all fields that
37 are nodes and all items of fields that are lists of nodes.
38 """
39 for name in node._fields:
40 field = getattr(node, name, None)
41 if isinstance(field, ast.AST):
42 yield field
43 elif isinstance(field, list):
44 for item in field:
45 yield item
46 # Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)
47 if hasattr(ast, 'Try'):
48 ast_TryExcept = ast.Try
49 ast_TryFinally = ()
50 else:
51 ast_TryExcept = ast.TryExcept
52 ast_TryFinally = ast.TryFinally
53
54 from . import messages
55
56 if PY2:
57 def getNodeType(node_class):
58 # workaround str.upper() which is locale-dependent
59 return str(unicode(node_class.__name__).upper()) # __IGNORE_WARNING__
60 else:
61 def getNodeType(node_class):
62 return node_class.__name__.upper()
63
64
65 class Binding(object):
66 """
67 Represents the binding of a value to a name.
68
69 The checker uses this to keep track of which names have been bound and
70 which names have not. See Assignment for a special type of binding that
71 is checked with stricter rules.
72 """
73 def __init__(self, name, source):
74 self.name = name
75 self.source = source
76 self.used = False
77
78 def __str__(self):
79 return self.name
80
81 def __repr__(self):
82 return '<%s object %r from line %r at 0x%x>' % (
83 self.__class__.__name__,
84 self.name,
85 self.source.lineno,
86 id(self))
87
88
89 class Importation(Binding):
90 """
91 A binding created by an import statement.
92 """
93 def __init__(self, name, source):
94 self.fullName = name
95 name = name.split('.')[0]
96 super(Importation, self).__init__(name, source)
97
98
99 class Argument(Binding):
100 """
101 Represents binding a name as an argument.
102 """
103 pass
104
105
106 class Definition(Binding):
107 """
108 A binding that defines a function or a class.
109 """
110 pass
111
112
113 class Assignment(Binding):
114 """
115 Represents binding a name with an explicit assignment.
116
117 The checker will raise warnings for any Assignment that isn't used. Also,
118 the checker does not consider assignments in tuple/list unpacking to be
119 Assignments, rather it treats them as simple Bindings.
120 """
121 pass
122
123
124 class FunctionDefinition(Definition):
125 """
126 Represents a function definition.
127 """
128 pass
129
130
131 class ClassDefinition(Definition):
132 """
133 Represents a class definition.
134 """
135 pass
136
137
138 class ExportBinding(Binding):
139 """
140 A binding created by an __all__ assignment. If the names in the list
141 can be determined statically, they will be treated as names for export and
142 additional checking applied to them.
143
144 The only __all__ assignment that can be recognized is one which takes
145 the value of a literal list containing literal strings. For example::
146
147 __all__ = ["foo", "bar"]
148
149 Names which are imported and not otherwise used but appear in the value of
150 __all__ will not have an unused import warning reported for them.
151 """
152 def names(self):
153 """
154 Return a list of the names referenced by this binding.
155 """
156 names = []
157 if isinstance(self.source, ast.List):
158 for node in self.source.elts:
159 if isinstance(node, ast.Str):
160 names.append(node.s)
161 return names
162
163
164 class Scope(dict):
165 """
166 Class defining the scope base class.
167 """
168 importStarred = False # set to True when import * is found
169
170 def __repr__(self):
171 scope_cls = self.__class__.__name__
172 return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self))
173
174
175 class ClassScope(Scope):
176 """
177 Class representing a name scope for a class.
178 """
179 pass
180
181
182 class FunctionScope(Scope):
183 """
184 Class representing a name scope for a function.
185 """
186 usesLocals = False
187 alwaysUsed = set(['__tracebackhide__',
188 '__traceback_info__', '__traceback_supplement__'])
189
190 def __init__(self):
191 super(FunctionScope, self).__init__()
192 # Simplify: manage the special locals as globals
193 self.globals = self.alwaysUsed.copy()
194
195 def unusedAssignments(self):
196 """
197 Return a generator for the assignments which have not been used.
198 """
199 for name, binding in self.items():
200 if (not binding.used and name not in self.globals
201 and not self.usesLocals
202 and isinstance(binding, Assignment)):
203 yield name, binding
204
205
206 class GeneratorScope(Scope):
207 """
208 Class representing a name scope for a generator function.
209 """
210 pass
211
212
213 class ModuleScope(Scope):
214 """
215 Class representing a name scope for a module.
216 """
217 pass
218
219 # Globally defined names which are not attributes of the builtins module, or
220 # are only present on some platforms.
221 _MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError']
222
223
224 def getNodeName(node):
225 """
226 Module function for getting the name of a node.
227 """
228 # Returns node.id, or node.name, or None
229 if hasattr(node, 'id'): # One of the many nodes with an id
230 return node.id
231 if hasattr(node, 'name'): # a ExceptHandler node
232 return node.name
233
234
235 class Checker(object):
236 """
237 Class to check the cleanliness and sanity of Python code.
238 """
239 nodeDepth = 0
240 offset = None
241 traceTree = False
242 withDoctest = ('PYFLAKES_NODOCTEST' not in os.environ)
243
244 builtIns = set(builtin_vars).union(_MAGIC_GLOBALS)
245 _customBuiltIns = os.environ.get('PYFLAKES_BUILTINS')
246 if _customBuiltIns:
247 builtIns.update(_customBuiltIns.split(','))
248 del _customBuiltIns
249
250 def __init__(self, tree, filename='(none)', builtins=None):
251 """
252 Constructor
253
254 @param tree parsed module tree or module source code
255 @param filename name of the module file (string)
256 @param builtins set of names to be treated as builtins (set of string)
257 """
258 self._nodeHandlers = {}
259 self._deferredFunctions = []
260 self._deferredAssignments = []
261 self.deadScopes = []
262 self.messages = []
263 self.filename = filename
264 if builtins:
265 self.builtIns = self.builtIns.union(builtins)
266 self.scopeStack = [ModuleScope()]
267 self.exceptHandlers = [()]
268 self.futuresAllowed = True
269
270 ## added for eric5
271 if isinstance(tree, basestring):
272 tree = compile(tree, filename, "exec", ast.PyCF_ONLY_AST)
273 ## end added for eric5
274
275 self.root = tree
276 self.handleChildren(tree)
277 self.runDeferred(self._deferredFunctions)
278 # Set _deferredFunctions to None so that deferFunction will fail
279 # noisily if called after we've run through the deferred functions.
280 self._deferredFunctions = None
281 self.runDeferred(self._deferredAssignments)
282 # Set _deferredAssignments to None so that deferAssignment will fail
283 # noisily if called after we've run through the deferred assignments.
284 self._deferredAssignments = None
285 del self.scopeStack[1:]
286 self.popScope()
287 self.checkDeadScopes()
288
289 def deferFunction(self, callable):
290 '''
291 Schedule a function handler to be called just before completion.
292
293 This is used for handling function bodies, which must be deferred
294 because code later in the file might modify the global scope. When
295 `callable` is called, the scope at the time this is called will be
296 restored, however it will contain any new bindings added to it.
297 '''
298 self._deferredFunctions.append((callable, self.scopeStack[:],
299 self.offset))
300
301 def deferAssignment(self, callable):
302 """
303 Schedule an assignment handler to be called just after deferred
304 function handlers.
305 """
306 self._deferredAssignments.append((callable, self.scopeStack[:],
307 self.offset))
308
309 def runDeferred(self, deferred):
310 """
311 Run the callables in deferred using their associated scope stack.
312 """
313 for handler, scope, offset in deferred:
314 self.scopeStack = scope
315 self.offset = offset
316 handler()
317
318 @property
319 def scope(self):
320 return self.scopeStack[-1]
321
322 def popScope(self):
323 self.deadScopes.append(self.scopeStack.pop())
324
325 def checkDeadScopes(self):
326 """
327 Look at scopes which have been fully examined and report names in them
328 which were imported but unused.
329 """
330 for scope in self.deadScopes:
331 export = isinstance(scope.get('__all__'), ExportBinding)
332 if export:
333 all = scope['__all__'].names()
334 if not scope.importStarred and \
335 os.path.basename(self.filename) != '__init__.py':
336 # Look for possible mistakes in the export list
337 undefined = set(all) - set(scope)
338 for name in undefined:
339 self.report(messages.UndefinedExport,
340 scope['__all__'].source, name)
341 else:
342 all = []
343
344 # Look for imported names that aren't used.
345 for importation in scope.values():
346 if isinstance(importation, Importation):
347 if not importation.used and importation.name not in all:
348 self.report(messages.UnusedImport,
349 importation.source, importation.name)
350
351 def pushScope(self, scopeClass=FunctionScope):
352 self.scopeStack.append(scopeClass())
353
354 def pushFunctionScope(self): # XXX Deprecated
355 self.pushScope(FunctionScope)
356
357 def pushClassScope(self): # XXX Deprecated
358 self.pushScope(ClassScope)
359
360 def report(self, messageClass, *args, **kwargs):
361 self.messages.append(messageClass(self.filename, *args, **kwargs))
362
363 def hasParent(self, node, kind):
364 while hasattr(node, 'parent'):
365 node = node.parent
366 if isinstance(node, kind):
367 return True
368
369 def getCommonAncestor(self, lnode, rnode, stop=None):
370 if not stop:
371 stop = self.root
372 if lnode is rnode:
373 return lnode
374 if stop in (lnode, rnode):
375 return stop
376
377 if not hasattr(lnode, 'parent') or not hasattr(rnode, 'parent'):
378 return
379 if (lnode.level > rnode.level):
380 return self.getCommonAncestor(lnode.parent, rnode, stop)
381 if (rnode.level > lnode.level):
382 return self.getCommonAncestor(lnode, rnode.parent, stop)
383 return self.getCommonAncestor(lnode.parent, rnode.parent, stop)
384
385 def descendantOf(self, node, ancestors, stop=None):
386 for a in ancestors:
387 if self.getCommonAncestor(node, a, stop) not in (stop, None):
388 return True
389 return False
390
391 def onFork(self, parent, lnode, rnode, items):
392 return (self.descendantOf(lnode, items, parent) ^
393 self.descendantOf(rnode, items, parent))
394
395 def differentForks(self, lnode, rnode):
396 """True, if lnode and rnode are located on different forks of IF/TRY"""
397 ancestor = self.getCommonAncestor(lnode, rnode)
398 if isinstance(ancestor, ast.If):
399 for fork in (ancestor.body, ancestor.orelse):
400 if self.onFork(ancestor, lnode, rnode, fork):
401 return True
402 elif isinstance(ancestor, ast_TryExcept):
403 body = ancestor.body + ancestor.orelse
404 for fork in [body] + [[hdl] for hdl in ancestor.handlers]:
405 if self.onFork(ancestor, lnode, rnode, fork):
406 return True
407 elif isinstance(ancestor, ast_TryFinally):
408 if self.onFork(ancestor, lnode, rnode, ancestor.body):
409 return True
410 return False
411
412 def addBinding(self, node, value, reportRedef=True):
413 """
414 Called when a binding is altered.
415
416 - `node` is the statement responsible for the change
417 - `value` is the optional new value, a Binding instance, associated
418 with the binding; if None, the binding is deleted if it exists.
419 - if `reportRedef` is True (default), rebinding while unused will be
420 reported.
421 """
422 redefinedWhileUnused = False
423 if not isinstance(self.scope, ClassScope):
424 for scope in self.scopeStack[::-1]:
425 existing = scope.get(value.name)
426 if (isinstance(existing, Importation)
427 and not existing.used
428 and (not isinstance(value, Importation) or
429 value.fullName == existing.fullName)
430 and reportRedef
431 and not self.differentForks(node, existing.source)):
432 redefinedWhileUnused = True
433 self.report(messages.RedefinedWhileUnused,
434 node, value.name, existing.source)
435
436 existing = self.scope.get(value.name)
437 if not redefinedWhileUnused and self.hasParent(value.source, ast.ListComp):
438 if (existing and reportRedef
439 and not self.hasParent(existing.source, (ast.For, ast.ListComp))
440 and not self.differentForks(node, existing.source)):
441 self.report(messages.RedefinedInListComp,
442 node, value.name, existing.source)
443
444 if (isinstance(existing, Definition)
445 and not existing.used
446 and not self.differentForks(node, existing.source)):
447 self.report(messages.RedefinedWhileUnused,
448 node, value.name, existing.source)
449 else:
450 self.scope[value.name] = value
451
452 def getNodeHandler(self, node_class):
453 try:
454 return self._nodeHandlers[node_class]
455 except KeyError:
456 nodeType = getNodeType(node_class)
457 self._nodeHandlers[node_class] = handler = getattr(self, nodeType)
458 return handler
459
460 def handleNodeLoad(self, node):
461 name = getNodeName(node)
462 if not name:
463 return
464 # try local scope
465 try:
466 self.scope[name].used = (self.scope, node)
467 except KeyError:
468 pass
469 else:
470 return
471
472 scopes = [scope for scope in self.scopeStack[:-1]
473 if isinstance(scope, (FunctionScope, ModuleScope))]
474 if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:
475 scopes.append(self.scopeStack[-2])
476
477 # try enclosing function scopes and global scope
478 importStarred = self.scope.importStarred
479 for scope in reversed(scopes):
480 importStarred = importStarred or scope.importStarred
481 try:
482 scope[name].used = (self.scope, node)
483 except KeyError:
484 pass
485 else:
486 return
487
488 # look in the built-ins
489 if importStarred or name in self.builtIns:
490 return
491 if name == '__path__' and os.path.basename(self.filename) == '__init__.py':
492 # the special name __path__ is valid only in packages
493 return
494
495 # protected with a NameError handler?
496 if 'NameError' not in self.exceptHandlers[-1]:
497 self.report(messages.UndefinedName, node, name)
498
499 def handleNodeStore(self, node):
500 name = getNodeName(node)
501 if not name:
502 return
503 # if the name hasn't already been defined in the current scope
504 if isinstance(self.scope, FunctionScope) and name not in self.scope:
505 # for each function or module scope above us
506 for scope in self.scopeStack[:-1]:
507 if not isinstance(scope, (FunctionScope, ModuleScope)):
508 continue
509 # if the name was defined in that scope, and the name has
510 # been accessed already in the current scope, and hasn't
511 # been declared global
512 used = name in scope and scope[name].used
513 if used and used[0] is self.scope and name not in self.scope.globals:
514 # then it's probably a mistake
515 self.report(messages.UndefinedLocal,
516 scope[name].used[1], name, scope[name].source)
517 break
518
519 parent = getattr(node, 'parent', None)
520 if isinstance(parent, (ast.For, ast.comprehension, ast.Tuple, ast.List)):
521 binding = Binding(name, node)
522 elif (parent is not None and name == '__all__' and
523 isinstance(self.scope, ModuleScope)):
524 binding = ExportBinding(name, parent.value)
525 else:
526 binding = Assignment(name, node)
527 if name in self.scope:
528 binding.used = self.scope[name].used
529 self.addBinding(node, binding)
530
531 def handleNodeDelete(self, node):
532 name = getNodeName(node)
533 if not name:
534 return
535 if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
536 self.scope.globals.remove(name)
537 else:
538 try:
539 del self.scope[name]
540 except KeyError:
541 self.report(messages.UndefinedName, node, name)
542
543 def handleChildren(self, tree):
544 for node in iter_child_nodes(tree):
545 self.handleNode(node, tree)
546
547 def isDocstring(self, node):
548 """
549 Determine if the given node is a docstring, as long as it is at the
550 correct place in the node tree.
551 """
552 return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and
553 isinstance(node.value, ast.Str))
554
555 def getDocstring(self, node):
556 if isinstance(node, ast.Expr):
557 node = node.value
558 if not isinstance(node, ast.Str):
559 return (None, None)
560 # Computed incorrectly if the docstring has backslash
561 doctest_lineno = node.lineno - node.s.count('\n') - 1
562 return (node.s, doctest_lineno)
563
564 def handleNode(self, node, parent):
565 if node is None:
566 return
567 if self.offset and getattr(node, 'lineno', None) is not None:
568 node.lineno += self.offset[0]
569 node.col_offset += self.offset[1]
570 if self.traceTree:
571 print(' ' * self.nodeDepth + node.__class__.__name__)
572 if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
573 self.isDocstring(node)):
574 self.futuresAllowed = False
575 self.nodeDepth += 1
576 node.level = self.nodeDepth
577 node.parent = parent
578 try:
579 handler = self.getNodeHandler(node.__class__)
580 handler(node)
581 finally:
582 self.nodeDepth -= 1
583 if self.traceTree:
584 print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
585
586 _getDoctestExamples = doctest.DocTestParser().get_examples
587
588 def handleDoctests(self, node):
589 try:
590 docstring, node_lineno = self.getDocstring(node.body[0])
591 if not docstring:
592 return
593 examples = self._getDoctestExamples(docstring)
594 except (ValueError, IndexError):
595 # e.g. line 6 of the docstring for <string> has inconsistent
596 # leading whitespace: ...
597 return
598 node_offset = self.offset or (0, 0)
599 self.pushScope()
600 for example in examples:
601 try:
602 tree = compile(example.source, "<doctest>", "exec", ast.PyCF_ONLY_AST)
603 except SyntaxError:
604 e = sys.exc_info()[1]
605 position = (node_lineno + example.lineno + e.lineno,
606 example.indent + 4 + e.offset)
607 self.report(messages.DoctestSyntaxError, node, position)
608 else:
609 self.offset = (node_offset[0] + node_lineno + example.lineno,
610 node_offset[1] + example.indent + 4)
611 self.handleChildren(tree)
612 self.offset = node_offset
613 self.popScope()
614
615 def ignore(self, node):
616 pass
617
618 # "stmt" type nodes
619 RETURN = DELETE = PRINT = WHILE = IF = WITH = WITHITEM = RAISE = \
620 TRYFINALLY = ASSERT = EXEC = EXPR = handleChildren
621
622 CONTINUE = BREAK = PASS = ignore
623
624 # "expr" type nodes
625 BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = YIELD = YIELDFROM = \
626 COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \
627 STARRED = handleChildren
628
629 NUM = STR = BYTES = ELLIPSIS = ignore
630
631 # "slice" type nodes
632 SLICE = EXTSLICE = INDEX = handleChildren
633
634 # expression contexts are node instances too, though being constants
635 LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore
636
637 # same for operators
638 AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
639 BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
640 EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
641
642 # additional node types
643 COMPREHENSION = KEYWORD = handleChildren
644
645 def GLOBAL(self, node):
646 """
647 Keep track of globals declarations.
648 """
649 if isinstance(self.scope, FunctionScope):
650 self.scope.globals.update(node.names)
651
652 NONLOCAL = GLOBAL
653
654 def LISTCOMP(self, node):
655 # handle generators before element
656 for gen in node.generators:
657 self.handleNode(gen, node)
658 self.handleNode(node.elt, node)
659
660 def GENERATOREXP(self, node):
661 self.pushScope(GeneratorScope)
662 # handle generators before element
663 for gen in node.generators:
664 self.handleNode(gen, node)
665 self.handleNode(node.elt, node)
666 self.popScope()
667
668 SETCOMP = GENERATOREXP
669
670 def DICTCOMP(self, node):
671 self.pushScope(GeneratorScope)
672 for gen in node.generators:
673 self.handleNode(gen, node)
674 self.handleNode(node.key, node)
675 self.handleNode(node.value, node)
676 self.popScope()
677
678 def FOR(self, node):
679 """
680 Process bindings for loop variables.
681 """
682 vars = []
683
684 def collectLoopVars(n):
685 if isinstance(n, ast.Name):
686 vars.append(n.id)
687 elif isinstance(n, ast.expr_context):
688 return
689 else:
690 for c in iter_child_nodes(n):
691 collectLoopVars(c)
692
693 collectLoopVars(node.target)
694 for varn in vars:
695 if (isinstance(self.scope.get(varn), Importation)
696 # unused ones will get an unused import warning
697 and self.scope[varn].used):
698 self.report(messages.ImportShadowedByLoopVar,
699 node, varn, self.scope[varn].source)
700
701 self.handleChildren(node)
702
703 def NAME(self, node):
704 """
705 Handle occurrence of Name (which can be a load/store/delete access.)
706 """
707 # Locate the name in locals / function / globals scopes.
708 if isinstance(node.ctx, (ast.Load, ast.AugLoad)):
709 self.handleNodeLoad(node)
710 if (node.id == 'locals' and isinstance(self.scope, FunctionScope)
711 and isinstance(node.parent, ast.Call)):
712 # we are doing locals() call in current scope
713 self.scope.usesLocals = True
714 elif isinstance(node.ctx, (ast.Store, ast.AugStore)):
715 self.handleNodeStore(node)
716 elif isinstance(node.ctx, ast.Del):
717 self.handleNodeDelete(node)
718 else:
719 # must be a Param context -- this only happens for names in function
720 # arguments, but these aren't dispatched through here
721 raise RuntimeError("Got impossible expression context: %r" % (node.ctx,))
722
723 def FUNCTIONDEF(self, node):
724 for deco in node.decorator_list:
725 self.handleNode(deco, node)
726 self.addBinding(node, FunctionDefinition(node.name, node))
727 self.LAMBDA(node)
728 if self.withDoctest:
729 self.deferFunction(lambda: self.handleDoctests(node))
730
731 def LAMBDA(self, node):
732 args = []
733
734 if PY2:
735 def addArgs(arglist):
736 for arg in arglist:
737 if isinstance(arg, ast.Tuple):
738 addArgs(arg.elts)
739 else:
740 if arg.id in args:
741 self.report(messages.DuplicateArgument,
742 node, arg.id)
743 args.append(arg.id)
744 addArgs(node.args.args)
745 defaults = node.args.defaults
746 else:
747 for arg in node.args.args + node.args.kwonlyargs:
748 if arg.arg in args:
749 self.report(messages.DuplicateArgument,
750 node, arg.arg)
751 args.append(arg.arg)
752 self.handleNode(arg.annotation, node)
753 if hasattr(node, 'returns'): # Only for FunctionDefs
754 for annotation in (node.args.varargannotation,
755 node.args.kwargannotation, node.returns):
756 self.handleNode(annotation, node)
757 defaults = node.args.defaults + node.args.kw_defaults
758
759 # vararg/kwarg identifiers are not Name nodes
760 for wildcard in (node.args.vararg, node.args.kwarg):
761 if not wildcard:
762 continue
763 if wildcard in args:
764 self.report(messages.DuplicateArgument, node, wildcard)
765 args.append(wildcard)
766 for default in defaults:
767 self.handleNode(default, node)
768
769 def runFunction():
770
771 self.pushScope()
772 for name in args:
773 self.addBinding(node, Argument(name, node), reportRedef=False)
774 if isinstance(node.body, list):
775 # case for FunctionDefs
776 for stmt in node.body:
777 self.handleNode(stmt, node)
778 else:
779 # case for Lambdas
780 self.handleNode(node.body, node)
781
782 def checkUnusedAssignments():
783 """
784 Check to see if any assignments have not been used.
785 """
786 for name, binding in self.scope.unusedAssignments():
787 self.report(messages.UnusedVariable, binding.source, name)
788 self.deferAssignment(checkUnusedAssignments)
789 self.popScope()
790
791 self.deferFunction(runFunction)
792
793 def CLASSDEF(self, node):
794 """
795 Check names used in a class definition, including its decorators, base
796 classes, and the body of its definition. Additionally, add its name to
797 the current scope.
798 """
799 for deco in node.decorator_list:
800 self.handleNode(deco, node)
801 for baseNode in node.bases:
802 self.handleNode(baseNode, node)
803 if not PY2:
804 for keywordNode in node.keywords:
805 self.handleNode(keywordNode, node)
806 self.pushScope(ClassScope)
807 if self.withDoctest:
808 self.deferFunction(lambda: self.handleDoctests(node))
809 for stmt in node.body:
810 self.handleNode(stmt, node)
811 self.popScope()
812 self.addBinding(node, ClassDefinition(node.name, node))
813
814 def ASSIGN(self, node):
815 self.handleNode(node.value, node)
816 for target in node.targets:
817 self.handleNode(target, node)
818
819 def AUGASSIGN(self, node):
820 self.handleNodeLoad(node.target)
821 self.handleNode(node.value, node)
822 self.handleNode(node.target, node)
823
824 def IMPORT(self, node):
825 for alias in node.names:
826 name = alias.asname or alias.name
827 importation = Importation(name, node)
828 self.addBinding(node, importation)
829
830 def IMPORTFROM(self, node):
831 if node.module == '__future__':
832 if not self.futuresAllowed:
833 self.report(messages.LateFutureImport,
834 node, [n.name for n in node.names])
835 else:
836 self.futuresAllowed = False
837
838 for alias in node.names:
839 if alias.name == '*':
840 self.scope.importStarred = True
841 self.report(messages.ImportStarUsed, node, node.module)
842 continue
843 name = alias.asname or alias.name
844 importation = Importation(name, node)
845 if node.module == '__future__':
846 importation.used = (self.scope, node)
847 self.addBinding(node, importation)
848
849 def TRY(self, node):
850 handler_names = []
851 # List the exception handlers
852 for handler in node.handlers:
853 if isinstance(handler.type, ast.Tuple):
854 for exc_type in handler.type.elts:
855 handler_names.append(getNodeName(exc_type))
856 elif handler.type:
857 handler_names.append(getNodeName(handler.type))
858 # Memorize the except handlers and process the body
859 self.exceptHandlers.append(handler_names)
860 for child in node.body:
861 self.handleNode(child, node)
862 self.exceptHandlers.pop()
863 # Process the other nodes: "except:", "else:", "finally:"
864 for child in iter_child_nodes(node):
865 if child not in node.body:
866 self.handleNode(child, node)
867
868 TRYEXCEPT = TRY
869
870 def EXCEPTHANDLER(self, node):
871 # 3.x: in addition to handling children, we must handle the name of
872 # the exception, which is not a Name node, but a simple string.
873 if isinstance(node.name, str):
874 self.handleNodeStore(node)
875 self.handleChildren(node)

eric ide

mercurial