Skip to content

Commit 7e70e2e

Browse files
authored
[3.12] gh-112243: Don't include comments in f-string debug expressions (GH-112284) (#112285)
(cherry picked from commit d59feb5)
1 parent d4fd165 commit 7e70e2e

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

Lib/test/test_fstring.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,9 @@ def __repr__(self):
15791579
self.assertEqual(f'X{x = }Y', 'Xx = '+repr(x)+'Y')
15801580
self.assertEqual(f"sadsd {1 + 1 = :{1 + 1:1d}f}", "sadsd 1 + 1 = 2.000000")
15811581

1582+
self.assertEqual(f"{1+2 = # my comment
1583+
}", '1+2 = \n 3')
1584+
15821585
# These next lines contains tabs. Backslash escapes don't
15831586
# work in f-strings.
15841587
# patchcheck doesn't like these tabs. So the only way to test
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Don't include comments in f-string debug expressions. Patch by Pablo Galindo

Parser/tokenizer.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,11 +406,55 @@ set_fstring_expr(struct tok_state* tok, struct token *token, char c) {
406406
return 0;
407407
}
408408

409-
PyObject *res = PyUnicode_DecodeUTF8(
410-
tok_mode->last_expr_buffer,
411-
tok_mode->last_expr_size - tok_mode->last_expr_end,
412-
NULL
413-
);
409+
PyObject *res = NULL;
410+
411+
// Check if there is a # character in the expression
412+
int hash_detected = 0;
413+
for (Py_ssize_t i = 0; i < tok_mode->last_expr_size - tok_mode->last_expr_end; i++) {
414+
if (tok_mode->last_expr_buffer[i] == '#') {
415+
hash_detected = 1;
416+
break;
417+
}
418+
}
419+
420+
if (hash_detected) {
421+
Py_ssize_t input_length = tok_mode->last_expr_size - tok_mode->last_expr_end;
422+
char *result = (char *)PyObject_Malloc((input_length + 1) * sizeof(char));
423+
if (!result) {
424+
return -1;
425+
}
426+
427+
Py_ssize_t i = 0;
428+
Py_ssize_t j = 0;
429+
430+
for (i = 0, j = 0; i < input_length; i++) {
431+
if (tok_mode->last_expr_buffer[i] == '#') {
432+
// Skip characters until newline or end of string
433+
while (tok_mode->last_expr_buffer[i] != '\0' && i < input_length) {
434+
if (tok_mode->last_expr_buffer[i] == '\n') {
435+
result[j++] = tok_mode->last_expr_buffer[i];
436+
break;
437+
}
438+
i++;
439+
}
440+
} else {
441+
result[j++] = tok_mode->last_expr_buffer[i];
442+
}
443+
}
444+
445+
result[j] = '\0'; // Null-terminate the result string
446+
res = PyUnicode_DecodeUTF8(result, j, NULL);
447+
PyObject_Free(result);
448+
} else {
449+
res = PyUnicode_DecodeUTF8(
450+
tok_mode->last_expr_buffer,
451+
tok_mode->last_expr_size - tok_mode->last_expr_end,
452+
NULL
453+
);
454+
455+
}
456+
457+
414458
if (!res) {
415459
return -1;
416460
}

0 commit comments

Comments
 (0)