summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCrowthebird <78076854+thatbirdguythatuknownot@users.noreply.github.com>2024-05-02 13:32:20 (GMT)
committerGitHub <noreply@github.com>2024-05-02 13:32:20 (GMT)
commit7c97dc8c9594c71bd3d1f69758a27de45f57e4c3 (patch)
tree480d75833e594394bccb168b6b8d86c131d0d65a
parent67bba9dd0f5b9c2d24c2bc6d239c4502040484af (diff)
downloadcpython-7c97dc8c9594c71bd3d1f69758a27de45f57e4c3.zip
cpython-7c97dc8c9594c71bd3d1f69758a27de45f57e4c3.tar.gz
cpython-7c97dc8c9594c71bd3d1f69758a27de45f57e4c3.tar.bz2
gh-118216: Don't consider dotted `__future__` imports (#118267)
-rw-r--r--Doc/whatsnew/3.13.rst4
-rw-r--r--Lib/test/test_future_stmt/test_future.py19
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-04-25-11-48-28.gh-issue-118216.SVg700.rst1
-rw-r--r--Python/compile.c2
-rw-r--r--Python/future.c2
5 files changed, 26 insertions, 2 deletions
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 52fb975..3ccf17b 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -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
===========
diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py
index 2c8ceb6..69ae58b 100644
--- a/Lib/test/test_future_stmt/test_future.py
+++ b/Lib/test/test_future_stmt/test_future.py
@@ -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
index 0000000..937cdff
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-25-11-48-28.gh-issue-118216.SVg700.rst
@@ -0,0 +1 @@
+Don't consider :mod:`__future__` imports with dots before the module name.
diff --git a/Python/compile.c b/Python/compile.c
index 4e94f92..feedd98 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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);
diff --git a/Python/future.c b/Python/future.c
index 399345b..8d94d51 100644
--- a/Python/future.c
+++ b/Python/future.c
@@ -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__")) {