diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py index 6767a2463e9ed..78e215f91ada6 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py @@ -24,6 +24,12 @@ r"Test" R"Test" +# Block conversion if there is an unescaped quote just before the end of the triple +# quoted string +r'''\""''' +r'''""''' +r'\""' + 'This string will not include \ backslashes or newline characters.' diff --git a/crates/ruff_python_formatter/src/expression/string.rs b/crates/ruff_python_formatter/src/expression/string.rs index fdf6270982562..d6ed59f5ed8e5 100644 --- a/crates/ruff_python_formatter/src/expression/string.rs +++ b/crates/ruff_python_formatter/src/expression/string.rs @@ -323,14 +323,21 @@ fn preferred_quotes_raw( break true; } - if chars.peek() == Some(&configured_quote_char) { - // `""` or `''` - chars.next(); + match chars.peek() { + // We can't turn `r'''\""'''` into `r"""\"""""`, this would confuse the parser + // about where the closing triple quotes start + None => break true, + Some(next) if *next == configured_quote_char => { + // `""` or `''` + chars.next(); - if chars.peek() == Some(&configured_quote_char) { - // `"""` or `'''` - break true; + // We can't turn `r'''""'''` into `r""""""""`, nor can we have + // `"""` or `'''` respectively inside the string + if chars.peek().is_none() || chars.peek() == Some(&configured_quote_char) { + break true; + } } + _ => {} } } Some(_) => continue, diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap index 53afe8b2a34c0..a3ed8ac6ec4b0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__string.py.snap @@ -30,6 +30,12 @@ U"Test" r"Test" R"Test" +# Block conversion if there is an unescaped quote just before the end of the triple +# quoted string +r'''\""''' +r'''""''' +r'\""' + 'This string will not include \ backslashes or newline characters.' @@ -162,6 +168,12 @@ magic-trailing-comma = Respect r"Test" R"Test" +# Block conversion if there is an unescaped quote just before the end of the triple +# quoted string +r'''\""''' +r'''""''' +r'\""' + "This string will not include \ backslashes or newline characters." @@ -310,6 +322,12 @@ magic-trailing-comma = Respect r'Test' R'Test' +# Block conversion if there is an unescaped quote just before the end of the triple +# quoted string +r'''\""''' +r'''""''' +r'\""' + 'This string will not include \ backslashes or newline characters.'