[Python-checkins] bpo-41084: Adjust message when an f-string expression causes a SyntaxError (GH-21084)
Lysandros Nikolaou
webhook-mailer at python.org
Fri Jun 26 07:24:32 EDT 2020
https://github.com/python/cpython/commit/2e0a920e9eb540654c0bb2298143b00637dc5961
commit: 2e0a920e9eb540654c0bb2298143b00637dc5961
branch: master
author: Lysandros Nikolaou <lisandrosnik at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-26T12:24:05+01:00
summary:
bpo-41084: Adjust message when an f-string expression causes a SyntaxError (GH-21084)
Prefix the error message with `fstring: `, when parsing an f-string expression throws a `SyntaxError`.
files:
A Misc/NEWS.d/next/Core and Builtins/2020-06-23-15-10-19.bpo-41084.pt3y7F.rst
M Lib/test/test_fstring.py
M Parser/pegen.c
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
index 7ffe01d2d8c31..0dc7dd8e254c3 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -524,7 +524,7 @@ def test_format_specifier_expressions(self):
# This looks like a nested format spec.
])
- self.assertAllRaise(SyntaxError, "invalid syntax",
+ self.assertAllRaise(SyntaxError, "f-string: invalid syntax",
[# Invalid syntax inside a nested spec.
"f'{4:{/5}}'",
])
@@ -598,7 +598,7 @@ def test_parens_in_expressions(self):
# are added around it. But we shouldn't go from an invalid
# expression to a valid one. The added parens are just
# supposed to allow whitespace (including newlines).
- self.assertAllRaise(SyntaxError, 'invalid syntax',
+ self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
["f'{,}'",
"f'{,}'", # this is (,), which is an error
])
@@ -716,7 +716,7 @@ def test_lambda(self):
# lambda doesn't work without parens, because the colon
# makes the parser think it's a format_spec
- self.assertAllRaise(SyntaxError, 'invalid syntax',
+ self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
["f'{lambda x:x}'",
])
@@ -1194,6 +1194,10 @@ def test_walrus(self):
self.assertEqual(f'{(x:=10)}', '10')
self.assertEqual(x, 10)
+ def test_invalid_syntax_error_message(self):
+ with self.assertRaisesRegex(SyntaxError, "f-string: invalid syntax"):
+ compile("f'{a $ b}'", "?", "exec")
+
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-06-23-15-10-19.bpo-41084.pt3y7F.rst b/Misc/NEWS.d/next/Core and Builtins/2020-06-23-15-10-19.bpo-41084.pt3y7F.rst
new file mode 100644
index 0000000000000..cd349af770bd0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-06-23-15-10-19.bpo-41084.pt3y7F.rst
@@ -0,0 +1 @@
+Prefix the error message with 'f-string: ', when parsing an f-string expression which throws a :exc:`SyntaxError`.
diff --git a/Parser/pegen.c b/Parser/pegen.c
index 594754cee5d53..79fcd2f5999de 100644
--- a/Parser/pegen.c
+++ b/Parser/pegen.c
@@ -391,6 +391,21 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
PyObject *tmp = NULL;
p->error_indicator = 1;
+ if (p->start_rule == Py_fstring_input) {
+ const char *fstring_msg = "f-string: ";
+ Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg);
+
+ char *new_errmsg = PyMem_RawMalloc(len + 1); // Lengths of both strings plus NULL character
+ if (!new_errmsg) {
+ return (void *) PyErr_NoMemory();
+ }
+
+ // Copy both strings into new buffer
+ memcpy(new_errmsg, fstring_msg, strlen(fstring_msg));
+ memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg));
+ new_errmsg[len] = 0;
+ errmsg = new_errmsg;
+ }
errstr = PyUnicode_FromFormatV(errmsg, va);
if (!errstr) {
goto error;
@@ -427,11 +442,17 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
Py_DECREF(errstr);
Py_DECREF(value);
+ if (p->start_rule == Py_fstring_input) {
+ PyMem_RawFree((void *)errmsg);
+ }
return NULL;
error:
Py_XDECREF(errstr);
Py_XDECREF(error_line);
+ if (p->start_rule == Py_fstring_input) {
+ PyMem_RawFree((void *)errmsg);
+ }
return NULL;
}
More information about the Python-checkins
mailing list