@@ -435,6 +435,7 @@ def __init__(self):
435435 super (FunctionScope , self ).__init__ ()
436436 # Simplify: manage the special locals as globals
437437 self .globals = self .alwaysUsed .copy ()
438+ self .global_names = []
438439 self .returnValue = None # First non-empty return
439440 self .isGenerator = False # Detect a generator
440441
@@ -1016,6 +1017,15 @@ def handleForwardAnnotation():
10161017 def ignore (self , node ):
10171018 pass
10181019
1020+ def store_global_scope (self , name , value ):
1021+ """This store name in global scope if it is in global_names"""
1022+ if isinstance (self .scope , FunctionScope ):
1023+ global_scope_index = 1 if self ._in_doctest () else 0
1024+ global_scope = self .scopeStack [global_scope_index ]
1025+ if name in self .scope .global_names :
1026+ global_scope .setdefault (name ,
1027+ Assignment (name , value ))
1028+
10191029 # "stmt" type nodes
10201030 DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
10211031 ASYNCWITH = ASYNCWITHITEM = TRYFINALLY = EXEC = \
@@ -1122,7 +1132,8 @@ def GLOBAL(self, node):
11221132 m .message_args [0 ] != node_name ]
11231133
11241134 # Bind name to global scope if it doesn't exist already.
1125- global_scope .setdefault (node_name , node_value )
1135+ if isinstance (self .scope , FunctionScope ):
1136+ self .scope .global_names .append (node_name )
11261137
11271138 # Bind name to non-global scopes, but as already "used".
11281139 node_value .used = (global_scope , node )
@@ -1144,17 +1155,33 @@ def NAME(self, node):
11441155 """
11451156 Handle occurrence of Name (which can be a load/store/delete access.)
11461157 """
1158+ global_scope_index = 1 if self ._in_doctest () else 0
1159+ global_scope = self .scopeStack [global_scope_index ]
11471160 # Locate the name in locals / function / globals scopes.
11481161 if isinstance (node .ctx , (ast .Load , ast .AugLoad )):
11491162 self .handleNodeLoad (node )
11501163 if (node .id == 'locals' and isinstance (self .scope , FunctionScope )
11511164 and isinstance (node .parent , ast .Call )):
11521165 # we are doing locals() call in current scope
11531166 self .scope .usesLocals = True
1167+ if (isinstance (self .scope , FunctionScope ) and
1168+ node .id in self .scope .global_names ):
1169+ if node .id not in global_scope :
1170+ self .report (messages .UndefinedName , node , node .id )
11541171 elif isinstance (node .ctx , (ast .Store , ast .AugStore , ast .Param )):
11551172 self .handleNodeStore (node )
1173+ if (isinstance (self .scope , FunctionScope ) and
1174+ node .id in self .scope .global_names ):
1175+ global_scope .setdefault (node .id , Assignment (node .id , node ))
11561176 elif isinstance (node .ctx , ast .Del ):
11571177 self .handleNodeDelete (node )
1178+ if (isinstance (self .scope , FunctionScope ) and
1179+ node .id in self .scope .global_names ):
1180+ if node .id not in global_scope :
1181+ self .report (messages .UndefinedName , node , node .id )
1182+ else :
1183+ global_scope .pop (node .id , None )
1184+ self .scope .global_names .remove (node .id )
11581185 else :
11591186 # Unknown context
11601187 raise RuntimeError ("Got impossible expression context: %r" % (node .ctx ,))
@@ -1366,13 +1393,16 @@ def TUPLE(self, node):
13661393
13671394 def IMPORT (self , node ):
13681395 for alias in node .names :
1396+ name = alias .name
13691397 if '.' in alias .name and not alias .asname :
1370- importation = SubmoduleImportation (alias . name , node )
1398+ importation = SubmoduleImportation (name , node )
13711399 else :
13721400 name = alias .asname or alias .name
13731401 importation = Importation (name , node , alias .name )
13741402 self .addBinding (node , importation )
13751403
1404+ self .store_global_scope (name , alias )
1405+
13761406 def IMPORTFROM (self , node ):
13771407 if node .module == '__future__' :
13781408 if not self .futuresAllowed :
@@ -1405,6 +1435,8 @@ def IMPORTFROM(self, node):
14051435 module , alias .name )
14061436 self .addBinding (node , importation )
14071437
1438+ self .store_global_scope (name , alias )
1439+
14081440 def TRY (self , node ):
14091441 handler_names = []
14101442 # List the exception handlers
0 commit comments