Line data Source code
1 : #include "Python.h"
2 : #include "Python-ast.h"
3 : #include "node.h"
4 : #include "token.h"
5 : #include "graminit.h"
6 : #include "code.h"
7 : #include "symtable.h"
8 :
9 : #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
10 : #define ERR_LATE_FUTURE \
11 : "from __future__ imports must occur at the beginning of the file"
12 :
13 : static int
14 0 : future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
15 : {
16 : int i;
17 : asdl_seq *names;
18 :
19 : assert(s->kind == ImportFrom_kind);
20 :
21 0 : names = s->v.ImportFrom.names;
22 0 : for (i = 0; i < asdl_seq_LEN(names); i++) {
23 0 : alias_ty name = (alias_ty)asdl_seq_GET(names, i);
24 0 : const char *feature = _PyUnicode_AsString(name->name);
25 0 : if (!feature)
26 0 : return 0;
27 0 : if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
28 0 : continue;
29 0 : } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
30 0 : continue;
31 0 : } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
32 0 : continue;
33 0 : } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
34 0 : continue;
35 0 : } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
36 0 : continue;
37 0 : } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
38 0 : continue;
39 0 : } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
40 0 : continue;
41 0 : } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
42 0 : ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
43 0 : } else if (strcmp(feature, "braces") == 0) {
44 0 : PyErr_SetString(PyExc_SyntaxError,
45 : "not a chance");
46 0 : PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
47 0 : return 0;
48 : } else {
49 0 : PyErr_Format(PyExc_SyntaxError,
50 : UNDEFINED_FUTURE_FEATURE, feature);
51 0 : PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
52 0 : return 0;
53 : }
54 : }
55 0 : return 1;
56 : }
57 :
58 : static int
59 3 : future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
60 : {
61 3 : int i, found_docstring = 0, done = 0, prev_line = 0;
62 :
63 3 : if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
64 0 : return 1;
65 :
66 : /* A subsequent pass will detect future imports that don't
67 : appear at the beginning of the file. There's one case,
68 : however, that is easier to handle here: A series of imports
69 : joined by semi-colons, where the first import is a future
70 : statement but some subsequent import has the future form
71 : but is preceded by a regular import.
72 : */
73 :
74 :
75 6 : for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
76 6 : stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
77 :
78 6 : if (done && s->lineno > prev_line)
79 3 : return 1;
80 3 : prev_line = s->lineno;
81 :
82 : /* The tests below will return from this function unless it is
83 : still possible to find a future statement. The only things
84 : that can precede a future statement are another future
85 : statement and a doc string.
86 : */
87 :
88 3 : if (s->kind == ImportFrom_kind) {
89 2 : identifier modname = s->v.ImportFrom.module;
90 4 : if (modname &&
91 2 : !PyUnicode_CompareWithASCIIString(modname, "__future__")) {
92 0 : if (done) {
93 0 : PyErr_SetString(PyExc_SyntaxError,
94 : ERR_LATE_FUTURE);
95 0 : PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
96 0 : return 0;
97 : }
98 0 : if (!future_check_features(ff, s, filename))
99 0 : return 0;
100 0 : ff->ff_lineno = s->lineno;
101 : }
102 : else
103 2 : done = 1;
104 : }
105 1 : else if (s->kind == Expr_kind && !found_docstring) {
106 0 : expr_ty e = s->v.Expr.value;
107 0 : if (e->kind != Str_kind)
108 0 : done = 1;
109 : else
110 0 : found_docstring = 1;
111 : }
112 : else
113 1 : done = 1;
114 : }
115 0 : return 1;
116 : }
117 :
118 :
119 : PyFutureFeatures *
120 3 : PyFuture_FromAST(mod_ty mod, const char *filename)
121 : {
122 : PyFutureFeatures *ff;
123 :
124 3 : ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
125 3 : if (ff == NULL) {
126 0 : PyErr_NoMemory();
127 0 : return NULL;
128 : }
129 3 : ff->ff_features = 0;
130 3 : ff->ff_lineno = -1;
131 :
132 3 : if (!future_parse(ff, mod, filename)) {
133 0 : PyObject_Free(ff);
134 0 : return NULL;
135 : }
136 3 : return ff;
137 : }
|