mirror of https://github.com/python/cpython
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`.
This commit is contained in:
parent
ef19bad7d6
commit
2e0a920e9e
|
@ -524,7 +524,7 @@ non-important content
|
||||||
# This looks like a nested format spec.
|
# 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.
|
[# Invalid syntax inside a nested spec.
|
||||||
"f'{4:{/5}}'",
|
"f'{4:{/5}}'",
|
||||||
])
|
])
|
||||||
|
@ -598,7 +598,7 @@ non-important content
|
||||||
# are added around it. But we shouldn't go from an invalid
|
# are added around it. But we shouldn't go from an invalid
|
||||||
# expression to a valid one. The added parens are just
|
# expression to a valid one. The added parens are just
|
||||||
# supposed to allow whitespace (including newlines).
|
# supposed to allow whitespace (including newlines).
|
||||||
self.assertAllRaise(SyntaxError, 'invalid syntax',
|
self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
|
||||||
["f'{,}'",
|
["f'{,}'",
|
||||||
"f'{,}'", # this is (,), which is an error
|
"f'{,}'", # this is (,), which is an error
|
||||||
])
|
])
|
||||||
|
@ -716,7 +716,7 @@ non-important content
|
||||||
|
|
||||||
# lambda doesn't work without parens, because the colon
|
# lambda doesn't work without parens, because the colon
|
||||||
# makes the parser think it's a format_spec
|
# 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}'",
|
["f'{lambda x:x}'",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1194,6 +1194,10 @@ non-important content
|
||||||
self.assertEqual(f'{(x:=10)}', '10')
|
self.assertEqual(f'{(x:=10)}', '10')
|
||||||
self.assertEqual(x, 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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Prefix the error message with 'f-string: ', when parsing an f-string expression which throws a :exc:`SyntaxError`.
|
|
@ -391,6 +391,21 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
|
||||||
PyObject *tmp = NULL;
|
PyObject *tmp = NULL;
|
||||||
p->error_indicator = 1;
|
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);
|
errstr = PyUnicode_FromFormatV(errmsg, va);
|
||||||
if (!errstr) {
|
if (!errstr) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -427,11 +442,17 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
|
||||||
|
|
||||||
Py_DECREF(errstr);
|
Py_DECREF(errstr);
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
|
if (p->start_rule == Py_fstring_input) {
|
||||||
|
PyMem_RawFree((void *)errmsg);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(errstr);
|
Py_XDECREF(errstr);
|
||||||
Py_XDECREF(error_line);
|
Py_XDECREF(error_line);
|
||||||
|
if (p->start_rule == Py_fstring_input) {
|
||||||
|
PyMem_RawFree((void *)errmsg);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue