@@ -141,6 +141,18 @@ def redefines(self, other):
141
141
return isinstance (other , Definition ) and self .name == other .name
142
142
143
143
144
+ class FutureImportation (Importation ):
145
+ """
146
+ A binding created by a from `__future__` import statement.
147
+
148
+ `__future__` imports are implicitly used.
149
+ """
150
+
151
+ def __init__ (self , name , source , scope ):
152
+ super (FutureImportation , self ).__init__ (name , source )
153
+ self .used = (scope , source )
154
+
155
+
144
156
class Argument (Binding ):
145
157
"""
146
158
Represents binding a name as an argument.
@@ -237,11 +249,12 @@ class GeneratorScope(Scope):
237
249
238
250
239
251
class ModuleScope (Scope ):
240
- pass
252
+ """Scope for a module."""
253
+ _futures_allowed = True
241
254
242
255
243
256
class DoctestScope (ModuleScope ):
244
- pass
257
+ """Scope for a doctest."""
245
258
246
259
247
260
# Globally defined names which are not attributes of the builtins module, or
@@ -293,7 +306,6 @@ def __init__(self, tree, filename='(none)', builtins=None,
293
306
self .withDoctest = withDoctest
294
307
self .scopeStack = [ModuleScope ()]
295
308
self .exceptHandlers = [()]
296
- self .futuresAllowed = True
297
309
self .root = tree
298
310
self .handleChildren (tree )
299
311
self .runDeferred (self ._deferredFunctions )
@@ -606,9 +618,13 @@ def handleNode(self, node, parent):
606
618
node .col_offset += self .offset [1 ]
607
619
if self .traceTree :
608
620
print (' ' * self .nodeDepth + node .__class__ .__name__ )
609
- if self .futuresAllowed and not (isinstance (node , ast .ImportFrom ) or
610
- self .isDocstring (node )):
611
- self .futuresAllowed = False
621
+
622
+ if (isinstance (self .scope , ModuleScope ) and
623
+ self .scope ._futures_allowed and
624
+ not (isinstance (node , ast .ImportFrom ) or
625
+ self .isDocstring (node ))):
626
+ self .scope ._futures_allowed = False
627
+
612
628
self .nodeDepth += 1
613
629
node .depth = self .nodeDepth
614
630
node .parent = parent
@@ -952,21 +968,27 @@ def IMPORT(self, node):
952
968
953
969
def IMPORTFROM (self , node ):
954
970
if node .module == '__future__' :
955
- if not self .futuresAllowed :
971
+ # __future__ can only appear in module/doctest scope and
972
+ # should not have been disabled already in handleNode and
973
+ # the scope must not have any other type of binding.
974
+ if (not isinstance (self .scope , ModuleScope ) or
975
+ not self .scope ._futures_allowed or
976
+ any (not isinstance (binding , FutureImportation )
977
+ for binding in self .scope .values ())):
978
+ self .scope ._futures_allowed = False
956
979
self .report (messages .LateFutureImport ,
957
980
node , [n .name for n in node .names ])
958
- else :
959
- self .futuresAllowed = False
960
981
961
982
for alias in node .names :
962
- if alias .name == '*' :
983
+ name = alias .asname or alias .name
984
+ if node .module == '__future__' :
985
+ importation = FutureImportation (name , node , self .scope )
986
+ elif alias .name == '*' :
963
987
self .scope .importStarred = True
964
988
self .report (messages .ImportStarUsed , node , node .module )
965
989
continue
966
- name = alias .asname or alias .name
967
- importation = Importation (name , node )
968
- if node .module == '__future__' :
969
- importation .used = (self .scope , node )
990
+ else :
991
+ importation = Importation (name , node )
970
992
self .addBinding (node , importation )
971
993
972
994
def TRY (self , node ):
0 commit comments