/src/Python-3.8.3/Python/future.c
Line  | Count  | Source  | 
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  |  | #include "ast.h"  | 
9  |  |  | 
10  | 0  | #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"  | 
11  | 0  | #define ERR_LATE_FUTURE \  | 
12  | 0  | "from __future__ imports must occur at the beginning of the file"  | 
13  |  |  | 
14  |  | static int  | 
15  |  | future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)  | 
16  | 0  | { | 
17  | 0  |     int i;  | 
18  | 0  |     asdl_seq *names;  | 
19  |  | 
  | 
20  | 0  |     assert(s->kind == ImportFrom_kind);  | 
21  |  | 
  | 
22  | 0  |     names = s->v.ImportFrom.names;  | 
23  | 0  |     for (i = 0; i < asdl_seq_LEN(names); i++) { | 
24  | 0  |         alias_ty name = (alias_ty)asdl_seq_GET(names, i);  | 
25  | 0  |         const char *feature = PyUnicode_AsUTF8(name->name);  | 
26  | 0  |         if (!feature)  | 
27  | 0  |             return 0;  | 
28  | 0  |         if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { | 
29  | 0  |             continue;  | 
30  | 0  |         } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { | 
31  | 0  |             continue;  | 
32  | 0  |         } else if (strcmp(feature, FUTURE_DIVISION) == 0) { | 
33  | 0  |             continue;  | 
34  | 0  |         } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { | 
35  | 0  |             continue;  | 
36  | 0  |         } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { | 
37  | 0  |             continue;  | 
38  | 0  |         } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) { | 
39  | 0  |             continue;  | 
40  | 0  |         } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) { | 
41  | 0  |             continue;  | 
42  | 0  |         } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { | 
43  | 0  |             ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;  | 
44  | 0  |         } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) { | 
45  | 0  |             continue;  | 
46  | 0  |         } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) { | 
47  | 0  |             ff->ff_features |= CO_FUTURE_ANNOTATIONS;  | 
48  | 0  |         } else if (strcmp(feature, "braces") == 0) { | 
49  | 0  |             PyErr_SetString(PyExc_SyntaxError,  | 
50  | 0  |                             "not a chance");  | 
51  | 0  |             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);  | 
52  | 0  |             return 0;  | 
53  | 0  |         } else { | 
54  | 0  |             PyErr_Format(PyExc_SyntaxError,  | 
55  | 0  |                          UNDEFINED_FUTURE_FEATURE, feature);  | 
56  | 0  |             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);  | 
57  | 0  |             return 0;  | 
58  | 0  |         }  | 
59  | 0  |     }  | 
60  | 0  |     return 1;  | 
61  | 0  | }  | 
62  |  |  | 
63  |  | static int  | 
64  |  | future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)  | 
65  | 16  | { | 
66  | 16  |     int i, done = 0, prev_line = 0;  | 
67  |  |  | 
68  | 16  |     if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))  | 
69  | 0  |         return 1;  | 
70  |  |  | 
71  | 16  |     if (asdl_seq_LEN(mod->v.Module.body) == 0)  | 
72  | 0  |         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  | 16  |     i = 0;  | 
83  | 16  |     if (_PyAST_GetDocString(mod->v.Module.body) != NULL)  | 
84  | 0  |         i++;  | 
85  |  |  | 
86  | 32  |     for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { | 
87  | 18  |         stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);  | 
88  |  |  | 
89  | 18  |         if (done && s->lineno > prev_line)  | 
90  | 2  |             return 1;  | 
91  | 16  |         prev_line = s->lineno;  | 
92  |  |  | 
93  |  |         /* The tests below will return from this function unless it is  | 
94  |  |            still possible to find a future statement.  The only things  | 
95  |  |            that can precede a future statement are another future  | 
96  |  |            statement and a doc string.  | 
97  |  |         */  | 
98  |  |  | 
99  | 16  |         if (s->kind == ImportFrom_kind) { | 
100  | 0  |             identifier modname = s->v.ImportFrom.module;  | 
101  | 0  |             if (modname &&  | 
102  | 0  |                 _PyUnicode_EqualToASCIIString(modname, "__future__")) { | 
103  | 0  |                 if (done) { | 
104  | 0  |                     PyErr_SetString(PyExc_SyntaxError,  | 
105  | 0  |                                     ERR_LATE_FUTURE);  | 
106  | 0  |                     PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);  | 
107  | 0  |                     return 0;  | 
108  | 0  |                 }  | 
109  | 0  |                 if (!future_check_features(ff, s, filename))  | 
110  | 0  |                     return 0;  | 
111  | 0  |                 ff->ff_lineno = s->lineno;  | 
112  | 0  |             }  | 
113  | 0  |             else { | 
114  | 0  |                 done = 1;  | 
115  | 0  |             }  | 
116  | 0  |         }  | 
117  | 16  |         else { | 
118  | 16  |             done = 1;  | 
119  | 16  |         }  | 
120  | 16  |     }  | 
121  | 14  |     return 1;  | 
122  | 16  | }  | 
123  |  |  | 
124  |  |  | 
125  |  | PyFutureFeatures *  | 
126  |  | PyFuture_FromASTObject(mod_ty mod, PyObject *filename)  | 
127  | 16  | { | 
128  | 16  |     PyFutureFeatures *ff;  | 
129  |  |  | 
130  | 16  |     ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));  | 
131  | 16  |     if (ff == NULL) { | 
132  | 0  |         PyErr_NoMemory();  | 
133  | 0  |         return NULL;  | 
134  | 0  |     }  | 
135  | 16  |     ff->ff_features = 0;  | 
136  | 16  |     ff->ff_lineno = -1;  | 
137  |  |  | 
138  | 16  |     if (!future_parse(ff, mod, filename)) { | 
139  | 0  |         PyObject_Free(ff);  | 
140  | 0  |         return NULL;  | 
141  | 0  |     }  | 
142  | 16  |     return ff;  | 
143  | 16  | }  | 
144  |  |  | 
145  |  |  | 
146  |  | PyFutureFeatures *  | 
147  |  | PyFuture_FromAST(mod_ty mod, const char *filename_str)  | 
148  | 0  | { | 
149  | 0  |     PyFutureFeatures *ff;  | 
150  | 0  |     PyObject *filename;  | 
151  |  | 
  | 
152  | 0  |     filename = PyUnicode_DecodeFSDefault(filename_str);  | 
153  | 0  |     if (filename == NULL)  | 
154  | 0  |         return NULL;  | 
155  | 0  |     ff = PyFuture_FromASTObject(mod, filename);  | 
156  | 0  |     Py_DECREF(filename);  | 
157  | 0  |     return ff;  | 
158  | 0  | }  |