Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py

changeset 4502
76f2b46437a6
parent 4465
2fbb5bdb8ddf
child 4555
861e1741985c
diff -r 3224f20d8eb0 -r 76f2b46437a6 Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py
--- a/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py	Tue Oct 20 19:14:55 2015 +0200
+++ b/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py	Tue Oct 20 19:19:12 2015 +0200
@@ -455,6 +455,10 @@
             elif isinstance(existing, Importation) and value.redefines(existing):
                 existing.redefined.append(node)
 
+        if value.name in self.scope:
+            # then assume the rebound name is used as a global or within a loop
+            value.used = self.scope[value.name].used
+
         self.scope[value.name] = value
 
     def getNodeHandler(self, node_class):
@@ -478,7 +482,7 @@
             return
 
         scopes = [scope for scope in self.scopeStack[:-1]
-                  if isinstance(scope, (FunctionScope, ModuleScope))]
+                  if isinstance(scope, (FunctionScope, ModuleScope, GeneratorScope))]
         if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:
             scopes.append(self.scopeStack[-2])
 
@@ -533,14 +537,30 @@
             binding = ExportBinding(name, node.parent, self.scope)
         else:
             binding = Assignment(name, node)
-        if name in self.scope:
-            binding.used = self.scope[name].used
         self.addBinding(node, binding)
 
     def handleNodeDelete(self, node):
+
+        def on_conditional_branch():
+            """
+            Return `True` if node is part of a conditional body.
+            """
+            current = getattr(node, 'parent', None)
+            while current:
+                if isinstance(current, (ast.If, ast.While, ast.IfExp)):
+                    return True
+                current = getattr(current, 'parent', None)
+            return False
+
         name = getNodeName(node)
         if not name:
             return
+
+        if on_conditional_branch():
+            # We can not predict if this conditional branch is going to
+            # be executed.
+            return
+
         if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
             self.scope.globals.remove(name)
         else:
@@ -638,8 +658,8 @@
 
     # "stmt" type nodes
     DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
-        ASYNCWITH = RAISE = TRYFINALLY = ASSERT = EXEC = EXPR = \
-        ASSIGN = handleChildren
+        ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = ASSERT = EXEC = \
+        EXPR = ASSIGN = handleChildren
 
     CONTINUE = BREAK = PASS = ignore
 
@@ -662,14 +682,38 @@
         EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
 
     # additional node types
-    LISTCOMP = COMPREHENSION = KEYWORD = handleChildren
+    COMPREHENSION = KEYWORD = handleChildren
 
     def GLOBAL(self, node):
         """
         Keep track of globals declarations.
         """
-        if isinstance(self.scope, FunctionScope):
-            self.scope.globals.update(node.names)
+        # In doctests, the global scope is an anonymous function at index 1.
+        global_scope_index = 0#1 if self.withDoctest else 0
+        global_scope = self.scopeStack[global_scope_index]
+
+        # Ignore 'global' statement in global scope.
+        if self.scope is not global_scope:
+
+            # One 'global' statement can bind multiple (comma-delimited) names.
+            for node_name in node.names:
+                node_value = Assignment(node_name, node)
+
+                # Remove UndefinedName messages already reported for this name.
+                self.messages = [
+                    m for m in self.messages if not
+                    isinstance(m, messages.UndefinedName) and not
+                    m.message_args[0] == node_name]
+
+                # Bind name to global scope if it doesn't exist already.
+                global_scope.setdefault(node_name, node_value)
+
+                # Bind name to non-global scopes, but as already "used".
+                node_value.used = (global_scope, node)
+                for scope in self.scopeStack[global_scope_index + 1:]:
+                    scope[node_name] = node_value
+                    if isinstance(scope, FunctionScope):
+                        scope.globals.add(node_name)
 
     NONLOCAL = GLOBAL
 
@@ -678,6 +722,8 @@
         self.handleChildren(node)
         self.popScope()
 
+    LISTCOMP = handleChildren if PY2 else GENERATOREXP
+
     DICTCOMP = SETCOMP = GENERATOREXP
 
     def NAME(self, node):
@@ -701,6 +747,10 @@
             raise RuntimeError("Got impossible expression context: %r" % (node.ctx,))
 
     def RETURN(self, node):
+        if isinstance(self.scope, ClassScope):
+            self.report(messages.ReturnOutsideFunction, node)
+            return
+
         if (
             node.value and
             hasattr(self.scope, 'returnValue') and
@@ -713,7 +763,7 @@
         self.scope.isGenerator = True
         self.handleNode(node.value, node)
 
-    YIELDFROM = YIELD
+    AWAIT = YIELDFROM = YIELD
 
     def FUNCTIONDEF(self, node):
         for deco in node.decorator_list:

eric ide

mercurial