| 1 | """Parser for future statements"""
 | 
| 2 | 
 | 
| 3 | from . import ast
 | 
| 4 | from .visitor import ASTVisitor
 | 
| 5 | 
 | 
| 6 | 
 | 
| 7 | def is_future(stmt):
 | 
| 8 |     """Return true if statement is a well-formed future statement"""
 | 
| 9 |     if not isinstance(stmt, ast.From):
 | 
| 10 |         return 0
 | 
| 11 |     if stmt.modname == "__future__":
 | 
| 12 |         return 1
 | 
| 13 |     else:
 | 
| 14 |         return 0
 | 
| 15 | 
 | 
| 16 | 
 | 
| 17 | class FutureParser(ASTVisitor):
 | 
| 18 | 
 | 
| 19 |     features = ("nested_scopes", "generators", "division",
 | 
| 20 |                 "absolute_import", "with_statement", "print_function",
 | 
| 21 |                 "unicode_literals")
 | 
| 22 | 
 | 
| 23 |     def __init__(self):
 | 
| 24 |         ASTVisitor.__init__(self)
 | 
| 25 |         self.found = {}  # set
 | 
| 26 | 
 | 
| 27 |     def visitModule(self, node):
 | 
| 28 |         stmt = node.node
 | 
| 29 |         for s in stmt.nodes:
 | 
| 30 |             if not self.check_stmt(s):
 | 
| 31 |                 break
 | 
| 32 | 
 | 
| 33 |     def check_stmt(self, stmt):
 | 
| 34 |         if is_future(stmt):
 | 
| 35 |             for name, asname in stmt.names:
 | 
| 36 |                 if name in self.features:
 | 
| 37 |                     self.found[name] = 1
 | 
| 38 |                 else:
 | 
| 39 |                     raise SyntaxError, \
 | 
| 40 |                           "future feature %s is not defined" % name
 | 
| 41 |             stmt.valid_future = 1
 | 
| 42 |             return 1
 | 
| 43 |         return 0
 | 
| 44 | 
 | 
| 45 |     def get_features(self):
 | 
| 46 |         """Return list of features enabled by future statements"""
 | 
| 47 |         return self.found.keys()
 | 
| 48 | 
 | 
| 49 | 
 | 
| 50 | class BadFutureParser(ASTVisitor):
 | 
| 51 |     """Check for invalid future statements"""
 | 
| 52 | 
 | 
| 53 |     def visitFrom(self, node):
 | 
| 54 |         if hasattr(node, 'valid_future'):
 | 
| 55 |             return
 | 
| 56 |         if node.modname != "__future__":
 | 
| 57 |             return
 | 
| 58 |         raise SyntaxError, "invalid future statement " + repr(node)
 |