@@ -147,6 +147,18 @@ def redefines(self, other):
147147 return isinstance (other , Definition ) and self .name == other .name
148148
149149
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+
150162class Argument (Binding ):
151163 """
152164 Represents binding a name as an argument.
@@ -243,11 +255,12 @@ class GeneratorScope(Scope):
243255
244256
245257class ModuleScope (Scope ):
246- pass
258+ """Scope for a module."""
259+ _futures_allowed = True
247260
248261
249262class DoctestScope (ModuleScope ):
250- pass
263+ """Scope for a doctest."""
251264
252265
253266# Globally defined names which are not attributes of the builtins module, or
@@ -299,7 +312,6 @@ def __init__(self, tree, filename='(none)', builtins=None,
299312 self .withDoctest = withDoctest
300313 self .scopeStack = [ModuleScope ()]
301314 self .exceptHandlers = [()]
302- self .futuresAllowed = True
303315 self .root = tree
304316 self .handleChildren (tree )
305317 self .runDeferred (self ._deferredFunctions )
@@ -616,9 +628,13 @@ def handleNode(self, node, parent):
616628 node .col_offset += self .offset [1 ]
617629 if self .traceTree :
618630 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+
622638 self .nodeDepth += 1
623639 node .depth = self .nodeDepth
624640 node .parent = parent
@@ -964,14 +980,27 @@ def IMPORT(self, node):
964980
965981 def IMPORTFROM (self , node ):
966982 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
968995 self .report (messages .LateFutureImport ,
969996 node , [n .name for n in node .names ])
970- else :
971- self .futuresAllowed = False
997+ return
972998
973999 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 == '*' :
9751004 # Only Python 2, local import * is a SyntaxWarning
9761005 if not PY2 and not isinstance (self .scope , ModuleScope ):
9771006 self .report (messages .ImportStarNotPermitted ,
@@ -980,10 +1009,8 @@ def IMPORTFROM(self, node):
9801009 self .scope .importStarred = True
9811010 self .report (messages .ImportStarUsed , node , node .module )
9821011 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 )
9871014 self .addBinding (node , importation )
9881015
9891016 def TRY (self , node ):
0 commit comments