From a6152aef7ab99395413f40be7fd4f6ae9abad934 Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Tue, 4 Jul 2023 11:42:36 +0200 Subject: [PATCH 1/4] gh-106396: Special-case empty format spec to gen empty JoinedStr node --- Lib/test/test_fstring.py | 18 ++++++++++++++++++ Parser/action_helpers.c | 10 ++++++++++ 2 files changed, 28 insertions(+) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index ba223ae124a8fb..cb14bba2602def 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -496,6 +496,24 @@ def test_ast_line_numbers_with_parentheses(self): self.assertEqual(wat2.end_col_offset, 17) self.assertEqual(fstring.end_col_offset, 18) + def test_ast_fstring_empty_format_spec(self): + expr = "f'{expr:}'" + + mod = ast.parse(expr) + self.assertEqual(type(mod), ast.Module) + self.assertEqual(len(mod.body), 1) + + fstring = mod.body[0].value + self.assertEqual(type(fstring), ast.JoinedStr) + self.assertEqual(len(fstring.values), 1) + + fv = fstring.values[0] + self.assertEqual(type(fv), ast.FormattedValue) + + format_spec = fv.format_spec + self.assertEqual(type(format_spec), ast.JoinedStr) + self.assertEqual(len(format_spec.values), 0) + def test_docstring(self): def f(): f'''Not a docstring''' diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 70c267bb212fcb..7f654b78f70fc6 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -997,6 +997,16 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in if (!spec) { return NULL; } + + if (asdl_seq_LEN(spec) == 1) { + expr_ty e = asdl_seq_GET(spec, 0); + if (e->kind == Constant_kind + && PyUnicode_Check(e->v.Constant.value) + && PyUnicode_GetLength(e->v.Constant.value) == 0) { + spec = _Py_asdl_expr_seq_new(0, arena); + } + } + expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, end_col_offset, p->arena); if (!res) { return NULL; From be54786a25951d6a95c3bf8e203a47126b3cd1fe Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 09:51:52 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst new file mode 100644 index 00000000000000..020fe0044878a8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst @@ -0,0 +1 @@ +When the format specification of an f-string expression is empty, the parser now generates an empty :class:`ast.JoinedStr` node for it instead of adding an empty :class:`ast.Constant`. From e13e90c30b8d2520d931735b0d720dfe2f40e43c Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Tue, 4 Jul 2023 11:53:47 +0200 Subject: [PATCH 3/4] Improve NEWS blurb --- .../2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst index 020fe0044878a8..c5767e97271d9d 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-04-09-51-45.gh-issue-106396.DmYp7x.rst @@ -1 +1,3 @@ -When the format specification of an f-string expression is empty, the parser now generates an empty :class:`ast.JoinedStr` node for it instead of adding an empty :class:`ast.Constant`. +When the format specification of an f-string expression is empty, the parser now +generates an empty :class:`ast.JoinedStr` node for it instead of an one-element +:class:`ast.JoinedStr` with an empty string :class:`ast.Constant`. From 85ebc869091f14fa3901455868d7dd4a0a222eaf Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Tue, 4 Jul 2023 13:19:12 +0200 Subject: [PATCH 4/4] Add comment --- Parser/action_helpers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 7f654b78f70fc6..36e0750220a30d 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -998,6 +998,8 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in return NULL; } + // This is needed to keep compatibility with 3.11, where an empty format spec is parsed + // as an *empty* JoinedStr node, instead of having an empty constant in it. if (asdl_seq_LEN(spec) == 1) { expr_ty e = asdl_seq_GET(spec, 0); if (e->kind == Constant_kind