@@ -262,10 +262,11 @@ class Binding:
262
262
the node that this binding was last used.
263
263
"""
264
264
265
- def __init__ (self , name , source ):
265
+ def __init__ (self , name , source , * , assigned = True ):
266
266
self .name = name
267
267
self .source = source
268
268
self .used = False
269
+ self .assigned = assigned
269
270
270
271
def __str__ (self ):
271
272
return self .name
@@ -1073,6 +1074,12 @@ def addBinding(self, node, value):
1073
1074
break
1074
1075
existing = scope .get (value .name )
1075
1076
1077
+ global_scope = self .scopeStack [- 1 ]
1078
+ if (existing and global_scope .get (value .name ) == existing and
1079
+ not existing .assigned ):
1080
+ # make sure the variable is in the global scope before setting as assigned
1081
+ existing .assigned = True
1082
+
1076
1083
if (existing and not isinstance (existing , Builtin ) and
1077
1084
not self .differentForks (node , existing .source )):
1078
1085
@@ -1155,6 +1162,10 @@ def handleNodeLoad(self, node):
1155
1162
continue
1156
1163
1157
1164
binding = scope .get (name , None )
1165
+
1166
+ if getattr (binding , 'assigned' , None ) is False :
1167
+ self .report (messages .UndefinedName , node , name )
1168
+
1158
1169
if isinstance (binding , Annotation ) and not self ._in_postponed_annotation :
1159
1170
continue
1160
1171
@@ -1224,12 +1235,19 @@ def handleNodeStore(self, node):
1224
1235
continue
1225
1236
# if the name was defined in that scope, and the name has
1226
1237
# been accessed already in the current scope, and hasn't
1227
- # been declared global
1238
+ # been assigned globally
1228
1239
used = name in scope and scope [name ].used
1229
1240
if used and used [0 ] is self .scope and name not in self .scope .globals :
1230
1241
# then it's probably a mistake
1231
1242
self .report (messages .UndefinedLocal ,
1232
1243
scope [name ].used [1 ], name , scope [name ].source )
1244
+
1245
+ # and remove UndefinedName messages already reported for this name
1246
+ self .messages = [
1247
+ m for m in self .messages if not
1248
+ isinstance (m , messages .UndefinedName ) or
1249
+ m .message_args [0 ] != name ]
1250
+
1233
1251
break
1234
1252
1235
1253
parent_stmt = self .getParent (node )
@@ -1933,11 +1951,9 @@ def GLOBAL(self, node):
1933
1951
1934
1952
# One 'global' statement can bind multiple (comma-delimited) names.
1935
1953
for node_name in node .names :
1936
- node_value = Assignment (node_name , node )
1954
+ node_value = Assignment (node_name , node , assigned = False )
1937
1955
1938
1956
# Remove UndefinedName messages already reported for this name.
1939
- # TODO: if the global is not used in this scope, it does not
1940
- # become a globally defined name. See test_unused_global.
1941
1957
self .messages = [
1942
1958
m for m in self .messages if not
1943
1959
isinstance (m , messages .UndefinedName ) or
0 commit comments