| """Parser for future statements | 
 |  | 
 | """ | 
 |  | 
 | from compiler import ast, walk | 
 |  | 
 | def is_future(stmt): | 
 |     """Return true if statement is a well-formed future statement""" | 
 |     if not isinstance(stmt, ast.From): | 
 |         return 0 | 
 |     if stmt.modname == "__future__": | 
 |         return 1 | 
 |     else: | 
 |         return 0 | 
 |  | 
 | class FutureParser: | 
 |  | 
 |     features = ("nested_scopes", "generators", "division", | 
 |                 "absolute_import", "with_statement", "print_function", | 
 |                 "unicode_literals") | 
 |  | 
 |     def __init__(self): | 
 |         self.found = {} # set | 
 |  | 
 |     def visitModule(self, node): | 
 |         stmt = node.node | 
 |         for s in stmt.nodes: | 
 |             if not self.check_stmt(s): | 
 |                 break | 
 |  | 
 |     def check_stmt(self, stmt): | 
 |         if is_future(stmt): | 
 |             for name, asname in stmt.names: | 
 |                 if name in self.features: | 
 |                     self.found[name] = 1 | 
 |                 else: | 
 |                     raise SyntaxError, \ | 
 |                           "future feature %s is not defined" % name | 
 |             stmt.valid_future = 1 | 
 |             return 1 | 
 |         return 0 | 
 |  | 
 |     def get_features(self): | 
 |         """Return list of features enabled by future statements""" | 
 |         return self.found.keys() | 
 |  | 
 | class BadFutureParser: | 
 |     """Check for invalid future statements""" | 
 |  | 
 |     def visitFrom(self, node): | 
 |         if hasattr(node, 'valid_future'): | 
 |             return | 
 |         if node.modname != "__future__": | 
 |             return | 
 |         raise SyntaxError, "invalid future statement " + repr(node) | 
 |  | 
 | def find_futures(node): | 
 |     p1 = FutureParser() | 
 |     p2 = BadFutureParser() | 
 |     walk(node, p1) | 
 |     walk(node, p2) | 
 |     return p1.get_features() | 
 |  | 
 | if __name__ == "__main__": | 
 |     import sys | 
 |     from compiler import parseFile, walk | 
 |  | 
 |     for file in sys.argv[1:]: | 
 |         print file | 
 |         tree = parseFile(file) | 
 |         v = FutureParser() | 
 |         walk(tree, v) | 
 |         print v.found | 
 |         print |