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