From d6e2fdcc9ddc0c00ea0515fce4efde8fa54e9066 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 21 May 2019 15:03:24 -0700 Subject: [PATCH 1/2] bpo-37003: handle f-debug in ast-unparse, Ast-unparse was mistaking f'{x=}' for f"{x!r}" --- Lib/test/test_tools/test_unparse.py | 3 +++ Tools/parser/unparse.py | 31 ++++++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_tools/test_unparse.py b/Lib/test/test_tools/test_unparse.py index f3386f5e31a2df..e9ea294247bb8f 100644 --- a/Lib/test/test_tools/test_unparse.py +++ b/Lib/test/test_tools/test_unparse.py @@ -139,6 +139,9 @@ def test_fstrings(self): self.check_roundtrip(r"""f'{f"{0}"*3}'""") self.check_roundtrip(r"""f'{f"{y}"*3}'""") + def test_fstrings_debug(self): + self.check_roundtrip(r"""f'{f.a.b()=}'""") + def test_del_statement(self): self.check_roundtrip("del x, y, z") diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 385902ef4bc5e7..4f8ae08242d711 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -360,20 +360,23 @@ def _fstring_Constant(self, t, write): def _fstring_FormattedValue(self, t, write): write("{") - expr = io.StringIO() - Unparser(t.value, expr) - expr = expr.getvalue().rstrip("\n") - if expr.startswith("{"): - write(" ") # Separate pair of opening brackets as "{ {" - write(expr) - if t.conversion != -1: - conversion = chr(t.conversion) - assert conversion in "sra" - write(f"!{conversion}") - if t.format_spec: - write(":") - meth = getattr(self, "_fstring_" + type(t.format_spec).__name__) - meth(t.format_spec, write) + if t.expr_text: + write(t.expr_text) + else: + expr = io.StringIO() + Unparser(t.value, expr) + expr = expr.getvalue().rstrip("\n") + if expr.startswith("{"): + write(" ") # Separate pair of opening brackets as "{ {" + write(expr) + if t.conversion != -1: + conversion = chr(t.conversion) + assert conversion in "sra" + write(f"!{conversion}") + if t.format_spec: + write(":") + meth = getattr(self, "_fstring_" + type(t.format_spec).__name__) + meth(t.format_spec, write) write("}") def _Name(self, t): From 2a8d2ac5dd4b4700f094e6df020f9dee01bd3a55 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 21 May 2019 15:17:32 -0700 Subject: [PATCH 2/2] handle more cases --- Lib/test/test_tools/test_unparse.py | 5 +++++ Tools/parser/unparse.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_tools/test_unparse.py b/Lib/test/test_tools/test_unparse.py index e9ea294247bb8f..a6f33c1735e5d4 100644 --- a/Lib/test/test_tools/test_unparse.py +++ b/Lib/test/test_tools/test_unparse.py @@ -141,6 +141,11 @@ def test_fstrings(self): def test_fstrings_debug(self): self.check_roundtrip(r"""f'{f.a.b()=}'""") + self.check_roundtrip(r"""f'{f.a.b()=!s:20}'""") + self.check_roundtrip(r"""f'{f.a.b()=!r}'""") + self.check_roundtrip(r"""f'{f.a.b() = !r}'""") + self.check_roundtrip(r"""f'*{n=:+<30}*'""") + self.check_roundtrip(r"""f'{x=:.2f}'""") def test_del_statement(self): self.check_roundtrip("del x, y, z") diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 4f8ae08242d711..97b6461ed11616 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -369,14 +369,14 @@ def _fstring_FormattedValue(self, t, write): if expr.startswith("{"): write(" ") # Separate pair of opening brackets as "{ {" write(expr) - if t.conversion != -1: - conversion = chr(t.conversion) - assert conversion in "sra" - write(f"!{conversion}") - if t.format_spec: - write(":") - meth = getattr(self, "_fstring_" + type(t.format_spec).__name__) - meth(t.format_spec, write) + if t.conversion != -1: + conversion = chr(t.conversion) + assert conversion in "sra" + write(f"!{conversion}") + if t.format_spec: + write(":") + meth = getattr(self, "_fstring_" + type(t.format_spec).__name__) + meth(t.format_spec, write) write("}") def _Name(self, t):