this repo has no description
1# Portions copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2# pyre-unsafe
3"""Parser for future statements
4
5"""
6from __future__ import print_function
7
8import ast
9
10from .visitor import ASTVisitor, walk
11
12
13def is_future(stmt):
14 """Return true if statement is a well-formed future statement"""
15 if not isinstance(stmt, ast.ImportFrom):
16 return 0
17 if stmt.module == "__future__":
18 return 1
19 else:
20 return 0
21
22
23class FutureParser(ASTVisitor):
24
25 features = (
26 "nested_scopes",
27 "generators",
28 "division",
29 "absolute_import",
30 "with_statement",
31 "print_function",
32 "unicode_literals",
33 "generator_stop",
34 "barry_as_FLUFL",
35 "annotations",
36 )
37
38 def __init__(self):
39 super().__init__()
40 self.found = {} # set
41
42 def visitModule(self, node):
43 for s in node.body:
44 if isinstance(s, ast.Expr) and isinstance(s.value, ast.Str):
45 continue
46 if not self.check_stmt(s):
47 break
48
49 def check_stmt(self, stmt):
50 if is_future(stmt):
51 for alias in stmt.names:
52 name = alias.name
53 if name in self.features:
54 self.found[name] = 1
55 elif name == "braces":
56 raise SyntaxError("not a chance")
57 else:
58 raise SyntaxError("future feature %s is not defined" % name)
59 stmt.valid_future = 1
60 return 1
61 return 0
62
63 def get_features(self):
64 """Return list of features enabled by future statements"""
65 return self.found.keys()
66
67
68class BadFutureParser(ASTVisitor):
69 """Check for invalid future statements"""
70
71 def visitImportFrom(self, node):
72 if hasattr(node, "valid_future"):
73 return
74 if node.module != "__future__":
75 return
76 raise SyntaxError(
77 "from __future__ imports must occur at the beginning of the file"
78 )
79
80
81def find_futures(node):
82 p1 = FutureParser()
83 p2 = BadFutureParser()
84 walk(node, p1)
85 walk(node, p2)
86 return p1.get_features()