future.c 4.63 KB
Newer Older
1
#include "Python.h"
Jeremy Hylton's avatar
Jeremy Hylton committed
2
#include "Python-ast.h"
3 4 5
#include "node.h"
#include "token.h"
#include "graminit.h"
Jeremy Hylton's avatar
Jeremy Hylton committed
6
#include "code.h"
7 8 9
#include "symtable.h"

#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
10 11
#define ERR_LATE_FUTURE \
"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 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
    int i;
    asdl_seq *names;

    assert(s->kind == ImportFrom_kind);

    names = s->v.ImportFrom.names;
    for (i = 0; i < asdl_seq_LEN(names); i++) {
        alias_ty name = (alias_ty)asdl_seq_GET(names, i);
        const char *feature = _PyUnicode_AsString(name->name);
        if (!feature)
            return 0;
        if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
            ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
        } else if (strcmp(feature, "braces") == 0) {
            PyErr_SetString(PyExc_SyntaxError,
                            "not a chance");
46
            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
47 48 49 50
            return 0;
        } else {
            PyErr_Format(PyExc_SyntaxError,
                         UNDEFINED_FUTURE_FEATURE, feature);
51
            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
52 53 54 55
            return 0;
        }
    }
    return 1;
56 57
}

58
static int
59
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
60
{
61
    int i, done = 0, prev_line = 0;
Benjamin Peterson's avatar
Benjamin Peterson committed
62
    stmt_ty first;
63 64 65 66

    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
        return 1;

67 68 69
    if (asdl_seq_LEN(mod->v.Module.body) == 0)
        return 1;

70 71 72 73 74 75 76 77
    /* A subsequent pass will detect future imports that don't
       appear at the beginning of the file.  There's one case,
       however, that is easier to handle here: A series of imports
       joined by semi-colons, where the first import is a future
       statement but some subsequent import has the future form
       but is preceded by a regular import.
    */

78
    i = 0;
Benjamin Peterson's avatar
Benjamin Peterson committed
79
    first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
80 81
    if (first->kind == Expr_kind && first->v.Expr.value->kind == Str_kind)
        i++;
82

83 84

    for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
85 86 87 88 89 90 91 92 93 94 95 96 97
        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

        if (done && s->lineno > prev_line)
            return 1;
        prev_line = s->lineno;

        /* The tests below will return from this function unless it is
           still possible to find a future statement.  The only things
           that can precede a future statement are another future
           statement and a doc string.
        */

        if (s->kind == ImportFrom_kind) {
98
            identifier modname = s->v.ImportFrom.module;
Benjamin Peterson's avatar
Benjamin Peterson committed
99 100
            if (modname &&
                !PyUnicode_CompareWithASCIIString(modname, "__future__")) {
101 102 103
                if (done) {
                    PyErr_SetString(PyExc_SyntaxError,
                                    ERR_LATE_FUTURE);
104
                    PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
105 106 107 108 109 110
                    return 0;
                }
                if (!future_check_features(ff, s, filename))
                    return 0;
                ff->ff_lineno = s->lineno;
            }
111
            else {
112
                done = 1;
113
            }
114
        }
115
        else {
116
            done = 1;
117
        }
118 119
    }
    return 1;
120 121
}

Jeremy Hylton's avatar
Jeremy Hylton committed
122

123
PyFutureFeatures *
124
PyFuture_FromASTObject(mod_ty mod, PyObject *filename)
125
{
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    PyFutureFeatures *ff;

    ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
    if (ff == NULL) {
        PyErr_NoMemory();
        return NULL;
    }
    ff->ff_features = 0;
    ff->ff_lineno = -1;

    if (!future_parse(ff, mod, filename)) {
        PyObject_Free(ff);
        return NULL;
    }
    return ff;
141
}
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156


PyFutureFeatures *
PyFuture_FromAST(mod_ty mod, const char *filename_str)
{
    PyFutureFeatures *ff;
    PyObject *filename;

    filename = PyUnicode_DecodeFSDefault(filename_str);
    if (filename == NULL)
        return NULL;
    ff = PyFuture_FromASTObject(mod, filename);
    Py_DECREF(filename);
    return ff;
}