1313import ast
1414import copy
1515import logging
16+ import textwrap
1617import tokenize as tk
1718from itertools import takewhile , dropwhile , chain
1819from re import compile as re
@@ -486,20 +487,48 @@ def parse_definition(self, class_):
486487 self .current .value )
487488 return definition
488489
490+ def check_current (self , kind = None , value = None ):
491+ msg = textwrap .dedent ("""
492+ Unexpected token at line {self.line}:
493+
494+ In file: {self.filename}
495+
496+ Got kind {self.current.kind!r}
497+ Got value {self.current.value}
498+ """ .format (self = self ))
499+ kind_valid = self .current .kind == kind if kind else True
500+ value_valid = self .current .value == value if value else True
501+ assert kind_valid and value_valid , msg
502+
489503 def parse_from_import_statement (self ):
490504 """Parse a 'from x import y' statement.
491505
492506 The purpose is to find __future__ statements.
493507
494508 """
495509 log .debug ('parsing from/import statement.' )
510+ is_future_import = self ._parse_from_import_source ()
511+ self ._parse_from_import_names (is_future_import )
512+
513+ def _parse_from_import_source (self ):
514+ """Parse the 'from x import' part in a 'from x import y' statement.
515+
516+ Return true iff `x` is __future__.
517+ """
496518 assert self .current .value == 'from' , self .current .value
497519 self .stream .move ()
498- if self .current .value != '__future__' :
499- return
520+ is_future_import = self .current .value == '__future__'
500521 self .stream .move ()
522+ while (self .current .kind in (tk .DOT , tk .NAME , tk .OP ) and
523+ self .current .value != 'import' ):
524+ self .stream .move ()
525+ self .check_current (value = 'import' )
501526 assert self .current .value == 'import' , self .current .value
502527 self .stream .move ()
528+ return is_future_import
529+
530+ def _parse_from_import_names (self , is_future_import ):
531+ """Parse the 'y' part in a 'from x import y' statement."""
503532 if self .current .value == '(' :
504533 self .consume (tk .OP )
505534 expected_end_kind = tk .OP
@@ -512,8 +541,9 @@ def parse_from_import_statement(self):
512541 continue
513542 log .debug ("parsing import, token is %r (%s)" ,
514543 self .current .kind , self .current .value )
515- log .debug ('found future import: %s' , self .current .value )
516- self .future_imports [self .current .value ] = True
544+ if is_future_import :
545+ log .debug ('found future import: %s' , self .current .value )
546+ self .future_imports [self .current .value ] = True
517547 self .consume (tk .NAME )
518548 log .debug ("parsing import, token is %r (%s)" ,
519549 self .current .kind , self .current .value )
0 commit comments