1 """Parser for future statements 2 3 """ 4 5 from compiler import ast, walk 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 class FutureParser: 17 18 features = ("nested_scopes", "generators", "division", 19 "absolute_import", "with_statement", "print_function", 20 "unicode_literals") 21 22 def __init__(self): 23 self.found = {} # set 24 25 def visitModule(self, node): 26 stmt = node.node 27 for s in stmt.nodes: 28 if not self.check_stmt(s): 29 break 30 31 def check_stmt(self, stmt): 32 if is_future(stmt): 33 for name, asname in stmt.names: 34 if name in self.features: 35 self.found[name] = 1 36 else: 37 raise SyntaxError, \ 38 "future feature %s is not defined" % name 39 stmt.valid_future = 1 40 return 1 41 return 0 42 43 def get_features(self): 44 """Return list of features enabled by future statements""" 45 return self.found.keys() 46 47 class BadFutureParser: 48 """Check for invalid future statements""" 49 50 def visitFrom(self, node): 51 if hasattr(node, 'valid_future'): 52 return 53 if node.modname != "__future__": 54 return 55 raise SyntaxError, "invalid future statement " + repr(node) 56 57 def find_futures(node): 58 p1 = FutureParser() 59 p2 = BadFutureParser() 60 walk(node, p1) 61 walk(node, p2) 62 return p1.get_features() 63 64 if __name__ == "__main__": 65 import sys 66 from compiler import parseFile, walk 67 68 for file in sys.argv[1:]: 69 print file 70 tree = parseFile(file) 71 v = FutureParser() 72 walk(tree, v) 73 print v.found 74 print