@@ -147,6 +147,18 @@ def redefines(self, other):
147
147
return isinstance (other , Definition ) and self .name == other .name
148
148
149
149
150
+ class FutureImportation (Importation ):
151
+ """
152
+ A binding created by a from `__future__` import statement.
153
+
154
+ `__future__` imports are implicitly used.
155
+ """
156
+
157
+ def __init__ (self , name , source , scope ):
158
+ super (FutureImportation , self ).__init__ (name , source )
159
+ self .used = (scope , source )
160
+
161
+
150
162
class Argument (Binding ):
151
163
"""
152
164
Represents binding a name as an argument.
@@ -243,11 +255,12 @@ class GeneratorScope(Scope):
243
255
244
256
245
257
class ModuleScope (Scope ):
246
- pass
258
+ """Scope for a module."""
259
+ _futures_allowed = True
247
260
248
261
249
262
class DoctestScope (ModuleScope ):
250
- pass
263
+ """Scope for a doctest."""
251
264
252
265
253
266
# Globally defined names which are not attributes of the builtins module, or
@@ -299,7 +312,6 @@ def __init__(self, tree, filename='(none)', builtins=None,
299
312
self .withDoctest = withDoctest
300
313
self .scopeStack = [ModuleScope ()]
301
314
self .exceptHandlers = [()]
302
- self .futuresAllowed = True
303
315
self .root = tree
304
316
self .handleChildren (tree )
305
317
self .runDeferred (self ._deferredFunctions )
@@ -616,9 +628,13 @@ def handleNode(self, node, parent):
616
628
node .col_offset += self .offset [1 ]
617
629
if self .traceTree :
618
630
print (' ' * self .nodeDepth + node .__class__ .__name__ )
619
- if self .futuresAllowed and not (isinstance (node , ast .ImportFrom ) or
620
- self .isDocstring (node )):
621
- self .futuresAllowed = False
631
+
632
+ if (isinstance (self .scope , ModuleScope ) and
633
+ self .scope ._futures_allowed and
634
+ not (isinstance (node , ast .ImportFrom ) or
635
+ self .isDocstring (node ))):
636
+ self .scope ._futures_allowed = False
637
+
622
638
self .nodeDepth += 1
623
639
node .depth = self .nodeDepth
624
640
node .parent = parent
@@ -964,14 +980,27 @@ def IMPORT(self, node):
964
980
965
981
def IMPORTFROM (self , node ):
966
982
if node .module == '__future__' :
967
- if not self .futuresAllowed :
983
+ def has_only_future_imports ():
984
+ """Return False if any other type of binding exists."""
985
+ return all (
986
+ isinstance (binding , FutureImportation )
987
+ for binding in self .scope .values ())
988
+
989
+ # scope._futures_allowed may have been disabled in handleNode,
990
+ # and the scope can only have __future__ bindings
991
+ if (not isinstance (self .scope , ModuleScope ) or
992
+ not self .scope ._futures_allowed or
993
+ not has_only_future_imports ()):
994
+ self .scope ._futures_allowed = False
968
995
self .report (messages .LateFutureImport ,
969
996
node , [n .name for n in node .names ])
970
- else :
971
- self .futuresAllowed = False
997
+ return
972
998
973
999
for alias in node .names :
974
- if alias .name == '*' :
1000
+ name = alias .asname or alias .name
1001
+ if node .module == '__future__' :
1002
+ importation = FutureImportation (name , node , self .scope )
1003
+ elif alias .name == '*' :
975
1004
# Only Python 2, local import * is a SyntaxWarning
976
1005
if not PY2 and not isinstance (self .scope , ModuleScope ):
977
1006
self .report (messages .ImportStarNotPermitted ,
@@ -980,10 +1009,8 @@ def IMPORTFROM(self, node):
980
1009
self .scope .importStarred = True
981
1010
self .report (messages .ImportStarUsed , node , node .module )
982
1011
continue
983
- name = alias .asname or alias .name
984
- importation = Importation (name , node )
985
- if node .module == '__future__' :
986
- importation .used = (self .scope , node )
1012
+ else :
1013
+ importation = Importation (name , node )
987
1014
self .addBinding (node , importation )
988
1015
989
1016
def TRY (self , node ):
0 commit comments