]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-118216: Don't consider dotted `__future__` imports (#118267)
authorCrowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com>
Thu, 2 May 2024 13:32:20 +0000 (21:32 +0800)
committerGitHub <noreply@github.com>
Thu, 2 May 2024 13:32:20 +0000 (06:32 -0700)
Doc/whatsnew/3.13.rst
Lib/test/test_future_stmt/test_future.py
Misc/NEWS.d/next/Core and Builtins/2024-04-25-11-48-28.gh-issue-118216.SVg700.rst [new file with mode: 0644]
Python/compile.c
Python/future.c

index 52fb9752cf413257d9ff1855c01507033f040734..3ccf17be9796d50fc9484304fc8d712e39060751 100644 (file)
@@ -288,6 +288,10 @@ Other Language Changes
   class scopes are not inlined into their parent scope. (Contributed by
   Jelle Zijlstra in :gh:`109118` and :gh:`118160`.)
 
+* ``from __future__ import ...`` statements are now just normal
+  relative imports if dots are present before the module name.
+  (Contributed by Jeremiah Gabriel Pascual in :gh:`118216`.)
+
 
 New Modules
 ===========
index 2c8ceb664cb362daab89136cd83c5f849a96e366..69ae58b0fbcae35d61e844e8330a1857e0414d97 100644 (file)
@@ -203,6 +203,25 @@ class FutureTest(unittest.TestCase):
         out = kill_python(p)
         self.assertNotIn(b'SyntaxError: invalid syntax', out)
 
+    def test_future_dotted_import(self):
+        with self.assertRaises(ImportError):
+            exec("from .__future__ import spam")
+
+        code = dedent(
+            """
+            from __future__ import print_function
+            from ...__future__ import ham
+            """
+        )
+        with self.assertRaises(ImportError):
+            exec(code)
+
+        code = """
+            from .__future__ import nested_scopes
+            from __future__ import barry_as_FLUFL
+        """
+        self.assertSyntaxError(code, lineno=2)
+
 class AnnotationsFutureTestCase(unittest.TestCase):
     template = dedent(
         """
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-25-11-48-28.gh-issue-118216.SVg700.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-25-11-48-28.gh-issue-118216.SVg700.rst
new file mode 100644 (file)
index 0000000..937cdff
--- /dev/null
@@ -0,0 +1 @@
+Don't consider :mod:`__future__` imports with dots before the module name.
index 4e94f9297a32d170928ac792bf783e225ef38d55..feedd98883439707838186a85d463043931ecb06 100644 (file)
@@ -3849,7 +3849,7 @@ compiler_from_import(struct compiler *c, stmt_ty s)
     }
 
     if (location_is_after(LOC(s), c->c_future.ff_location) &&
-        s->v.ImportFrom.module &&
+        s->v.ImportFrom.module && s->v.ImportFrom.level == 0 &&
         _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__"))
     {
         Py_DECREF(names);
index 399345bd8fcbd956cba43a757126c115cece9e33..8d94d515605dcd62a940bca2d28c32501dd8ef7f 100644 (file)
@@ -77,7 +77,7 @@ future_parse(_PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
          *  are another future statement and a doc string.
          */
 
-        if (s->kind == ImportFrom_kind) {
+        if (s->kind == ImportFrom_kind && s->v.ImportFrom.level == 0) {
             identifier modname = s->v.ImportFrom.module;
             if (modname &&
                 _PyUnicode_EqualToASCIIString(modname, "__future__")) {