Skip to content

Commit

Permalink
bpo-41084: Adjust message when an f-string expression causes a Syntax…
Browse files Browse the repository at this point in the history
…Error (pythonGH-21084)

Prefix the error message with `fstring: `, when parsing an f-string expression throws a `SyntaxError`.
(cherry picked from commit 2e0a920)

Co-authored-by: Lysandros Nikolaou <[email protected]>
  • Loading branch information
lysnikolaou authored and miss-islington committed Jun 27, 2020
1 parent 5193d0a commit dda1fb5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
10 changes: 7 additions & 3 deletions Lib/test/test_fstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}}'",
])
Expand Down Expand Up @@ -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
])
Expand Down Expand Up @@ -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}'",
])

Expand Down Expand Up @@ -1200,6 +1200,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()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prefix the error message with 'f-string: ', when parsing an f-string expression which throws a :exc:`SyntaxError`.
21 changes: 21 additions & 0 deletions Parser/pegen/pegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit dda1fb5

Please sign in to comment.