Skip to content

Commit ff7f731

Browse files
authored
gh-104658: Fix location of unclosed quote error for multiline f-strings (#104660)
1 parent 663c049 commit ff7f731

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

Lib/test/test_fstring.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,21 @@ def test_not_closing_quotes(self):
15581558
self.assertAllRaise(SyntaxError, "unterminated f-string literal", ['f"', "f'"])
15591559
self.assertAllRaise(SyntaxError, "unterminated triple-quoted f-string literal",
15601560
['f"""', "f'''"])
1561-
1561+
# Ensure that the errors are reported at the correct line number.
1562+
data = '''\
1563+
x = 1 + 1
1564+
y = 2 + 2
1565+
z = f"""
1566+
sdfjnsdfjsdf
1567+
sdfsdfs{1+
1568+
2} dfigdf {3+
1569+
4}sdufsd""
1570+
'''
1571+
try:
1572+
compile(data, "?", "exec")
1573+
except SyntaxError as e:
1574+
self.assertEqual(e.text, 'z = f"""')
1575+
self.assertEqual(e.lineno, 3)
15621576
def test_syntax_error_after_debug(self):
15631577
self.assertAllRaise(SyntaxError, "f-string: expecting a valid expression after '{'",
15641578
[

Parser/tokenizer.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ tok_underflow_interactive(struct tok_state *tok) {
11241124

11251125
static int
11261126
tok_underflow_file(struct tok_state *tok) {
1127-
if (tok->start == NULL) {
1127+
if (tok->start == NULL && !INSIDE_FSTRING(tok)) {
11281128
tok->cur = tok->inp = tok->buf;
11291129
}
11301130
if (tok->decoding_state == STATE_INIT) {
@@ -2250,6 +2250,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
22502250
the_current_tok->f_string_quote_size = quote_size;
22512251
the_current_tok->f_string_start = tok->start;
22522252
the_current_tok->f_string_multi_line_start = tok->line_start;
2253+
the_current_tok->f_string_line_start = tok->lineno;
22532254
the_current_tok->f_string_start_offset = -1;
22542255
the_current_tok->f_string_multi_line_start_offset = -1;
22552256
the_current_tok->last_expr_buffer = NULL;
@@ -2580,7 +2581,9 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct
25802581
tok->cur++;
25812582
tok->line_start = current_tok->f_string_multi_line_start;
25822583
int start = tok->lineno;
2583-
tok->lineno = tok->first_lineno;
2584+
2585+
tokenizer_mode *the_current_tok = TOK_GET_MODE(tok);
2586+
tok->lineno = the_current_tok->f_string_line_start;
25842587

25852588
if (current_tok->f_string_quote_size == 3) {
25862589
return MAKE_TOKEN(syntaxerror(tok,

Parser/tokenizer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ typedef struct _tokenizer_mode {
5353
int f_string_raw;
5454
const char* f_string_start;
5555
const char* f_string_multi_line_start;
56+
int f_string_line_start;
5657

5758
Py_ssize_t f_string_start_offset;
5859
Py_ssize_t f_string_multi_line_start_offset;

0 commit comments

Comments
 (0)