Handle backslashes in raw strings while normalizing (#105)

In raw strings, a single backslash means a literal backslash. It is also used to escape quotes if it precedes them. This means it is impossible to change the quote type for strings that contain an unescaped version of the other quote type.
Fixes #100
This commit is contained in:
Zsolt Dollenstein 2018-04-04 21:20:46 +01:00 committed by Łukasz Langa
parent f8e9544c93
commit 51b3b2624d
2 changed files with 19 additions and 4 deletions

View File

@ -1917,7 +1917,17 @@ def normalize_string_quotes(leaf: Leaf) -> None:
if first_quote_pos == -1:
return # There's an internal error
prefix = leaf.value[:first_quote_pos]
body = leaf.value[first_quote_pos + len(orig_quote):-len(orig_quote)]
if "r" in prefix.casefold():
if body.count(new_quote) != body.count(f"\\{new_quote}"):
# There's at least one unescaped new_quote in this raw string
# so converting is impossible
return
# Do not introduce or remove backslashes in raw strings
new_body = body
else:
new_body = body.replace(f"\\{orig_quote}", orig_quote).replace(
new_quote, f"\\{new_quote}"
)
@ -1932,7 +1942,6 @@ def normalize_string_quotes(leaf: Leaf) -> None:
if new_escape_count == orig_escape_count and orig_quote == '"':
return # Prefer double quotes
prefix = leaf.value[:first_quote_pos]
leaf.value = f"{prefix}{new_quote}{new_body}{new_quote}"

View File

@ -15,6 +15,9 @@
f'MOAR {" ".join([])}'
f"MOAR {' '.join([])}"
r"raw string ftw"
r'Date d\'expiration:(.*)'
r'Tricky "quote'
r'Not-so-tricky \"quote'
# output
@ -35,3 +38,6 @@
f'MOAR {" ".join([])}'
f"MOAR {' '.join([])}"
r"raw string ftw"
r"Date d\'expiration:(.*)"
r'Tricky "quote'
r"Not-so-tricky \"quote"