1 #include "Python.h"
2 #include "pycore_ast.h" // _PyAST_GetDocString()
3
4 #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
5
6 static int
7 future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
8 {
9 int i;
10
11 assert(s->kind == ImportFrom_kind);
12
13 asdl_alias_seq *names = s->v.ImportFrom.names;
14 for (i = 0; i < asdl_seq_LEN(names); i++) {
15 alias_ty name = (alias_ty)asdl_seq_GET(names, i);
16 const char *feature = PyUnicode_AsUTF8(name->name);
17 if (!feature)
18 return 0;
19 if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
20 continue;
21 } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
22 continue;
23 } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
24 continue;
25 } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
26 continue;
27 } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
28 continue;
29 } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
30 continue;
31 } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
32 continue;
33 } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
34 ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
35 } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
36 continue;
37 } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
38 ff->ff_features |= CO_FUTURE_ANNOTATIONS;
39 } else if (strcmp(feature, "braces") == 0) {
40 PyErr_SetString(PyExc_SyntaxError,
41 "not a chance");
42 PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
43 return 0;
44 } else {
45 PyErr_Format(PyExc_SyntaxError,
46 UNDEFINED_FUTURE_FEATURE, feature);
47 PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
48 return 0;
49 }
50 }
51 return 1;
52 }
53
54 static int
55 future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
56 {
57 if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) {
58 return 1;
59 }
60
61 Py_ssize_t n = asdl_seq_LEN(mod->v.Module.body);
62 if (n == 0) {
63 return 1;
64 }
65
66 Py_ssize_t i = 0;
67 if (_PyAST_GetDocString(mod->v.Module.body) != NULL) {
68 i++;
69 }
70
71 for (; i < n; i++) {
72 stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
73
74 /* The only things that can precede a future statement
75 * are another future statement and a doc string.
76 */
77
78 if (s->kind == ImportFrom_kind) {
79 identifier modname = s->v.ImportFrom.module;
80 if (modname &&
81 _PyUnicode_EqualToASCIIString(modname, "__future__")) {
82 if (!future_check_features(ff, s, filename)) {
83 return 0;
84 }
85 ff->ff_location = SRC_LOCATION_FROM_AST(s);
86 }
87 else {
88 return 1;
89 }
90 }
91 else {
92 return 1;
93 }
94 }
95 return 1;
96 }
97
98
99 int
100 _PyFuture_FromAST(mod_ty mod, PyObject *filename, PyFutureFeatures *ff)
101 {
102 ff->ff_features = 0;
103 ff->ff_location = (_PyCompilerSrcLocation){-1, -1, -1, -1};
104
105 if (!future_parse(ff, mod, filename)) {
106 return 0;
107 }
108 return 1;
109 }