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