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