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