blob: fef189e9e91dedbb27b39f7b9a66a5a020c1c339 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001"""Parser for future statements
2
3"""
4
5from compiler import ast, walk
6
7def 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
16class 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
46class 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
56def find_futures(node):
57 p1 = FutureParser()
58 p2 = BadFutureParser()
59 walk(node, p1)
60 walk(node, p2)
61 return p1.get_features()
62
63if __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