180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton"""Parser for future statements 280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton""" 480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltonfrom compiler import ast, walk 680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltondef is_future(stmt): 880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton """Return true if statement is a well-formed future statement""" 980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if not isinstance(stmt, ast.From): 1080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 0 1180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if stmt.modname == "__future__": 1280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 1 1380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton else: 1480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 0 1580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 1680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltonclass FutureParser: 1780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 1834aa7ba11431a46e72ec30ee7528f2e52adbed7fThomas Wouters features = ("nested_scopes", "generators", "division", 19311d071541ba1fd8615ecf604026e96d547c1d80Neal Norwitz "absolute_import", "with_statement", "print_function", 20311d071541ba1fd8615ecf604026e96d547c1d80Neal Norwitz "unicode_literals") 21e0c446bb4ad67294f42d4cb53b4ff28413bd8ddeTim Peters 2280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton def __init__(self): 2380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton self.found = {} # set 2480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 2580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton def visitModule(self, node): 2680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton stmt = node.node 27ec5bfd13cada33ed36f93fd76b1355ce9ee2710fJeremy Hylton for s in stmt.nodes: 2880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if not self.check_stmt(s): 2980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton break 3080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 3180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton def check_stmt(self, stmt): 3280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if is_future(stmt): 3380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton for name, asname in stmt.names: 3480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if name in self.features: 3580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton self.found[name] = 1 3680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton else: 3780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton raise SyntaxError, \ 3880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton "future feature %s is not defined" % name 3980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton stmt.valid_future = 1 4080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 1 4180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 0 4280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 4380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton def get_features(self): 4480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton """Return list of features enabled by future statements""" 4580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return self.found.keys() 4680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 4780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltonclass BadFutureParser: 4880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton """Check for invalid future statements""" 4980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 5080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton def visitFrom(self, node): 5180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if hasattr(node, 'valid_future'): 5280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 5380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton if node.modname != "__future__": 5480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return 55415ed937c21f0d563fb11a20189831b908673462Martin v. Löwis raise SyntaxError, "invalid future statement " + repr(node) 5680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 5780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltondef find_futures(node): 5880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton p1 = FutureParser() 5980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton p2 = BadFutureParser() 6080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton walk(node, p1) 6180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton walk(node, p2) 6280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton return p1.get_features() 6380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 6480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hyltonif __name__ == "__main__": 6580e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton import sys 6680e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton from compiler import parseFile, walk 6780e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton 6880e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton for file in sys.argv[1:]: 6980e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton print file 7080e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton tree = parseFile(file) 7180e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton v = FutureParser() 7280e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton walk(tree, v) 7380e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton print v.found 7480e29bd1392bfae865f2ff44b1fe92a5d0fad7c8Jeremy Hylton print 75