eric6/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py

changeset 6942
2602857055c5
parent 6742
7cb30f7f94f6
child 7060
d04e8965af91
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2019 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 eric6
8 """
9 Main module.
10
11 Implement the central Checker class.
12 Also, it models the Bindings and Scopes.
13 """
14 import __future__
15 import ast
16 import bisect
17 import collections
18 import doctest
19 import functools
20 import os
21 import re
22 import sys
23 import tokenize
24
25 from . import messages
26
27 PY2 = sys.version_info < (3, 0)
28 PY35_PLUS = sys.version_info >= (3, 5) # Python 3.5 and above
29 PY36_PLUS = sys.version_info >= (3, 6) # Python 3.6 and above
30 PY38_PLUS = sys.version_info >= (3, 8)
31 try:
32 sys.pypy_version_info
33 PYPY = True
34 except AttributeError:
35 PYPY = False
36
37 builtin_vars = dir(__import__('__builtin__' if PY2 else 'builtins'))
38
39 if PY2:
40 tokenize_tokenize = tokenize.generate_tokens
41 else:
42 tokenize_tokenize = tokenize.tokenize
43
44 if PY2:
45 def getNodeType(node_class):
46 # workaround str.upper() which is locale-dependent
47 return str(unicode(node_class.__name__).upper()) # __IGNORE_WARNING__
48
49 def get_raise_argument(node):
50 return node.type
51
52 else:
53 def getNodeType(node_class):
54 return node_class.__name__.upper()
55
56 def get_raise_argument(node):
57 return node.exc
58
59 # Silence `pyflakes` from reporting `undefined name 'unicode'` in Python 3.
60 unicode = str
61
62 # Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)
63 if PY2:
64 def getAlternatives(n):
65 if isinstance(n, (ast.If, ast.TryFinally)):
66 return [n.body]
67 if isinstance(n, ast.TryExcept):
68 return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
69 else:
70 def getAlternatives(n):
71 if isinstance(n, ast.If):
72 return [n.body]
73 if isinstance(n, ast.Try):
74 return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
75
76 if PY35_PLUS:
77 FOR_TYPES = (ast.For, ast.AsyncFor)
78 LOOP_TYPES = (ast.While, ast.For, ast.AsyncFor)
79 else:
80 FOR_TYPES = (ast.For,)
81 LOOP_TYPES = (ast.While, ast.For)
82
83 # https://github.com/python/typed_ast/blob/55420396/ast27/Parser/tokenizer.c#L102-L104
84 TYPE_COMMENT_RE = re.compile(r'^#\s*type:\s*')
85 # https://github.com/python/typed_ast/blob/55420396/ast27/Parser/tokenizer.c#L1400
86 TYPE_IGNORE_RE = re.compile(TYPE_COMMENT_RE.pattern + r'ignore\s*(#|$)')
87 # https://github.com/python/typed_ast/blob/55420396/ast27/Grammar/Grammar#L147
88 TYPE_FUNC_RE = re.compile(r'^(\(.*?\))\s*->\s*(.*)$')
89
90
91 class _FieldsOrder(dict):
92 """Fix order of AST node fields."""
93
94 def _get_fields(self, node_class):
95 # handle iter before target, and generators before element
96 fields = node_class._fields
97 if 'iter' in fields:
98 key_first = 'iter'.find
99 elif 'generators' in fields:
100 key_first = 'generators'.find
101 else:
102 key_first = 'value'.find
103 return tuple(sorted(fields, key=key_first, reverse=True))
104
105 def __missing__(self, node_class):
106 self[node_class] = fields = self._get_fields(node_class)
107 return fields
108
109
110 def counter(items):
111 """
112 Simplest required implementation of collections.Counter. Required as 2.6
113 does not have Counter in collections.
114 """
115 results = {}
116 for item in items:
117 results[item] = results.get(item, 0) + 1
118 return results
119
120
121 def iter_child_nodes(node, omit=None, _fields_order=_FieldsOrder()):
122 """
123 Yield all direct child nodes of *node*, that is, all fields that
124 are nodes and all items of fields that are lists of nodes.
125
126 :param node: AST node to be iterated upon
127 :param omit: String or tuple of strings denoting the
128 attributes of the node to be omitted from
129 further parsing
130 :param _fields_order: Order of AST node fields
131 """
132 for name in _fields_order[node.__class__]:
133 if omit and name in omit:
134 continue
135 field = getattr(node, name, None)
136 if isinstance(field, ast.AST):
137 yield field
138 elif isinstance(field, list):
139 for item in field:
140 yield item
141
142
143 def convert_to_value(item):
144 if isinstance(item, ast.Str):
145 return item.s
146 elif hasattr(ast, 'Bytes') and isinstance(item, ast.Bytes):
147 return item.s
148 elif isinstance(item, ast.Tuple):
149 return tuple(convert_to_value(i) for i in item.elts)
150 elif isinstance(item, ast.Num):
151 return item.n
152 elif isinstance(item, ast.Name):
153 result = VariableKey(item=item)
154 constants_lookup = {
155 'True': True,
156 'False': False,
157 'None': None,
158 }
159 return constants_lookup.get(
160 result.name,
161 result,
162 )
163 elif (not PY2) and isinstance(item, ast.NameConstant):
164 # None, True, False are nameconstants in python3, but names in 2
165 return item.value
166 else:
167 return UnhandledKeyType()
168
169
170 def is_notimplemented_name_node(node):
171 return isinstance(node, ast.Name) and getNodeName(node) == 'NotImplemented'
172
173
174 class Binding(object):
175 """
176 Represents the binding of a value to a name.
177
178 The checker uses this to keep track of which names have been bound and
179 which names have not. See L{Assignment} for a special type of binding that
180 is checked with stricter rules.
181
182 @ivar used: pair of (L{Scope}, node) indicating the scope and
183 the node that this binding was last used.
184 """
185
186 def __init__(self, name, source):
187 self.name = name
188 self.source = source
189 self.used = False
190
191 def __str__(self):
192 return self.name
193
194 def __repr__(self):
195 return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__,
196 self.name,
197 self.source.lineno,
198 id(self))
199
200 def redefines(self, other):
201 return isinstance(other, Definition) and self.name == other.name
202
203
204 class Definition(Binding):
205 """
206 A binding that defines a function or a class.
207 """
208
209
210 class Builtin(Definition):
211 """A definition created for all Python builtins."""
212
213 def __init__(self, name):
214 super(Builtin, self).__init__(name, None)
215
216 def __repr__(self):
217 return '<%s object %r at 0x%x>' % (self.__class__.__name__,
218 self.name,
219 id(self))
220
221
222 class UnhandledKeyType(object):
223 """
224 A dictionary key of a type that we cannot or do not check for duplicates.
225 """
226
227
228 class VariableKey(object):
229 """
230 A dictionary key which is a variable.
231
232 @ivar item: The variable AST object.
233 """
234 def __init__(self, item):
235 self.name = item.id
236
237 def __eq__(self, compare):
238 return (
239 compare.__class__ == self.__class__ and
240 compare.name == self.name
241 )
242
243 def __hash__(self):
244 return hash(self.name)
245
246
247 class Importation(Definition):
248 """
249 A binding created by an import statement.
250
251 @ivar fullName: The complete name given to the import statement,
252 possibly including multiple dotted components.
253 @type fullName: C{str}
254 """
255
256 def __init__(self, name, source, full_name=None):
257 self.fullName = full_name or name
258 self.redefined = []
259 super(Importation, self).__init__(name, source)
260
261 def redefines(self, other):
262 if isinstance(other, SubmoduleImportation):
263 # See note in SubmoduleImportation about RedefinedWhileUnused
264 return self.fullName == other.fullName
265 return isinstance(other, Definition) and self.name == other.name
266
267 def _has_alias(self):
268 """Return whether importation needs an as clause."""
269 return not self.fullName.split('.')[-1] == self.name
270
271 @property
272 def source_statement(self):
273 """Generate a source statement equivalent to the import."""
274 if self._has_alias():
275 return 'import %s as %s' % (self.fullName, self.name)
276 else:
277 return 'import %s' % self.fullName
278
279 def __str__(self):
280 """Return import full name with alias."""
281 if self._has_alias():
282 return self.fullName + ' as ' + self.name
283 else:
284 return self.fullName
285
286
287 class SubmoduleImportation(Importation):
288 """
289 A binding created by a submodule import statement.
290
291 A submodule import is a special case where the root module is implicitly
292 imported, without an 'as' clause, and the submodule is also imported.
293 Python does not restrict which attributes of the root module may be used.
294
295 This class is only used when the submodule import is without an 'as' clause.
296
297 pyflakes handles this case by registering the root module name in the scope,
298 allowing any attribute of the root module to be accessed.
299
300 RedefinedWhileUnused is suppressed in `redefines` unless the submodule
301 name is also the same, to avoid false positives.
302 """
303
304 def __init__(self, name, source):
305 # A dot should only appear in the name when it is a submodule import
306 assert '.' in name and (not source or isinstance(source, ast.Import))
307 package_name = name.split('.')[0]
308 super(SubmoduleImportation, self).__init__(package_name, source)
309 self.fullName = name
310
311 def redefines(self, other):
312 if isinstance(other, Importation):
313 return self.fullName == other.fullName
314 return super(SubmoduleImportation, self).redefines(other)
315
316 def __str__(self):
317 return self.fullName
318
319 @property
320 def source_statement(self):
321 return 'import ' + self.fullName
322
323
324 class ImportationFrom(Importation):
325
326 def __init__(self, name, source, module, real_name=None):
327 self.module = module
328 self.real_name = real_name or name
329
330 if module.endswith('.'):
331 full_name = module + self.real_name
332 else:
333 full_name = module + '.' + self.real_name
334
335 super(ImportationFrom, self).__init__(name, source, full_name)
336
337 def __str__(self):
338 """Return import full name with alias."""
339 if self.real_name != self.name:
340 return self.fullName + ' as ' + self.name
341 else:
342 return self.fullName
343
344 @property
345 def source_statement(self):
346 if self.real_name != self.name:
347 return 'from %s import %s as %s' % (self.module,
348 self.real_name,
349 self.name)
350 else:
351 return 'from %s import %s' % (self.module, self.name)
352
353
354 class StarImportation(Importation):
355 """A binding created by a 'from x import *' statement."""
356
357 def __init__(self, name, source):
358 super(StarImportation, self).__init__('*', source)
359 # Each star importation needs a unique name, and
360 # may not be the module name otherwise it will be deemed imported
361 self.name = name + '.*'
362 self.fullName = name
363
364 @property
365 def source_statement(self):
366 return 'from ' + self.fullName + ' import *'
367
368 def __str__(self):
369 # When the module ends with a ., avoid the ambiguous '..*'
370 if self.fullName.endswith('.'):
371 return self.source_statement
372 else:
373 return self.name
374
375
376 class FutureImportation(ImportationFrom):
377 """
378 A binding created by a from `__future__` import statement.
379
380 `__future__` imports are implicitly used.
381 """
382
383 def __init__(self, name, source, scope):
384 super(FutureImportation, self).__init__(name, source, '__future__')
385 self.used = (scope, source)
386
387
388 class Argument(Binding):
389 """
390 Represents binding a name as an argument.
391 """
392
393
394 class Assignment(Binding):
395 """
396 Represents binding a name with an explicit assignment.
397
398 The checker will raise warnings for any Assignment that isn't used. Also,
399 the checker does not consider assignments in tuple/list unpacking to be
400 Assignments, rather it treats them as simple Bindings.
401 """
402
403
404 class FunctionDefinition(Definition):
405 pass
406
407
408 class ClassDefinition(Definition):
409 pass
410
411
412 class ExportBinding(Binding):
413 """
414 A binding created by an C{__all__} assignment. If the names in the list
415 can be determined statically, they will be treated as names for export and
416 additional checking applied to them.
417
418 The only recognized C{__all__} assignment via list concatenation is in the
419 following format:
420
421 __all__ = ['a'] + ['b'] + ['c']
422
423 Names which are imported and not otherwise used but appear in the value of
424 C{__all__} will not have an unused import warning reported for them.
425 """
426
427 def __init__(self, name, source, scope):
428 if '__all__' in scope and isinstance(source, ast.AugAssign):
429 self.names = list(scope['__all__'].names)
430 else:
431 self.names = []
432
433 def _add_to_names(container):
434 for node in container.elts:
435 if isinstance(node, ast.Str):
436 self.names.append(node.s)
437
438 if isinstance(source.value, (ast.List, ast.Tuple)):
439 _add_to_names(source.value)
440 # If concatenating lists
441 elif isinstance(source.value, ast.BinOp):
442 currentValue = source.value
443 while isinstance(currentValue.right, ast.List):
444 left = currentValue.left
445 right = currentValue.right
446 _add_to_names(right)
447 # If more lists are being added
448 if isinstance(left, ast.BinOp):
449 currentValue = left
450 # If just two lists are being added
451 elif isinstance(left, ast.List):
452 _add_to_names(left)
453 # All lists accounted for - done
454 break
455 # If not list concatenation
456 else:
457 break
458 super(ExportBinding, self).__init__(name, source)
459
460
461 class Scope(dict):
462 importStarred = False # set to True when import * is found
463
464 def __repr__(self):
465 scope_cls = self.__class__.__name__
466 return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self))
467
468
469 class ClassScope(Scope):
470 pass
471
472
473 class FunctionScope(Scope):
474 """
475 I represent a name scope for a function.
476
477 @ivar globals: Names declared 'global' in this function.
478 """
479 usesLocals = False
480 alwaysUsed = {'__tracebackhide__', '__traceback_info__',
481 '__traceback_supplement__'}
482
483 def __init__(self):
484 super(FunctionScope, self).__init__()
485 # Simplify: manage the special locals as globals
486 self.globals = self.alwaysUsed.copy()
487 self.returnValue = None # First non-empty return
488 self.isGenerator = False # Detect a generator
489
490 def unusedAssignments(self):
491 """
492 Return a generator for the assignments which have not been used.
493 """
494 for name, binding in self.items():
495 if (not binding.used and
496 name != '_' and # see issue #202
497 name not in self.globals and
498 not self.usesLocals and
499 isinstance(binding, Assignment)):
500 yield name, binding
501
502
503 class GeneratorScope(Scope):
504 pass
505
506
507 class ModuleScope(Scope):
508 """Scope for a module."""
509 _futures_allowed = True
510 _annotations_future_enabled = False
511
512
513 class DoctestScope(ModuleScope):
514 """Scope for a doctest."""
515
516
517 # Globally defined names which are not attributes of the builtins module, or
518 # are only present on some platforms.
519 _MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError']
520 # module scope annotation will store in `__annotations__`, see also PEP 526.
521 if PY36_PLUS:
522 _MAGIC_GLOBALS.append('__annotations__')
523
524
525 def getNodeName(node):
526 # Returns node.id, or node.name, or None
527 if hasattr(node, 'id'): # One of the many nodes with an id
528 return node.id
529 if hasattr(node, 'name'): # an ExceptHandler node
530 return node.name
531
532
533 def is_typing_overload(value, scope):
534 def is_typing_overload_decorator(node):
535 return (
536 (
537 isinstance(node, ast.Name) and
538 node.id in scope and
539 scope[node.id].fullName == 'typing.overload'
540 ) or (
541 isinstance(node, ast.Attribute) and
542 isinstance(node.value, ast.Name) and
543 node.value.id == 'typing' and
544 node.attr == 'overload'
545 )
546 )
547
548 return (
549 isinstance(value.source, ast.FunctionDef) and
550 len(value.source.decorator_list) == 1 and
551 is_typing_overload_decorator(value.source.decorator_list[0])
552 )
553
554
555 def make_tokens(code):
556 # PY3: tokenize.tokenize requires readline of bytes
557 if not isinstance(code, bytes):
558 code = code.encode('UTF-8')
559 lines = iter(code.splitlines(True))
560 # next(lines, b'') is to prevent an error in pypy3
561 return tuple(tokenize_tokenize(lambda: next(lines, b'')))
562
563
564 class _TypeableVisitor(ast.NodeVisitor):
565 """Collect the line number and nodes which are deemed typeable by
566 PEP 484
567
568 https://www.python.org/dev/peps/pep-0484/#type-comments
569 """
570 def __init__(self):
571 self.typeable_lines = [] # type: List[int]
572 self.typeable_nodes = {} # type: Dict[int, ast.AST]
573
574 def _typeable(self, node):
575 # if there is more than one typeable thing on a line last one wins
576 self.typeable_lines.append(node.lineno)
577 self.typeable_nodes[node.lineno] = node
578
579 self.generic_visit(node)
580
581 visit_Assign = visit_For = visit_FunctionDef = visit_With = _typeable
582 visit_AsyncFor = visit_AsyncFunctionDef = visit_AsyncWith = _typeable
583
584
585 def _collect_type_comments(tree, tokens):
586 visitor = _TypeableVisitor()
587 visitor.visit(tree)
588
589 type_comments = collections.defaultdict(list)
590 for tp, text, start, _, _ in tokens:
591 if (
592 tp != tokenize.COMMENT or # skip non comments
593 not TYPE_COMMENT_RE.match(text) or # skip non-type comments
594 TYPE_IGNORE_RE.match(text) # skip ignores
595 ):
596 continue
597
598 # search for the typeable node at or before the line number of the
599 # type comment.
600 # if the bisection insertion point is before any nodes this is an
601 # invalid type comment which is ignored.
602 lineno, _ = start
603 idx = bisect.bisect_right(visitor.typeable_lines, lineno)
604 if idx == 0:
605 continue
606 node = visitor.typeable_nodes[visitor.typeable_lines[idx - 1]]
607 type_comments[node].append((start, text))
608
609 return type_comments
610
611
612 class Checker(object):
613 """
614 I check the cleanliness and sanity of Python code.
615
616 @ivar _deferredFunctions: Tracking list used by L{deferFunction}. Elements
617 of the list are two-tuples. The first element is the callable passed
618 to L{deferFunction}. The second element is a copy of the scope stack
619 at the time L{deferFunction} was called.
620
621 @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for
622 callables which are deferred assignment checks.
623 """
624
625 _ast_node_scope = {
626 ast.Module: ModuleScope,
627 ast.ClassDef: ClassScope,
628 ast.FunctionDef: FunctionScope,
629 ast.Lambda: FunctionScope,
630 ast.ListComp: GeneratorScope,
631 ast.SetComp: GeneratorScope,
632 ast.GeneratorExp: GeneratorScope,
633 ast.DictComp: GeneratorScope,
634 }
635 if PY35_PLUS:
636 _ast_node_scope[ast.AsyncFunctionDef] = FunctionScope,
637
638 nodeDepth = 0
639 offset = None
640 traceTree = False
641
642 builtIns = set(builtin_vars).union(_MAGIC_GLOBALS)
643 _customBuiltIns = os.environ.get('PYFLAKES_BUILTINS')
644 if _customBuiltIns:
645 builtIns.update(_customBuiltIns.split(','))
646 del _customBuiltIns
647
648 # TODO: file_tokens= is required to perform checks on type comments,
649 # eventually make this a required positional argument. For now it
650 # is defaulted to `()` for api compatibility.
651 def __init__(self, tree, filename='(none)', builtins=None,
652 withDoctest='PYFLAKES_DOCTEST' in os.environ, file_tokens=()):
653 self._nodeHandlers = {}
654 self._deferredFunctions = []
655 self._deferredAssignments = []
656 self.deadScopes = []
657 self.messages = []
658 self.filename = filename
659 if builtins:
660 self.builtIns = self.builtIns.union(builtins)
661 self.withDoctest = withDoctest
662 try:
663 self.scopeStack = [Checker._ast_node_scope[type(tree)]()]
664 except KeyError:
665 raise RuntimeError('No scope implemented for the node %r' % tree)
666 self.exceptHandlers = [()]
667 self.root = tree
668 self._type_comments = _collect_type_comments(tree, file_tokens)
669 for builtin in self.builtIns:
670 self.addBinding(None, Builtin(builtin))
671 self.handleChildren(tree)
672 self.runDeferred(self._deferredFunctions)
673 # Set _deferredFunctions to None so that deferFunction will fail
674 # noisily if called after we've run through the deferred functions.
675 self._deferredFunctions = None
676 self.runDeferred(self._deferredAssignments)
677 # Set _deferredAssignments to None so that deferAssignment will fail
678 # noisily if called after we've run through the deferred assignments.
679 self._deferredAssignments = None
680 del self.scopeStack[1:]
681 self.popScope()
682 self.checkDeadScopes()
683
684 def deferFunction(self, callable):
685 """
686 Schedule a function handler to be called just before completion.
687
688 This is used for handling function bodies, which must be deferred
689 because code later in the file might modify the global scope. When
690 `callable` is called, the scope at the time this is called will be
691 restored, however it will contain any new bindings added to it.
692 """
693 self._deferredFunctions.append((callable, self.scopeStack[:], self.offset))
694
695 def deferAssignment(self, callable):
696 """
697 Schedule an assignment handler to be called just after deferred
698 function handlers.
699 """
700 self._deferredAssignments.append((callable, self.scopeStack[:], self.offset))
701
702 def runDeferred(self, deferred):
703 """
704 Run the callables in C{deferred} using their associated scope stack.
705 """
706 for handler, scope, offset in deferred:
707 self.scopeStack = scope
708 self.offset = offset
709 handler()
710
711 def _in_doctest(self):
712 return (len(self.scopeStack) >= 2 and
713 isinstance(self.scopeStack[1], DoctestScope))
714
715 @property
716 def futuresAllowed(self):
717 if not all(isinstance(scope, ModuleScope)
718 for scope in self.scopeStack):
719 return False
720
721 return self.scope._futures_allowed
722
723 @futuresAllowed.setter
724 def futuresAllowed(self, value):
725 assert value is False
726 if isinstance(self.scope, ModuleScope):
727 self.scope._futures_allowed = False
728
729 @property
730 def annotationsFutureEnabled(self):
731 scope = self.scopeStack[0]
732 if not isinstance(scope, ModuleScope):
733 return False
734 return scope._annotations_future_enabled
735
736 @annotationsFutureEnabled.setter
737 def annotationsFutureEnabled(self, value):
738 assert value is True
739 assert isinstance(self.scope, ModuleScope)
740 self.scope._annotations_future_enabled = True
741
742 @property
743 def scope(self):
744 return self.scopeStack[-1]
745
746 def popScope(self):
747 self.deadScopes.append(self.scopeStack.pop())
748
749 def checkDeadScopes(self):
750 """
751 Look at scopes which have been fully examined and report names in them
752 which were imported but unused.
753 """
754 for scope in self.deadScopes:
755 # imports in classes are public members
756 if isinstance(scope, ClassScope):
757 continue
758
759 all_binding = scope.get('__all__')
760 if all_binding and not isinstance(all_binding, ExportBinding):
761 all_binding = None
762
763 if all_binding:
764 all_names = set(all_binding.names)
765 undefined = all_names.difference(scope)
766 else:
767 all_names = undefined = []
768
769 if undefined:
770 if not scope.importStarred and \
771 os.path.basename(self.filename) != '__init__.py':
772 # Look for possible mistakes in the export list
773 for name in undefined:
774 self.report(messages.UndefinedExport,
775 scope['__all__'].source, name)
776
777 # mark all import '*' as used by the undefined in __all__
778 if scope.importStarred:
779 from_list = []
780 for binding in scope.values():
781 if isinstance(binding, StarImportation):
782 binding.used = all_binding
783 from_list.append(binding.fullName)
784 # report * usage, with a list of possible sources
785 from_list = ', '.join(sorted(from_list))
786 for name in undefined:
787 self.report(messages.ImportStarUsage,
788 scope['__all__'].source, name, from_list)
789
790 # Look for imported names that aren't used.
791 for value in scope.values():
792 if isinstance(value, Importation):
793 used = value.used or value.name in all_names
794 if not used:
795 messg = messages.UnusedImport
796 self.report(messg, value.source, str(value))
797 for node in value.redefined:
798 if isinstance(self.getParent(node), FOR_TYPES):
799 messg = messages.ImportShadowedByLoopVar
800 elif used:
801 continue
802 else:
803 messg = messages.RedefinedWhileUnused
804 self.report(messg, node, value.name, value.source)
805
806 def pushScope(self, scopeClass=FunctionScope):
807 self.scopeStack.append(scopeClass())
808
809 def report(self, messageClass, *args, **kwargs):
810 self.messages.append(messageClass(self.filename, *args, **kwargs))
811
812 def getParent(self, node):
813 # Lookup the first parent which is not Tuple, List or Starred
814 while True:
815 node = node.parent
816 if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
817 return node
818
819 def getCommonAncestor(self, lnode, rnode, stop):
820 if stop in (lnode, rnode) or not (hasattr(lnode, 'parent') and
821 hasattr(rnode, 'parent')):
822 return None
823 if lnode is rnode:
824 return lnode
825
826 if (lnode.depth > rnode.depth):
827 return self.getCommonAncestor(lnode.parent, rnode, stop)
828 if (lnode.depth < rnode.depth):
829 return self.getCommonAncestor(lnode, rnode.parent, stop)
830 return self.getCommonAncestor(lnode.parent, rnode.parent, stop)
831
832 def descendantOf(self, node, ancestors, stop):
833 for a in ancestors:
834 if self.getCommonAncestor(node, a, stop):
835 return True
836 return False
837
838 def _getAncestor(self, node, ancestor_type):
839 parent = node
840 while True:
841 if parent is self.root:
842 return None
843 parent = self.getParent(parent)
844 if isinstance(parent, ancestor_type):
845 return parent
846
847 def getScopeNode(self, node):
848 return self._getAncestor(node, tuple(Checker._ast_node_scope.keys()))
849
850 def differentForks(self, lnode, rnode):
851 """True, if lnode and rnode are located on different forks of IF/TRY"""
852 ancestor = self.getCommonAncestor(lnode, rnode, self.root)
853 parts = getAlternatives(ancestor)
854 if parts:
855 for items in parts:
856 if self.descendantOf(lnode, items, ancestor) ^ \
857 self.descendantOf(rnode, items, ancestor):
858 return True
859 return False
860
861 def addBinding(self, node, value):
862 """
863 Called when a binding is altered.
864
865 - `node` is the statement responsible for the change
866 - `value` is the new value, a Binding instance
867 """
868 # assert value.source in (node, node.parent):
869 for scope in self.scopeStack[::-1]:
870 if value.name in scope:
871 break
872 existing = scope.get(value.name)
873
874 if (existing and not isinstance(existing, Builtin) and
875 not self.differentForks(node, existing.source)):
876
877 parent_stmt = self.getParent(value.source)
878 if isinstance(existing, Importation) and isinstance(parent_stmt, FOR_TYPES):
879 self.report(messages.ImportShadowedByLoopVar,
880 node, value.name, existing.source)
881
882 elif scope is self.scope:
883 if (isinstance(parent_stmt, ast.comprehension) and
884 not isinstance(self.getParent(existing.source),
885 (FOR_TYPES, ast.comprehension))):
886 self.report(messages.RedefinedInListComp,
887 node, value.name, existing.source)
888 elif not existing.used and value.redefines(existing):
889 if value.name != '_' or isinstance(existing, Importation):
890 if not is_typing_overload(existing, self.scope):
891 self.report(messages.RedefinedWhileUnused,
892 node, value.name, existing.source)
893
894 elif isinstance(existing, Importation) and value.redefines(existing):
895 existing.redefined.append(node)
896
897 if value.name in self.scope:
898 # then assume the rebound name is used as a global or within a loop
899 value.used = self.scope[value.name].used
900
901 self.scope[value.name] = value
902
903 def getNodeHandler(self, node_class):
904 try:
905 return self._nodeHandlers[node_class]
906 except KeyError:
907 nodeType = getNodeType(node_class)
908 self._nodeHandlers[node_class] = handler = getattr(self, nodeType)
909 return handler
910
911 def handleNodeLoad(self, node):
912 name = getNodeName(node)
913 if not name:
914 return
915
916 in_generators = None
917 importStarred = None
918
919 # try enclosing function scopes and global scope
920 for scope in self.scopeStack[-1::-1]:
921 if isinstance(scope, ClassScope):
922 if not PY2 and name == '__class__':
923 return
924 elif in_generators is False:
925 # only generators used in a class scope can access the
926 # names of the class. this is skipped during the first
927 # iteration
928 continue
929
930 if (name == 'print' and
931 isinstance(scope.get(name, None), Builtin)):
932 parent = self.getParent(node)
933 if (isinstance(parent, ast.BinOp) and
934 isinstance(parent.op, ast.RShift)):
935 self.report(messages.InvalidPrintSyntax, node)
936
937 try:
938 scope[name].used = (self.scope, node)
939
940 # if the name of SubImportation is same as
941 # alias of other Importation and the alias
942 # is used, SubImportation also should be marked as used.
943 n = scope[name]
944 if isinstance(n, Importation) and n._has_alias():
945 try:
946 scope[n.fullName].used = (self.scope, node)
947 except KeyError:
948 pass
949 except KeyError:
950 pass
951 else:
952 return
953
954 importStarred = importStarred or scope.importStarred
955
956 if in_generators is not False:
957 in_generators = isinstance(scope, GeneratorScope)
958
959 if importStarred:
960 from_list = []
961
962 for scope in self.scopeStack[-1::-1]:
963 for binding in scope.values():
964 if isinstance(binding, StarImportation):
965 # mark '*' imports as used for each scope
966 binding.used = (self.scope, node)
967 from_list.append(binding.fullName)
968
969 # report * usage, with a list of possible sources
970 from_list = ', '.join(sorted(from_list))
971 self.report(messages.ImportStarUsage, node, name, from_list)
972 return
973
974 if name == '__path__' and os.path.basename(self.filename) == '__init__.py':
975 # the special name __path__ is valid only in packages
976 return
977
978 if name == '__module__' and isinstance(self.scope, ClassScope):
979 return
980
981 # protected with a NameError handler?
982 if 'NameError' not in self.exceptHandlers[-1]:
983 self.report(messages.UndefinedName, node, name)
984
985 def handleNodeStore(self, node):
986 name = getNodeName(node)
987 if not name:
988 return
989 # if the name hasn't already been defined in the current scope
990 if isinstance(self.scope, FunctionScope) and name not in self.scope:
991 # for each function or module scope above us
992 for scope in self.scopeStack[:-1]:
993 if not isinstance(scope, (FunctionScope, ModuleScope)):
994 continue
995 # if the name was defined in that scope, and the name has
996 # been accessed already in the current scope, and hasn't
997 # been declared global
998 used = name in scope and scope[name].used
999 if used and used[0] is self.scope and name not in self.scope.globals:
1000 # then it's probably a mistake
1001 self.report(messages.UndefinedLocal,
1002 scope[name].used[1], name, scope[name].source)
1003 break
1004
1005 parent_stmt = self.getParent(node)
1006 if isinstance(parent_stmt, (FOR_TYPES, ast.comprehension)) or (
1007 parent_stmt != node.parent and
1008 not self.isLiteralTupleUnpacking(parent_stmt)):
1009 binding = Binding(name, node)
1010 elif name == '__all__' and isinstance(self.scope, ModuleScope):
1011 binding = ExportBinding(name, node.parent, self.scope)
1012 elif isinstance(getattr(node, 'ctx', None), ast.Param):
1013 binding = Argument(name, self.getScopeNode(node))
1014 else:
1015 binding = Assignment(name, node)
1016 self.addBinding(node, binding)
1017
1018 def handleNodeDelete(self, node):
1019
1020 def on_conditional_branch():
1021 """
1022 Return `True` if node is part of a conditional body.
1023 """
1024 current = getattr(node, 'parent', None)
1025 while current:
1026 if isinstance(current, (ast.If, ast.While, ast.IfExp)):
1027 return True
1028 current = getattr(current, 'parent', None)
1029 return False
1030
1031 name = getNodeName(node)
1032 if not name:
1033 return
1034
1035 if on_conditional_branch():
1036 # We cannot predict if this conditional branch is going to
1037 # be executed.
1038 return
1039
1040 if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
1041 self.scope.globals.remove(name)
1042 else:
1043 try:
1044 del self.scope[name]
1045 except KeyError:
1046 self.report(messages.UndefinedName, node, name)
1047
1048 def _handle_type_comments(self, node):
1049 for (lineno, col_offset), comment in self._type_comments.get(node, ()):
1050 comment = comment.split(':', 1)[1].strip()
1051 func_match = TYPE_FUNC_RE.match(comment)
1052 if func_match:
1053 parts = (
1054 func_match.group(1).replace('*', ''),
1055 func_match.group(2).strip(),
1056 )
1057 else:
1058 parts = (comment,)
1059
1060 for part in parts:
1061 if PY2:
1062 part = part.replace('...', 'Ellipsis')
1063 self.deferFunction(functools.partial(
1064 self.handleStringAnnotation,
1065 part, node, lineno, col_offset,
1066 messages.CommentAnnotationSyntaxError,
1067 ))
1068
1069 def handleChildren(self, tree, omit=None):
1070 self._handle_type_comments(tree)
1071 for node in iter_child_nodes(tree, omit=omit):
1072 self.handleNode(node, tree)
1073
1074 def isLiteralTupleUnpacking(self, node):
1075 if isinstance(node, ast.Assign):
1076 for child in node.targets + [node.value]:
1077 if not hasattr(child, 'elts'):
1078 return False
1079 return True
1080
1081 def isDocstring(self, node):
1082 """
1083 Determine if the given node is a docstring, as long as it is at the
1084 correct place in the node tree.
1085 """
1086 return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and
1087 isinstance(node.value, ast.Str))
1088
1089 def getDocstring(self, node):
1090 if isinstance(node, ast.Expr):
1091 node = node.value
1092 if not isinstance(node, ast.Str):
1093 return (None, None)
1094
1095 if PYPY or PY38_PLUS:
1096 doctest_lineno = node.lineno - 1
1097 else:
1098 # Computed incorrectly if the docstring has backslash
1099 doctest_lineno = node.lineno - node.s.count('\n') - 1
1100
1101 return (node.s, doctest_lineno)
1102
1103 def handleNode(self, node, parent):
1104 if node is None:
1105 return
1106 if self.offset and getattr(node, 'lineno', None) is not None:
1107 node.lineno += self.offset[0]
1108 node.col_offset += self.offset[1]
1109 if self.traceTree:
1110 print(' ' * self.nodeDepth + node.__class__.__name__)
1111 if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
1112 self.isDocstring(node)):
1113 self.futuresAllowed = False
1114 self.nodeDepth += 1
1115 node.depth = self.nodeDepth
1116 node.parent = parent
1117 try:
1118 handler = self.getNodeHandler(node.__class__)
1119 handler(node)
1120 finally:
1121 self.nodeDepth -= 1
1122 if self.traceTree:
1123 print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
1124
1125 _getDoctestExamples = doctest.DocTestParser().get_examples
1126
1127 def handleDoctests(self, node):
1128 try:
1129 if hasattr(node, 'docstring'):
1130 docstring = node.docstring
1131
1132 # This is just a reasonable guess. In Python 3.7, docstrings no
1133 # longer have line numbers associated with them. This will be
1134 # incorrect if there are empty lines between the beginning
1135 # of the function and the docstring.
1136 node_lineno = node.lineno
1137 if hasattr(node, 'args'):
1138 node_lineno = max([node_lineno] +
1139 [arg.lineno for arg in node.args.args])
1140 else:
1141 (docstring, node_lineno) = self.getDocstring(node.body[0])
1142 examples = docstring and self._getDoctestExamples(docstring)
1143 except (ValueError, IndexError):
1144 # e.g. line 6 of the docstring for <string> has inconsistent
1145 # leading whitespace: ...
1146 return
1147 if not examples:
1148 return
1149
1150 # Place doctest in module scope
1151 saved_stack = self.scopeStack
1152 self.scopeStack = [self.scopeStack[0]]
1153 node_offset = self.offset or (0, 0)
1154 self.pushScope(DoctestScope)
1155 self.addBinding(None, Builtin('_'))
1156 for example in examples:
1157 try:
1158 tree = ast.parse(example.source, "<doctest>")
1159 except SyntaxError:
1160 e = sys.exc_info()[1]
1161 if PYPY:
1162 e.offset += 1
1163 position = (node_lineno + example.lineno + e.lineno,
1164 example.indent + 4 + (e.offset or 0))
1165 self.report(messages.DoctestSyntaxError, node, position)
1166 else:
1167 self.offset = (node_offset[0] + node_lineno + example.lineno,
1168 node_offset[1] + example.indent + 4)
1169 self.handleChildren(tree)
1170 self.offset = node_offset
1171 self.popScope()
1172 self.scopeStack = saved_stack
1173
1174 def handleStringAnnotation(self, s, node, ref_lineno, ref_col_offset, err):
1175 try:
1176 tree = ast.parse(s)
1177 except SyntaxError:
1178 self.report(err, node, s)
1179 return
1180
1181 body = tree.body
1182 if len(body) != 1 or not isinstance(body[0], ast.Expr):
1183 self.report(err, node, s)
1184 return
1185
1186 parsed_annotation = tree.body[0].value
1187 for descendant in ast.walk(parsed_annotation):
1188 if (
1189 'lineno' in descendant._attributes and
1190 'col_offset' in descendant._attributes
1191 ):
1192 descendant.lineno = ref_lineno
1193 descendant.col_offset = ref_col_offset
1194
1195 self.handleNode(parsed_annotation, node)
1196
1197 def handleAnnotation(self, annotation, node):
1198 if isinstance(annotation, ast.Str):
1199 # Defer handling forward annotation.
1200 self.deferFunction(functools.partial(
1201 self.handleStringAnnotation,
1202 annotation.s,
1203 node,
1204 annotation.lineno,
1205 annotation.col_offset,
1206 messages.ForwardAnnotationSyntaxError,
1207 ))
1208 elif self.annotationsFutureEnabled:
1209 self.deferFunction(lambda: self.handleNode(annotation, node))
1210 else:
1211 self.handleNode(annotation, node)
1212
1213 def ignore(self, node):
1214 pass
1215
1216 # "stmt" type nodes
1217 DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
1218 ASYNCWITH = ASYNCWITHITEM = TRYFINALLY = EXEC = \
1219 EXPR = ASSIGN = handleChildren
1220
1221 PASS = ignore
1222
1223 # "expr" type nodes
1224 BOOLOP = BINOP = UNARYOP = IFEXP = SET = \
1225 CALL = REPR = ATTRIBUTE = SUBSCRIPT = \
1226 STARRED = NAMECONSTANT = handleChildren
1227
1228 NUM = STR = BYTES = ELLIPSIS = CONSTANT = ignore
1229
1230 # "slice" type nodes
1231 SLICE = EXTSLICE = INDEX = handleChildren
1232
1233 # expression contexts are node instances too, though being constants
1234 LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore
1235
1236 # same for operators
1237 AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
1238 BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
1239 EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = \
1240 MATMULT = ignore
1241
1242 def RAISE(self, node):
1243 self.handleChildren(node)
1244
1245 arg = get_raise_argument(node)
1246
1247 if isinstance(arg, ast.Call):
1248 if is_notimplemented_name_node(arg.func):
1249 # Handle "raise NotImplemented(...)"
1250 self.report(messages.RaiseNotImplemented, node)
1251 elif is_notimplemented_name_node(arg):
1252 # Handle "raise NotImplemented"
1253 self.report(messages.RaiseNotImplemented, node)
1254
1255 # additional node types
1256 COMPREHENSION = KEYWORD = FORMATTEDVALUE = JOINEDSTR = handleChildren
1257
1258 def DICT(self, node):
1259 # Complain if there are duplicate keys with different values
1260 # If they have the same value it's not going to cause potentially
1261 # unexpected behaviour so we'll not complain.
1262 keys = [
1263 convert_to_value(key) for key in node.keys
1264 ]
1265
1266 key_counts = counter(keys)
1267 duplicate_keys = [
1268 key for key, count in key_counts.items()
1269 if count > 1
1270 ]
1271
1272 for key in duplicate_keys:
1273 key_indices = [i for i, i_key in enumerate(keys) if i_key == key]
1274
1275 values = counter(
1276 convert_to_value(node.values[index])
1277 for index in key_indices
1278 )
1279 if any(count == 1 for value, count in values.items()):
1280 for key_index in key_indices:
1281 key_node = node.keys[key_index]
1282 if isinstance(key, VariableKey):
1283 self.report(messages.MultiValueRepeatedKeyVariable,
1284 key_node,
1285 key.name)
1286 else:
1287 self.report(
1288 messages.MultiValueRepeatedKeyLiteral,
1289 key_node,
1290 key,
1291 )
1292 self.handleChildren(node)
1293
1294 def ASSERT(self, node):
1295 if isinstance(node.test, ast.Tuple) and node.test.elts != []:
1296 self.report(messages.AssertTuple, node)
1297 self.handleChildren(node)
1298
1299 def GLOBAL(self, node):
1300 """
1301 Keep track of globals declarations.
1302 """
1303 global_scope_index = 1 if self._in_doctest() else 0
1304 global_scope = self.scopeStack[global_scope_index]
1305
1306 # Ignore 'global' statement in global scope.
1307 if self.scope is not global_scope:
1308
1309 # One 'global' statement can bind multiple (comma-delimited) names.
1310 for node_name in node.names:
1311 node_value = Assignment(node_name, node)
1312
1313 # Remove UndefinedName messages already reported for this name.
1314 # TO DO: if the global is not used in this scope, it does not
1315 # become a globally defined name. See test_unused_global.
1316 self.messages = [
1317 m for m in self.messages if not
1318 isinstance(m, messages.UndefinedName) or
1319 m.message_args[0] != node_name]
1320
1321 # Bind name to global scope if it doesn't exist already.
1322 global_scope.setdefault(node_name, node_value)
1323
1324 # Bind name to non-global scopes, but as already "used".
1325 node_value.used = (global_scope, node)
1326 for scope in self.scopeStack[global_scope_index + 1:]:
1327 scope[node_name] = node_value
1328
1329 NONLOCAL = GLOBAL
1330
1331 def GENERATOREXP(self, node):
1332 self.pushScope(GeneratorScope)
1333 self.handleChildren(node)
1334 self.popScope()
1335
1336 LISTCOMP = handleChildren if PY2 else GENERATOREXP
1337
1338 DICTCOMP = SETCOMP = GENERATOREXP
1339
1340 def NAME(self, node):
1341 """
1342 Handle occurrence of Name (which can be a load/store/delete access.)
1343 """
1344 # Locate the name in locals / function / globals scopes.
1345 if isinstance(node.ctx, (ast.Load, ast.AugLoad)):
1346 self.handleNodeLoad(node)
1347 if (node.id == 'locals' and isinstance(self.scope, FunctionScope) and
1348 isinstance(node.parent, ast.Call)):
1349 # we are doing locals() call in current scope
1350 self.scope.usesLocals = True
1351 elif isinstance(node.ctx, (ast.Store, ast.AugStore, ast.Param)):
1352 self.handleNodeStore(node)
1353 elif isinstance(node.ctx, ast.Del):
1354 self.handleNodeDelete(node)
1355 else:
1356 # Unknown context
1357 raise RuntimeError("Got impossible expression context: %r" % (node.ctx,))
1358
1359 def CONTINUE(self, node):
1360 # Walk the tree up until we see a loop (OK), a function or class
1361 # definition (not OK), for 'continue', a finally block (not OK), or
1362 # the top module scope (not OK)
1363 n = node
1364 while hasattr(n, 'parent'):
1365 n, n_child = n.parent, n
1366 if isinstance(n, LOOP_TYPES):
1367 # Doesn't apply unless it's in the loop itself
1368 if n_child not in n.orelse:
1369 return
1370 if isinstance(n, (ast.FunctionDef, ast.ClassDef)):
1371 break
1372 # Handle Try/TryFinally difference in Python < and >= 3.3
1373 if hasattr(n, 'finalbody') and isinstance(node, ast.Continue):
1374 if n_child in n.finalbody:
1375 self.report(messages.ContinueInFinally, node)
1376 return
1377 if isinstance(node, ast.Continue):
1378 self.report(messages.ContinueOutsideLoop, node)
1379 else: # ast.Break
1380 self.report(messages.BreakOutsideLoop, node)
1381
1382 BREAK = CONTINUE
1383
1384 def RETURN(self, node):
1385 if isinstance(self.scope, (ClassScope, ModuleScope)):
1386 self.report(messages.ReturnOutsideFunction, node)
1387 return
1388
1389 if (
1390 node.value and
1391 hasattr(self.scope, 'returnValue') and
1392 not self.scope.returnValue
1393 ):
1394 self.scope.returnValue = node.value
1395 self.handleNode(node.value, node)
1396
1397 def YIELD(self, node):
1398 if isinstance(self.scope, (ClassScope, ModuleScope)):
1399 self.report(messages.YieldOutsideFunction, node)
1400 return
1401
1402 self.scope.isGenerator = True
1403 self.handleNode(node.value, node)
1404
1405 AWAIT = YIELDFROM = YIELD
1406
1407 def FUNCTIONDEF(self, node):
1408 for deco in node.decorator_list:
1409 self.handleNode(deco, node)
1410 self.LAMBDA(node)
1411 self.addBinding(node, FunctionDefinition(node.name, node))
1412 # doctest does not process doctest within a doctest,
1413 # or in nested functions.
1414 if (self.withDoctest and
1415 not self._in_doctest() and
1416 not isinstance(self.scope, FunctionScope)):
1417 self.deferFunction(lambda: self.handleDoctests(node))
1418
1419 ASYNCFUNCTIONDEF = FUNCTIONDEF
1420
1421 def LAMBDA(self, node):
1422 args = []
1423 annotations = []
1424
1425 if PY2:
1426 def addArgs(arglist):
1427 for arg in arglist:
1428 if isinstance(arg, ast.Tuple):
1429 addArgs(arg.elts)
1430 else:
1431 args.append(arg.id)
1432 addArgs(node.args.args)
1433 defaults = node.args.defaults
1434 else:
1435 for arg in node.args.args + node.args.kwonlyargs:
1436 args.append(arg.arg)
1437 annotations.append(arg.annotation)
1438 defaults = node.args.defaults + node.args.kw_defaults
1439
1440 # Only for Python3 FunctionDefs
1441 is_py3_func = hasattr(node, 'returns')
1442
1443 for arg_name in ('vararg', 'kwarg'):
1444 wildcard = getattr(node.args, arg_name)
1445 if not wildcard:
1446 continue
1447 args.append(wildcard if PY2 else wildcard.arg)
1448 if is_py3_func:
1449 if PY2: # Python 2.7
1450 argannotation = arg_name + 'annotation'
1451 annotations.append(getattr(node.args, argannotation))
1452 else: # Python >= 3.4
1453 annotations.append(wildcard.annotation)
1454
1455 if is_py3_func:
1456 annotations.append(node.returns)
1457
1458 if len(set(args)) < len(args):
1459 for (idx, arg) in enumerate(args):
1460 if arg in args[:idx]:
1461 self.report(messages.DuplicateArgument, node, arg)
1462
1463 for annotation in annotations:
1464 self.handleAnnotation(annotation, node)
1465
1466 for default in defaults:
1467 self.handleNode(default, node)
1468
1469 def runFunction():
1470
1471 self.pushScope()
1472
1473 self.handleChildren(node, omit='decorator_list')
1474
1475 def checkUnusedAssignments():
1476 """
1477 Check to see if any assignments have not been used.
1478 """
1479 for name, binding in self.scope.unusedAssignments():
1480 self.report(messages.UnusedVariable, binding.source, name)
1481 self.deferAssignment(checkUnusedAssignments)
1482
1483 if PY2:
1484 def checkReturnWithArgumentInsideGenerator():
1485 """
1486 Check to see if there is any return statement with
1487 arguments but the function is a generator.
1488 """
1489 if self.scope.isGenerator and self.scope.returnValue:
1490 self.report(messages.ReturnWithArgsInsideGenerator,
1491 self.scope.returnValue)
1492 self.deferAssignment(checkReturnWithArgumentInsideGenerator)
1493 self.popScope()
1494
1495 self.deferFunction(runFunction)
1496
1497 def ARGUMENTS(self, node):
1498 self.handleChildren(node, omit=('defaults', 'kw_defaults'))
1499 if PY2:
1500 scope_node = self.getScopeNode(node)
1501 if node.vararg:
1502 self.addBinding(node, Argument(node.vararg, scope_node))
1503 if node.kwarg:
1504 self.addBinding(node, Argument(node.kwarg, scope_node))
1505
1506 def ARG(self, node):
1507 self.addBinding(node, Argument(node.arg, self.getScopeNode(node)))
1508
1509 def CLASSDEF(self, node):
1510 """
1511 Check names used in a class definition, including its decorators, base
1512 classes, and the body of its definition. Additionally, add its name to
1513 the current scope.
1514 """
1515 for deco in node.decorator_list:
1516 self.handleNode(deco, node)
1517 for baseNode in node.bases:
1518 self.handleNode(baseNode, node)
1519 if not PY2:
1520 for keywordNode in node.keywords:
1521 self.handleNode(keywordNode, node)
1522 self.pushScope(ClassScope)
1523 # doctest does not process doctest within a doctest
1524 # classes within classes are processed.
1525 if (self.withDoctest and
1526 not self._in_doctest() and
1527 not isinstance(self.scope, FunctionScope)):
1528 self.deferFunction(lambda: self.handleDoctests(node))
1529 for stmt in node.body:
1530 self.handleNode(stmt, node)
1531 self.popScope()
1532 self.addBinding(node, ClassDefinition(node.name, node))
1533
1534 def AUGASSIGN(self, node):
1535 self.handleNodeLoad(node.target)
1536 self.handleNode(node.value, node)
1537 self.handleNode(node.target, node)
1538
1539 def TUPLE(self, node):
1540 if not PY2 and isinstance(node.ctx, ast.Store):
1541 # Python 3 advanced tuple unpacking: a, *b, c = d.
1542 # Only one starred expression is allowed, and no more than 1<<8
1543 # assignments are allowed before a stared expression. There is
1544 # also a limit of 1<<24 expressions after the starred expression,
1545 # which is impossible to test due to memory restrictions, but we
1546 # add it here anyway
1547 has_starred = False
1548 star_loc = -1
1549 for i, n in enumerate(node.elts):
1550 if isinstance(n, ast.Starred):
1551 if has_starred:
1552 self.report(messages.TwoStarredExpressions, node)
1553 # The SyntaxError doesn't distinguish two from more
1554 # than two.
1555 break
1556 has_starred = True
1557 star_loc = i
1558 if star_loc >= 1 << 8 or len(node.elts) - star_loc - 1 >= 1 << 24:
1559 self.report(messages.TooManyExpressionsInStarredAssignment, node)
1560 self.handleChildren(node)
1561
1562 LIST = TUPLE
1563
1564 def IMPORT(self, node):
1565 for alias in node.names:
1566 if '.' in alias.name and not alias.asname:
1567 importation = SubmoduleImportation(alias.name, node)
1568 else:
1569 name = alias.asname or alias.name
1570 importation = Importation(name, node, alias.name)
1571 self.addBinding(node, importation)
1572
1573 def IMPORTFROM(self, node):
1574 if node.module == '__future__':
1575 if not self.futuresAllowed:
1576 self.report(messages.LateFutureImport,
1577 node, [n.name for n in node.names])
1578 else:
1579 self.futuresAllowed = False
1580
1581 module = ('.' * node.level) + (node.module or '')
1582
1583 for alias in node.names:
1584 name = alias.asname or alias.name
1585 if node.module == '__future__':
1586 importation = FutureImportation(name, node, self.scope)
1587 if alias.name not in __future__.all_feature_names:
1588 self.report(messages.FutureFeatureNotDefined,
1589 node, alias.name)
1590 if alias.name == 'annotations':
1591 self.annotationsFutureEnabled = True
1592 elif alias.name == '*':
1593 # Only Python 2, local import * is a SyntaxWarning
1594 if not PY2 and not isinstance(self.scope, ModuleScope):
1595 self.report(messages.ImportStarNotPermitted,
1596 node, module)
1597 continue
1598
1599 self.scope.importStarred = True
1600 self.report(messages.ImportStarUsed, node, module)
1601 importation = StarImportation(module, node)
1602 else:
1603 importation = ImportationFrom(name, node,
1604 module, alias.name)
1605 self.addBinding(node, importation)
1606
1607 def TRY(self, node):
1608 handler_names = []
1609 # List the exception handlers
1610 for i, handler in enumerate(node.handlers):
1611 if isinstance(handler.type, ast.Tuple):
1612 for exc_type in handler.type.elts:
1613 handler_names.append(getNodeName(exc_type))
1614 elif handler.type:
1615 handler_names.append(getNodeName(handler.type))
1616
1617 if handler.type is None and i < len(node.handlers) - 1:
1618 self.report(messages.DefaultExceptNotLast, handler)
1619 # Memorize the except handlers and process the body
1620 self.exceptHandlers.append(handler_names)
1621 for child in node.body:
1622 self.handleNode(child, node)
1623 self.exceptHandlers.pop()
1624 # Process the other nodes: "except:", "else:", "finally:"
1625 self.handleChildren(node, omit='body')
1626
1627 TRYEXCEPT = TRY
1628
1629 def EXCEPTHANDLER(self, node):
1630 if PY2 or node.name is None:
1631 self.handleChildren(node)
1632 return
1633
1634 # If the name already exists in the scope, modify state of existing
1635 # binding.
1636 if node.name in self.scope:
1637 self.handleNodeStore(node)
1638
1639 # 3.x: the name of the exception, which is not a Name node, but a
1640 # simple string, creates a local that is only bound within the scope of
1641 # the except: block. As such, temporarily remove the existing binding
1642 # to more accurately determine if the name is used in the except:
1643 # block.
1644
1645 try:
1646 prev_definition = self.scope.pop(node.name)
1647 except KeyError:
1648 prev_definition = None
1649
1650 self.handleNodeStore(node)
1651 self.handleChildren(node)
1652
1653 # See discussion on https://github.com/PyCQA/pyflakes/pull/59
1654
1655 # We're removing the local name since it's being unbound after leaving
1656 # the except: block and it's always unbound if the except: block is
1657 # never entered. This will cause an "undefined name" error raised if
1658 # the checked code tries to use the name afterwards.
1659 #
1660 # Unless it's been removed already. Then do nothing.
1661
1662 try:
1663 binding = self.scope.pop(node.name)
1664 except KeyError:
1665 pass
1666 else:
1667 if not binding.used:
1668 self.report(messages.UnusedVariable, node, node.name)
1669
1670 # Restore.
1671 if prev_definition:
1672 self.scope[node.name] = prev_definition
1673
1674 def ANNASSIGN(self, node):
1675 if node.value:
1676 # Only bind the *targets* if the assignment has a value.
1677 # Otherwise it's not really ast.Store and shouldn't silence
1678 # UndefinedLocal warnings.
1679 self.handleNode(node.target, node)
1680 self.handleAnnotation(node.annotation, node)
1681 if node.value:
1682 # If the assignment has value, handle the *value* now.
1683 self.handleNode(node.value, node)
1684
1685 def COMPARE(self, node):
1686 literals = (ast.Str, ast.Num)
1687 if not PY2:
1688 literals += (ast.Bytes,)
1689
1690 left = node.left
1691 for op, right in zip(node.ops, node.comparators):
1692 if (isinstance(op, (ast.Is, ast.IsNot)) and
1693 (isinstance(left, literals) or isinstance(right, literals))):
1694 self.report(messages.IsLiteral, node)
1695 left = right
1696
1697 self.handleChildren(node)
1698
1699
1700 #
1701 # eflag: noqa = M702

eric ide

mercurial