gh-104658: Fix location of unclosed quote error for multiline f-strings (#104660)

This commit is contained in:
Pablo Galindo Salgado 2023-05-20 14:07:05 +01:00 committed by GitHub
parent 663c049ff7
commit ff7f731632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 3 deletions

View File

@ -1558,7 +1558,21 @@ x = (
self.assertAllRaise(SyntaxError, "unterminated f-string literal", ['f"', "f'"]) self.assertAllRaise(SyntaxError, "unterminated f-string literal", ['f"', "f'"])
self.assertAllRaise(SyntaxError, "unterminated triple-quoted f-string literal", self.assertAllRaise(SyntaxError, "unterminated triple-quoted f-string literal",
['f"""', "f'''"]) ['f"""', "f'''"])
# Ensure that the errors are reported at the correct line number.
data = '''\
x = 1 + 1
y = 2 + 2
z = f"""
sdfjnsdfjsdf
sdfsdfs{1+
2} dfigdf {3+
4}sdufsd""
'''
try:
compile(data, "?", "exec")
except SyntaxError as e:
self.assertEqual(e.text, 'z = f"""')
self.assertEqual(e.lineno, 3)
def test_syntax_error_after_debug(self): def test_syntax_error_after_debug(self):
self.assertAllRaise(SyntaxError, "f-string: expecting a valid expression after '{'", self.assertAllRaise(SyntaxError, "f-string: expecting a valid expression after '{'",
[ [

View File

@ -1124,7 +1124,7 @@ tok_underflow_interactive(struct tok_state *tok) {
static int static int
tok_underflow_file(struct tok_state *tok) { tok_underflow_file(struct tok_state *tok) {
if (tok->start == NULL) { if (tok->start == NULL && !INSIDE_FSTRING(tok)) {
tok->cur = tok->inp = tok->buf; tok->cur = tok->inp = tok->buf;
} }
if (tok->decoding_state == STATE_INIT) { if (tok->decoding_state == STATE_INIT) {
@ -2250,6 +2250,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
the_current_tok->f_string_quote_size = quote_size; the_current_tok->f_string_quote_size = quote_size;
the_current_tok->f_string_start = tok->start; the_current_tok->f_string_start = tok->start;
the_current_tok->f_string_multi_line_start = tok->line_start; the_current_tok->f_string_multi_line_start = tok->line_start;
the_current_tok->f_string_line_start = tok->lineno;
the_current_tok->f_string_start_offset = -1; the_current_tok->f_string_start_offset = -1;
the_current_tok->f_string_multi_line_start_offset = -1; the_current_tok->f_string_multi_line_start_offset = -1;
the_current_tok->last_expr_buffer = NULL; the_current_tok->last_expr_buffer = NULL;
@ -2580,7 +2581,9 @@ f_string_middle:
tok->cur++; tok->cur++;
tok->line_start = current_tok->f_string_multi_line_start; tok->line_start = current_tok->f_string_multi_line_start;
int start = tok->lineno; int start = tok->lineno;
tok->lineno = tok->first_lineno;
tokenizer_mode *the_current_tok = TOK_GET_MODE(tok);
tok->lineno = the_current_tok->f_string_line_start;
if (current_tok->f_string_quote_size == 3) { if (current_tok->f_string_quote_size == 3) {
return MAKE_TOKEN(syntaxerror(tok, return MAKE_TOKEN(syntaxerror(tok,

View File

@ -53,6 +53,7 @@ typedef struct _tokenizer_mode {
int f_string_raw; int f_string_raw;
const char* f_string_start; const char* f_string_start;
const char* f_string_multi_line_start; const char* f_string_multi_line_start;
int f_string_line_start;
Py_ssize_t f_string_start_offset; Py_ssize_t f_string_start_offset;
Py_ssize_t f_string_multi_line_start_offset; Py_ssize_t f_string_multi_line_start_offset;