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