/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 | 21 | #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 | 330 | { |
11 | 330 | Py_ssize_t i; |
12 | | |
13 | 330 | assert(s->kind == ImportFrom_kind); |
14 | | |
15 | 330 | asdl_alias_seq *names = s->v.ImportFrom.names; |
16 | 778 | for (i = 0; i < asdl_seq_LEN(names); i++) { |
17 | 469 | alias_ty name = (alias_ty)asdl_seq_GET(names, i); |
18 | 469 | const char *feature = PyUnicode_AsUTF8(name->name); |
19 | 469 | if (!feature) |
20 | 0 | return 0; |
21 | 469 | if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { |
22 | 11 | continue; |
23 | 458 | } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { |
24 | 1 | continue; |
25 | 457 | } else if (strcmp(feature, FUTURE_DIVISION) == 0) { |
26 | 1 | continue; |
27 | 456 | } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { |
28 | 18 | continue; |
29 | 438 | } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { |
30 | 67 | continue; |
31 | 371 | } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) { |
32 | 70 | continue; |
33 | 301 | } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) { |
34 | 140 | continue; |
35 | 161 | } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { |
36 | 10 | ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL; |
37 | 151 | } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) { |
38 | 10 | continue; |
39 | 141 | } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) { |
40 | 120 | ff->ff_features |= CO_FUTURE_ANNOTATIONS; |
41 | 120 | } 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 | 21 | } else { |
51 | 21 | PyErr_Format(PyExc_SyntaxError, |
52 | 21 | UNDEFINED_FUTURE_FEATURE, feature); |
53 | 21 | PyErr_RangedSyntaxLocationObject(filename, |
54 | 21 | name->lineno, |
55 | 21 | name->col_offset + 1, |
56 | 21 | name->end_lineno, |
57 | 21 | name->end_col_offset + 1); |
58 | 21 | return 0; |
59 | 21 | } |
60 | 469 | } |
61 | 309 | return 1; |
62 | 330 | } |
63 | | |
64 | | static int |
65 | | future_parse(_PyFutureFeatures *ff, mod_ty mod, PyObject *filename) |
66 | 7.34k | { |
67 | 7.34k | if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) { |
68 | 66 | return 1; |
69 | 66 | } |
70 | | |
71 | 7.27k | Py_ssize_t n = asdl_seq_LEN(mod->v.Module.body); |
72 | 7.27k | if (n == 0) { |
73 | 732 | return 1; |
74 | 732 | } |
75 | | |
76 | 6.54k | Py_ssize_t i = 0; |
77 | 6.54k | if (_PyAST_GetDocString(mod->v.Module.body) != NULL) { |
78 | 551 | i++; |
79 | 551 | } |
80 | | |
81 | 6.85k | for (; i < n; i++) { |
82 | 6.50k | 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.50k | if (s->kind == ImportFrom_kind && s->v.ImportFrom.level == 0) { |
89 | 364 | identifier modname = s->v.ImportFrom.module; |
90 | 364 | if (modname && |
91 | 364 | _PyUnicode_EqualToASCIIString(modname, "__future__")) { |
92 | 330 | if (!future_check_features(ff, s, filename)) { |
93 | 21 | return 0; |
94 | 21 | } |
95 | 309 | ff->ff_location = SRC_LOCATION_FROM_AST(s); |
96 | 309 | } |
97 | 34 | else { |
98 | 34 | return 1; |
99 | 34 | } |
100 | 364 | } |
101 | 6.14k | else { |
102 | 6.14k | return 1; |
103 | 6.14k | } |
104 | 6.50k | } |
105 | 350 | return 1; |
106 | 6.54k | } |
107 | | |
108 | | |
109 | | int |
110 | | _PyFuture_FromAST(mod_ty mod, PyObject *filename, _PyFutureFeatures *ff) |
111 | 7.34k | { |
112 | 7.34k | ff->ff_features = 0; |
113 | 7.34k | ff->ff_location = (_Py_SourceLocation){-1, -1, -1, -1}; |
114 | | |
115 | 7.34k | if (!future_parse(ff, mod, filename)) { |
116 | 21 | return 0; |
117 | 21 | } |
118 | 7.32k | return 1; |
119 | 7.34k | } |