summaryrefslogtreecommitdiffstats
path: root/Python/future.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/future.c')
-rw-r--r--Python/future.c53
1 files changed, 17 insertions, 36 deletions
diff --git a/Python/future.c b/Python/future.c
index d465608..2a45d2e 100644
--- a/Python/future.c
+++ b/Python/future.c
@@ -2,8 +2,6 @@
#include "pycore_ast.h" // _PyAST_GetDocString()
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
-#define ERR_LATE_FUTURE \
-"from __future__ imports must occur at the beginning of the file"
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
@@ -56,59 +54,42 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{
- int i, done = 0, prev_line = 0;
-
- if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
+ if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) {
return 1;
+ }
- if (asdl_seq_LEN(mod->v.Module.body) == 0)
+ Py_ssize_t n = asdl_seq_LEN(mod->v.Module.body);
+ if (n == 0) {
return 1;
+ }
- /* 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.
- */
-
- i = 0;
- if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
+ Py_ssize_t i = 0;
+ if (_PyAST_GetDocString(mod->v.Module.body) != NULL) {
i++;
+ }
- for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
+ for (; i < n; i++) {
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.
- */
+ /* The only things that can precede a future statement
+ * are another future statement and a doc string.
+ */
if (s->kind == ImportFrom_kind) {
identifier modname = s->v.ImportFrom.module;
if (modname &&
_PyUnicode_EqualToASCIIString(modname, "__future__")) {
- if (done) {
- PyErr_SetString(PyExc_SyntaxError,
- ERR_LATE_FUTURE);
- PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
+ if (!future_check_features(ff, s, filename)) {
return 0;
}
- if (!future_check_features(ff, s, filename))
- return 0;
- ff->ff_lineno = s->lineno;
+ ff->ff_location = SRC_LOCATION_FROM_AST(s);
}
else {
- done = 1;
+ return 1;
}
}
else {
- done = 1;
+ return 1;
}
}
return 1;
@@ -126,7 +107,7 @@ _PyFuture_FromAST(mod_ty mod, PyObject *filename)
return NULL;
}
ff->ff_features = 0;
- ff->ff_lineno = -1;
+ ff->ff_location = (_PyCompilerSrcLocation){-1, -1, -1, -1};
if (!future_parse(ff, mod, filename)) {
PyObject_Free(ff);