Skip to content

Commit 930df7b

Browse files
[3.12] gh-106396: Special-case empty format spec to gen empty JoinedStr node (GH-106401) (#106416)
(cherry picked from commit dfe4de2) Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
1 parent fda2970 commit 930df7b

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

Lib/test/test_fstring.py

+18
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,24 @@ def test_ast_line_numbers_with_parentheses(self):
496496
self.assertEqual(wat2.end_col_offset, 17)
497497
self.assertEqual(fstring.end_col_offset, 18)
498498

499+
def test_ast_fstring_empty_format_spec(self):
500+
expr = "f'{expr:}'"
501+
502+
mod = ast.parse(expr)
503+
self.assertEqual(type(mod), ast.Module)
504+
self.assertEqual(len(mod.body), 1)
505+
506+
fstring = mod.body[0].value
507+
self.assertEqual(type(fstring), ast.JoinedStr)
508+
self.assertEqual(len(fstring.values), 1)
509+
510+
fv = fstring.values[0]
511+
self.assertEqual(type(fv), ast.FormattedValue)
512+
513+
format_spec = fv.format_spec
514+
self.assertEqual(type(format_spec), ast.JoinedStr)
515+
self.assertEqual(len(format_spec.values), 0)
516+
499517
def test_docstring(self):
500518
def f():
501519
f'''Not a docstring'''
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
When the format specification of an f-string expression is empty, the parser now
2+
generates an empty :class:`ast.JoinedStr` node for it instead of an one-element
3+
:class:`ast.JoinedStr` with an empty string :class:`ast.Constant`.

Parser/action_helpers.c

+12
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,18 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in
10031003
if (!spec) {
10041004
return NULL;
10051005
}
1006+
1007+
// This is needed to keep compatibility with 3.11, where an empty format spec is parsed
1008+
// as an *empty* JoinedStr node, instead of having an empty constant in it.
1009+
if (asdl_seq_LEN(spec) == 1) {
1010+
expr_ty e = asdl_seq_GET(spec, 0);
1011+
if (e->kind == Constant_kind
1012+
&& PyUnicode_Check(e->v.Constant.value)
1013+
&& PyUnicode_GetLength(e->v.Constant.value) == 0) {
1014+
spec = _Py_asdl_expr_seq_new(0, arena);
1015+
}
1016+
}
1017+
10061018
expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, end_col_offset, p->arena);
10071019
if (!res) {
10081020
return NULL;

0 commit comments

Comments
 (0)