Skip to content

Commit 2184b76

Browse files
[3.11] gh-108843: fix ast.unparse for f-string with many quotes (#108980)
* [3.11] gh-108843: fix ast.unparse for f-string with many quotes * 📜🤖 Added by blurb_it. * simplify --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
1 parent 26b75b8 commit 2184b76

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

Lib/ast.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,13 +1175,29 @@ def visit_JoinedStr(self, node):
11751175

11761176
new_fstring_parts = []
11771177
quote_types = list(_ALL_QUOTES)
1178+
fallback_to_repr = False
11781179
for value, is_constant in fstring_parts:
1179-
value, quote_types = self._str_literal_helper(
1180+
value, new_quote_types = self._str_literal_helper(
11801181
value,
11811182
quote_types=quote_types,
11821183
escape_special_whitespace=is_constant,
11831184
)
11841185
new_fstring_parts.append(value)
1186+
if set(new_quote_types).isdisjoint(quote_types):
1187+
fallback_to_repr = True
1188+
break
1189+
quote_types = new_quote_types
1190+
1191+
if fallback_to_repr:
1192+
# If we weren't able to find a quote type that works for all parts
1193+
# of the JoinedStr, fallback to using repr and triple single quotes.
1194+
quote_types = ["'''"]
1195+
new_fstring_parts.clear()
1196+
for value, is_constant in fstring_parts:
1197+
value = repr('"' + value) # force repr to use single quotes
1198+
expected_prefix = "'\""
1199+
assert value.startswith(expected_prefix), repr(value)
1200+
new_fstring_parts.append(value[len(expected_prefix):-1])
11851201

11861202
value = "".join(new_fstring_parts)
11871203
quote_type = quote_types[0]

Lib/test/test_unparse.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,11 @@ def test_star_expr_assign_target_multiple(self):
662662
self.check_src_roundtrip("[a, b] = [c, d] = [e, f] = g")
663663
self.check_src_roundtrip("a, b = [c, d] = e, f = g")
664664

665+
def test_multiquote_joined_string(self):
666+
self.check_ast_roundtrip("f\"'''{1}\\\"\\\"\\\"\" ")
667+
self.check_ast_roundtrip("""f"'''{1}""\\"" """)
668+
self.check_ast_roundtrip("""f'""\"{1}''' """)
669+
self.check_ast_roundtrip("""f'""\"{1}""\\"' """)
665670

666671

667672
class DirectoryTestCase(ASTTestCase):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix an issue in :func:`ast.unparse` when unparsing f-strings containing many quote types.

0 commit comments

Comments
 (0)