/src/cpython/Python/future.c
Line | Count | Source (jump to first uncovered line) |
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 | 22 | #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 | 312 | { |
11 | 312 | Py_ssize_t i; |
12 | | |
13 | 312 | assert(s->kind == ImportFrom_kind); |
14 | | |
15 | 312 | asdl_alias_seq *names = s->v.ImportFrom.names; |
16 | 714 | for (i = 0; i < asdl_seq_LEN(names); i++) { |
17 | 425 | alias_ty name = (alias_ty)asdl_seq_GET(names, i); |
18 | 425 | const char *feature = PyUnicode_AsUTF8(name->name); |
19 | 425 | if (!feature) |
20 | 0 | return 0; |
21 | 425 | if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { |
22 | 10 | continue; |
23 | 415 | } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { |
24 | 0 | continue; |
25 | 415 | } else if (strcmp(feature, FUTURE_DIVISION) == 0) { |
26 | 1 | continue; |
27 | 414 | } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { |
28 | 18 | continue; |
29 | 396 | } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { |
30 | 40 | continue; |
31 | 356 | } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) { |
32 | 72 | continue; |
33 | 284 | } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) { |
34 | 115 | continue; |
35 | 169 | } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { |
36 | 10 | ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL; |
37 | 159 | } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) { |
38 | 10 | continue; |
39 | 149 | } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) { |
40 | 126 | ff->ff_features |= CO_FUTURE_ANNOTATIONS; |
41 | 126 | } else if (strcmp(feature, "braces") == 0) { |
42 | 1 | PyErr_SetString(PyExc_SyntaxError, |
43 | 1 | "not a chance"); |
44 | 1 | PyErr_RangedSyntaxLocationObject(filename, |
45 | 1 | name->lineno, |
46 | 1 | name->col_offset + 1, |
47 | 1 | name->end_lineno, |
48 | 1 | name->end_col_offset + 1); |
49 | 1 | return 0; |
50 | 22 | } else { |
51 | 22 | PyErr_Format(PyExc_SyntaxError, |
52 | 22 | UNDEFINED_FUTURE_FEATURE, feature); |
53 | 22 | PyErr_RangedSyntaxLocationObject(filename, |
54 | 22 | name->lineno, |
55 | 22 | name->col_offset + 1, |
56 | 22 | name->end_lineno, |
57 | 22 | name->end_col_offset + 1); |
58 | 22 | return 0; |
59 | 22 | } |
60 | 425 | } |
61 | 289 | return 1; |
62 | 312 | } |
63 | | |
64 | | static int |
65 | | future_parse(_PyFutureFeatures *ff, mod_ty mod, PyObject *filename) |
66 | 7.90k | { |
67 | 7.90k | if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) { |
68 | 43 | return 1; |
69 | 43 | } |
70 | | |
71 | 7.86k | Py_ssize_t n = asdl_seq_LEN(mod->v.Module.body); |
72 | 7.86k | if (n == 0) { |
73 | 875 | return 1; |
74 | 875 | } |
75 | | |
76 | 6.98k | Py_ssize_t i = 0; |
77 | 6.98k | if (_PyAST_GetDocString(mod->v.Module.body) != NULL) { |
78 | 605 | i++; |
79 | 605 | } |
80 | | |
81 | 7.27k | for (; i < n; i++) { |
82 | 6.86k | 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.86k | if (s->kind == ImportFrom_kind && s->v.ImportFrom.level == 0) { |
89 | 350 | identifier modname = s->v.ImportFrom.module; |
90 | 350 | if (modname && |
91 | 350 | _PyUnicode_EqualToASCIIString(modname, "__future__")) { |
92 | 312 | if (!future_check_features(ff, s, filename)) { |
93 | 23 | return 0; |
94 | 23 | } |
95 | 289 | ff->ff_location = SRC_LOCATION_FROM_AST(s); |
96 | 289 | } |
97 | 38 | else { |
98 | 38 | return 1; |
99 | 38 | } |
100 | 350 | } |
101 | 6.51k | else { |
102 | 6.51k | return 1; |
103 | 6.51k | } |
104 | 6.86k | } |
105 | 409 | return 1; |
106 | 6.98k | } |
107 | | |
108 | | |
109 | | int |
110 | | _PyFuture_FromAST(mod_ty mod, PyObject *filename, _PyFutureFeatures *ff) |
111 | 7.90k | { |
112 | 7.90k | ff->ff_features = 0; |
113 | 7.90k | ff->ff_location = (_Py_SourceLocation){-1, -1, -1, -1}; |
114 | | |
115 | 7.90k | if (!future_parse(ff, mod, filename)) { |
116 | 23 | return 0; |
117 | 23 | } |
118 | 7.88k | return 1; |
119 | 7.90k | } |