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
future_check_features(PyFutureFeatures * ff,stmt_ty s,PyObject * filename)14 future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
15 {
16     int i;
17     asdl_seq *names;
18 
19     assert(s->kind == ImportFrom_kind);
20 
21     names = s->v.ImportFrom.names;
22     for (i = 0; i < asdl_seq_LEN(names); i++) {
23         alias_ty name = (alias_ty)asdl_seq_GET(names, i);
24         const char *feature = PyUnicode_AsUTF8(name->name);
25         if (!feature)
26             return 0;
27         if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
28             continue;
29         } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
30             continue;
31         } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
32             continue;
33         } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
34             continue;
35         } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
36             continue;
37         } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
38             continue;
39         } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
40             continue;
41         } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
42             ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
43         } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
44             continue;
45         } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
46             ff->ff_features |= CO_FUTURE_ANNOTATIONS;
47         } else if (strcmp(feature, "braces") == 0) {
48             PyErr_SetString(PyExc_SyntaxError,
49                             "not a chance");
50             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
51             return 0;
52         } else {
53             PyErr_Format(PyExc_SyntaxError,
54                          UNDEFINED_FUTURE_FEATURE, feature);
55             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
56             return 0;
57         }
58     }
59     return 1;
60 }
61 
62 static int
future_parse(PyFutureFeatures * ff,mod_ty mod,PyObject * filename)63 future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
64 {
65     int i, done = 0, prev_line = 0;
66     stmt_ty first;
67 
68     if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
69         return 1;
70 
71     if (asdl_seq_LEN(mod->v.Module.body) == 0)
72         return 1;
73 
74     /* A subsequent pass will detect future imports that don't
75        appear at the beginning of the file.  There's one case,
76        however, that is easier to handle here: A series of imports
77        joined by semi-colons, where the first import is a future
78        statement but some subsequent import has the future form
79        but is preceded by a regular import.
80     */
81 
82     i = 0;
83     first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
84     if (first->kind == Expr_kind
85         && (first->v.Expr.value->kind == Str_kind
86             || (first->v.Expr.value->kind == Constant_kind
87                 && PyUnicode_CheckExact(first->v.Expr.value->v.Constant.value))))
88         i++;
89 
90     for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
91         stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
92 
93         if (done && s->lineno > prev_line)
94             return 1;
95         prev_line = s->lineno;
96 
97         /* The tests below will return from this function unless it is
98            still possible to find a future statement.  The only things
99            that can precede a future statement are another future
100            statement and a doc string.
101         */
102 
103         if (s->kind == ImportFrom_kind) {
104             identifier modname = s->v.ImportFrom.module;
105             if (modname &&
106                 _PyUnicode_EqualToASCIIString(modname, "__future__")) {
107                 if (done) {
108                     PyErr_SetString(PyExc_SyntaxError,
109                                     ERR_LATE_FUTURE);
110                     PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
111                     return 0;
112                 }
113                 if (!future_check_features(ff, s, filename))
114                     return 0;
115                 ff->ff_lineno = s->lineno;
116             }
117             else {
118                 done = 1;
119             }
120         }
121         else {
122             done = 1;
123         }
124     }
125     return 1;
126 }
127 
128 
129 PyFutureFeatures *
PyFuture_FromASTObject(mod_ty mod,PyObject * filename)130 PyFuture_FromASTObject(mod_ty mod, PyObject *filename)
131 {
132     PyFutureFeatures *ff;
133 
134     ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
135     if (ff == NULL) {
136         PyErr_NoMemory();
137         return NULL;
138     }
139     ff->ff_features = 0;
140     ff->ff_lineno = -1;
141 
142     if (!future_parse(ff, mod, filename)) {
143         PyObject_Free(ff);
144         return NULL;
145     }
146     return ff;
147 }
148 
149 
150 PyFutureFeatures *
PyFuture_FromAST(mod_ty mod,const char * filename_str)151 PyFuture_FromAST(mod_ty mod, const char *filename_str)
152 {
153     PyFutureFeatures *ff;
154     PyObject *filename;
155 
156     filename = PyUnicode_DecodeFSDefault(filename_str);
157     if (filename == NULL)
158         return NULL;
159     ff = PyFuture_FromASTObject(mod, filename);
160     Py_DECREF(filename);
161     return ff;
162 }
163