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