]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-121272: move __future__ import validation from compiler to symtable (#121273)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Tue, 2 Jul 2024 16:22:08 +0000 (17:22 +0100)
committerGitHub <noreply@github.com>
Tue, 2 Jul 2024 16:22:08 +0000 (16:22 +0000)
Python/compile.c
Python/symtable.c

index 69de0ec2996e00995143ce217da07c0591f9da31..d33db69f4253610e3bf5528607fe70f39a639a4a 100644 (file)
@@ -77,14 +77,6 @@ typedef struct _PyCfgBuilder cfg_builder;
 #define LOCATION(LNO, END_LNO, COL, END_COL) \
     ((const _Py_SourceLocation){(LNO), (END_LNO), (COL), (END_COL)})
 
-/* Return true if loc1 starts after loc2 ends. */
-static inline bool
-location_is_after(location loc1, location loc2) {
-    return (loc1.lineno > loc2.end_lineno) ||
-            ((loc1.lineno == loc2.end_lineno) &&
-             (loc1.col_offset > loc2.end_col_offset));
-}
-
 #define LOC(x) SRC_LOCATION_FROM_AST(x)
 
 typedef _PyJumpTargetLabel jump_target_label;
@@ -3847,14 +3839,6 @@ compiler_from_import(struct compiler *c, stmt_ty s)
         PyTuple_SET_ITEM(names, i, Py_NewRef(alias->name));
     }
 
-    if (location_is_after(LOC(s), c->c_future.ff_location) &&
-        s->v.ImportFrom.module && s->v.ImportFrom.level == 0 &&
-        _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__"))
-    {
-        Py_DECREF(names);
-        return compiler_error(c, LOC(s), "from __future__ imports must occur "
-                              "at the beginning of the file");
-    }
     ADDOP_LOAD_CONST_NEW(c, LOC(s), names);
 
     if (s->v.ImportFrom.module) {
index 2e56ea6e830846f6291cf61a447a9977be7e8b80..61fa5c6fdf923cc3eaecde13c93a836d4e61a4f4 100644 (file)
@@ -1660,6 +1660,27 @@ has_kwonlydefaults(asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)
     return 0;
 }
 
+static int
+check_import_from(struct symtable *st, stmt_ty s)
+{
+    assert(s->kind == ImportFrom_kind);
+    _Py_SourceLocation fut = st->st_future->ff_location;
+    if (s->v.ImportFrom.module && s->v.ImportFrom.level == 0 &&
+        _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__") &&
+        ((s->lineno > fut.lineno) ||
+         ((s->lineno == fut.end_lineno) && (s->col_offset > fut.end_col_offset))))
+    {
+        PyErr_SetString(PyExc_SyntaxError,
+                        "from __future__ imports must occur "
+                        "at the beginning of the file");
+        PyErr_RangedSyntaxLocationObject(st->st_filename,
+                                         s->lineno, s->col_offset + 1,
+                                         s->end_lineno, s->end_col_offset + 1);
+        return 0;
+    }
+    return 1;
+}
+
 static int
 symtable_visit_stmt(struct symtable *st, stmt_ty s)
 {
@@ -1914,6 +1935,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
         break;
     case ImportFrom_kind:
         VISIT_SEQ(st, alias, s->v.ImportFrom.names);
+        if (!check_import_from(st, s)) {
+            VISIT_QUIT(st, 0);
+        }
         break;
     case Global_kind: {
         Py_ssize_t i;