@@ -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,26 @@ def IMPORT(self, node):
964980
965981 def IMPORTFROM (self , node ):
966982 if node .module == '__future__' :
967- if not self .futuresAllowed :
983+ # the scope can not have any other type of binding
984+ has_other_import_from = any (
985+ not isinstance (binding , FutureImportation )
986+ for binding in self .scope .values ())
987+
988+ # __future__ can only appear at top of each module/doctest scope
989+ # handleNode disables _futures_allowed for any other type
990+ if (not isinstance (self .scope , ModuleScope ) or
991+ not self .scope ._futures_allowed
992+ or has_other_import_from ):
993+ self .scope ._futures_allowed = False
968994 self .report (messages .LateFutureImport ,
969995 node , [n .name for n in node .names ])
970- else :
971- self .futuresAllowed = False
996+ return
972997
973998 for alias in node .names :
974- if alias .name == '*' :
999+ name = alias .asname or alias .name
1000+ if node .module == '__future__' :
1001+ importation = FutureImportation (name , node , self .scope )
1002+ elif alias .name == '*' :
9751003 # Only Python 2, local import * is a SyntaxWarning
9761004 if not PY2 and not isinstance (self .scope , ModuleScope ):
9771005 self .report (messages .ImportStarNotPermitted ,
@@ -980,10 +1008,8 @@ def IMPORTFROM(self, node):
9801008 self .scope .importStarred = True
9811009 self .report (messages .ImportStarUsed , node , node .module )
9821010 continue
983- name = alias .asname or alias .name
984- importation = Importation (name , node )
985- if node .module == '__future__' :
986- importation .used = (self .scope , node )
1011+ else :
1012+ importation = Importation (name , node )
9871013 self .addBinding (node , importation )
9881014
9891015 def TRY (self , node ):
0 commit comments