aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorBrian Schubert <brianm.schubert@gmail.com>2024-10-29 19:57:59 -0400
committerGitHub <noreply@github.com>2024-10-29 23:57:59 +0000
commit224c370a3680132997f1e43d20a3b4ca95a060ab (patch)
tree34fabd982364362ebf462c14aee621c42893ca8f
parent9dfef4e5f4ac3c1ce494c48f2476a694c12d72a5 (diff)
downloadcpython-224c370a3680132997f1e43d20a3b4ca95a060ab.tar.gz
cpython-224c370a3680132997f1e43d20a3b4ca95a060ab.zip
gh-126139: Improve error message location for future statement with unknown feature (#126140)
-rw-r--r--Lib/test/test_exceptions.py4
-rw-r--r--Lib/test/test_future_stmt/test_future.py8
-rw-r--r--Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-15-17-31.gh-issue-126139.B4OQ8a.rst2
-rw-r--r--Python/future.c12
4 files changed, 18 insertions, 8 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index b3c21cd4f3d..5beeac3adfc 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -319,8 +319,8 @@ class ExceptionTests(unittest.TestCase):
check('def f():\n global x\n nonlocal x', 2, 3)
# Errors thrown by future.c
- check('from __future__ import doesnt_exist', 1, 1)
- check('from __future__ import braces', 1, 1)
+ check('from __future__ import doesnt_exist', 1, 24)
+ check('from __future__ import braces', 1, 24)
check('x=1\nfrom __future__ import division', 2, 1)
check('foo(1=2)', 1, 5)
check('def f():\n x, y: int', 2, 3)
diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py
index 44512e0101d..42c6cb3fefa 100644
--- a/Lib/test/test_future_stmt/test_future.py
+++ b/Lib/test/test_future_stmt/test_future.py
@@ -88,7 +88,7 @@ class FutureTest(unittest.TestCase):
"""
self.assertSyntaxError(
code, lineno=2,
- message='future feature rested_snopes is not defined',
+ message='future feature rested_snopes is not defined', offset=24,
)
def test_future_import_not_on_top(self):
@@ -137,19 +137,19 @@ class FutureTest(unittest.TestCase):
code = """
from __future__ import *
"""
- self.assertSyntaxError(code, message='future feature * is not defined')
+ self.assertSyntaxError(code, message='future feature * is not defined', offset=24)
def test_future_import_braces(self):
code = """
from __future__ import braces
"""
# Congrats, you found an easter egg!
- self.assertSyntaxError(code, message='not a chance')
+ self.assertSyntaxError(code, message='not a chance', offset=24)
code = """
from __future__ import nested_scopes, braces
"""
- self.assertSyntaxError(code, message='not a chance')
+ self.assertSyntaxError(code, message='not a chance', offset=39)
def test_module_with_future_import_not_on_top(self):
with self.assertRaises(SyntaxError) as cm:
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-15-17-31.gh-issue-126139.B4OQ8a.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-15-17-31.gh-issue-126139.B4OQ8a.rst
new file mode 100644
index 00000000000..278971b46d1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-15-17-31.gh-issue-126139.B4OQ8a.rst
@@ -0,0 +1,2 @@
+Provide better error location when attempting to use a :term:`future
+statement <__future__>` with an unknown future feature.
diff --git a/Python/future.c b/Python/future.c
index 8aeb541cb05..79b6c0c503b 100644
--- a/Python/future.c
+++ b/Python/future.c
@@ -41,12 +41,20 @@ future_check_features(_PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
- PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
+ PyErr_RangedSyntaxLocationObject(filename,
+ name->lineno,
+ name->col_offset + 1,
+ name->end_lineno,
+ name->end_col_offset + 1);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
- PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
+ PyErr_RangedSyntaxLocationObject(filename,
+ name->lineno,
+ name->col_offset + 1,
+ name->end_lineno,
+ name->end_col_offset + 1);
return 0;
}
}