From efcd039482de513eb2bb5f4f7688c51985c40494 Mon Sep 17 00:00:00 2001 From: Zsolt Dollenstein Date: Sun, 10 Jun 2018 09:39:24 +0100 Subject: [PATCH] Fix string normalization eating all backslashes above 3 --- README.md | 2 ++ black.py | 8 ++++---- tests/data/string_quotes.py | 2 ++ tests/data/string_wayne.py | 1 - 4 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 tests/data/string_wayne.py diff --git a/README.md b/README.md index 67cd613..0f22482 100644 --- a/README.md +++ b/README.md @@ -816,6 +816,8 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md). * fixed unnecessary slowdown on AST nodes with very many siblings +* fixed cannibalizing backslashes during string normalization + ### 18.6b2 diff --git a/black.py b/black.py index a405bad..9d9bada 100644 --- a/black.py +++ b/black.py @@ -2529,8 +2529,8 @@ def normalize_string_quotes(leaf: Leaf) -> None: prefix = leaf.value[:first_quote_pos] unescaped_new_quote = re.compile(rf"(([^\\]|^)(\\\\)*){new_quote}") - escaped_new_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{new_quote}") - escaped_orig_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{orig_quote}") + escaped_new_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){new_quote}") + escaped_orig_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){orig_quote}") body = leaf.value[first_quote_pos + len(orig_quote) : -len(orig_quote)] if "r" in prefix.casefold(): if unescaped_new_quote.search(body): @@ -2541,10 +2541,10 @@ def normalize_string_quotes(leaf: Leaf) -> None: # Do not introduce or remove backslashes in raw strings new_body = body else: - # remove unnecessary quotes + # remove unnecessary escapes new_body = sub_twice(escaped_new_quote, rf"\1\2{new_quote}", body) if body != new_body: - # Consider the string without unnecessary quotes as the original + # Consider the string without unnecessary escapes as the original body = new_body leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}" new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body) diff --git a/tests/data/string_quotes.py b/tests/data/string_quotes.py index 807f866..1994dd2 100644 --- a/tests/data/string_quotes.py +++ b/tests/data/string_quotes.py @@ -43,6 +43,7 @@ re.compile(r'[\\"]') "unnecessary \'\'escaping" '\\""' "\\''" +'Lots of \\\\\\\\\'quotes\'' # output @@ -91,3 +92,4 @@ re.compile(r'[\\"]') "unnecessary ''escaping" '\\""' "\\''" +"Lots of \\\\\\\\'quotes'" diff --git a/tests/data/string_wayne.py b/tests/data/string_wayne.py deleted file mode 100644 index 702349e..0000000 --- a/tests/data/string_wayne.py +++ /dev/null @@ -1 +0,0 @@ -u'"Based on the Saturday Night Live sketch of the same name, Wayne\'s World is a wacky, irreverent pop culture comedy about the adventures of two amiably aimless metal head friends, Wayne (Mike Myers) and Garth (Dana Carvey). From Wayne\'s basement, the pair broadcast a talk show called \\\\"Wayne\'s World\\\\" on local public access television. The show comes to the attention of a sleazy network executive (Rob Lowe) who wants to produce a big budget version of \\\\"Wayne\'s World\\\\" and he also wants Wayne\'s girlfriend, a rock singer named Cassandra (Tia Carrere). Wayne and Garth have to battle the executive not only to save their show, but also Cassandra. Director Penelope Spheeris, Myers and Carvey hang a lot of silly, but funny, jokes on this thin plot, and the energy of the cast as well as the wild pop culture references make Wayne\'s World a cut above the average Saturday Night Live spin off movie.\\\\n"' -- 2.39.2