Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py

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

eric ide

mercurial