From 5d0a469e8e2a6b83163ea27c9da654cb97f05e8a Mon Sep 17 00:00:00 2001 From: Zsolt Dollenstein Date: Sat, 9 Jun 2018 21:30:49 +0200 Subject: [PATCH 1/1] Fix string normalization sometimes producing invalid fstrings (#327) --- README.md | 5 +++++ black.py | 6 ++++++ tests/data/fstring.py | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ae640c..533a1f8 100644 --- a/README.md +++ b/README.md @@ -807,6 +807,11 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md). ## Change Log +### 18.6b3 + +* fixed improper formatting of f-strings with quotes inside interpolated + expressions (#322) + ### 18.6b2 * added `--config` (#65) diff --git a/black.py b/black.py index 6db661c..35daaa9 100644 --- a/black.py +++ b/black.py @@ -2549,6 +2549,12 @@ def normalize_string_quotes(leaf: Leaf) -> None: leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}" new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body) new_body = sub_twice(unescaped_new_quote, rf"\1\\{new_quote}", new_body) + if "f" in prefix.casefold(): + matches = re.findall(r"[^{]\{(.*?)\}[^}]", new_body) + for m in matches: + if "\\" in str(m): + # Do not introduce backslashes in interpolated expressions + return if new_quote == '"""' and new_body[-1:] == '"': # edge case: new_body = new_body[:-1] + '\\"' diff --git a/tests/data/fstring.py b/tests/data/fstring.py index b288cbc..4b33231 100644 --- a/tests/data/fstring.py +++ b/tests/data/fstring.py @@ -1,5 +1,21 @@ f"f-string without formatted values is just a string" f"{{NOT a formatted value}}" +f"{{NOT 'a' \"formatted\" \"value\"}}" f"some f-string with {a} {few():.2f} {formatted.values!r}" -f"{f'{nested} inner'} outer" +f'some f-string with {a} {few(""):.2f} {formatted.values!r}' +f"{f'''{'nested'} inner'''} outer" +f"\"{f'{nested} inner'}\" outer" f"space between opening braces: { {a for a in (1, 2, 3)}}" +f'Hello \'{tricky + "example"}\'' + +# output + +f"f-string without formatted values is just a string" +f"{{NOT a formatted value}}" +f'{{NOT \'a\' "formatted" "value"}}' +f"some f-string with {a} {few():.2f} {formatted.values!r}" +f'some f-string with {a} {few(""):.2f} {formatted.values!r}' +f"{f'''{'nested'} inner'''} outer" +f"\"{f'{nested} inner'}\" outer" +f"space between opening braces: { {a for a in (1, 2, 3)}}" +f'Hello \'{tricky + "example"}\'' -- 2.39.5