@@ -435,6 +435,7 @@ def __init__(self):
435
435
super (FunctionScope , self ).__init__ ()
436
436
# Simplify: manage the special locals as globals
437
437
self .globals = self .alwaysUsed .copy ()
438
+ self .global_names = []
438
439
self .returnValue = None # First non-empty return
439
440
self .isGenerator = False # Detect a generator
440
441
@@ -1016,6 +1017,15 @@ def handleForwardAnnotation():
1016
1017
def ignore (self , node ):
1017
1018
pass
1018
1019
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
+
1019
1029
# "stmt" type nodes
1020
1030
DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
1021
1031
ASYNCWITH = ASYNCWITHITEM = TRYFINALLY = EXEC = \
@@ -1122,7 +1132,8 @@ def GLOBAL(self, node):
1122
1132
m .message_args [0 ] != node_name ]
1123
1133
1124
1134
# 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 )
1126
1137
1127
1138
# Bind name to non-global scopes, but as already "used".
1128
1139
node_value .used = (global_scope , node )
@@ -1144,17 +1155,33 @@ def NAME(self, node):
1144
1155
"""
1145
1156
Handle occurrence of Name (which can be a load/store/delete access.)
1146
1157
"""
1158
+ global_scope_index = 1 if self ._in_doctest () else 0
1159
+ global_scope = self .scopeStack [global_scope_index ]
1147
1160
# Locate the name in locals / function / globals scopes.
1148
1161
if isinstance (node .ctx , (ast .Load , ast .AugLoad )):
1149
1162
self .handleNodeLoad (node )
1150
1163
if (node .id == 'locals' and isinstance (self .scope , FunctionScope )
1151
1164
and isinstance (node .parent , ast .Call )):
1152
1165
# we are doing locals() call in current scope
1153
1166
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 )
1154
1171
elif isinstance (node .ctx , (ast .Store , ast .AugStore , ast .Param )):
1155
1172
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 ))
1156
1176
elif isinstance (node .ctx , ast .Del ):
1157
1177
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 )
1158
1185
else :
1159
1186
# Unknown context
1160
1187
raise RuntimeError ("Got impossible expression context: %r" % (node .ctx ,))
@@ -1366,13 +1393,16 @@ def TUPLE(self, node):
1366
1393
1367
1394
def IMPORT (self , node ):
1368
1395
for alias in node .names :
1396
+ name = alias .name
1369
1397
if '.' in alias .name and not alias .asname :
1370
- importation = SubmoduleImportation (alias . name , node )
1398
+ importation = SubmoduleImportation (name , node )
1371
1399
else :
1372
1400
name = alias .asname or alias .name
1373
1401
importation = Importation (name , node , alias .name )
1374
1402
self .addBinding (node , importation )
1375
1403
1404
+ self .store_global_scope (name , alias )
1405
+
1376
1406
def IMPORTFROM (self , node ):
1377
1407
if node .module == '__future__' :
1378
1408
if not self .futuresAllowed :
@@ -1405,6 +1435,8 @@ def IMPORTFROM(self, node):
1405
1435
module , alias .name )
1406
1436
self .addBinding (node , importation )
1407
1437
1438
+ self .store_global_scope (name , alias )
1439
+
1408
1440
def TRY (self , node ):
1409
1441
handler_names = []
1410
1442
# List the exception handlers
0 commit comments