Alternate quotes for strings inside f-strings in preview (#13860)

This commit is contained in:
Micha Reiser 2024-10-23 07:57:53 +02:00 committed by GitHub
parent f335fe4d4a
commit 2f88f84972
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 556 additions and 118 deletions

View file

@ -941,7 +941,7 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
log.info(
- "Skipping:"
- f" {desc['db_id']} {foo('bar',x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
+ f'Skipping: {desc["db_id"]} {foo("bar", x=123)} {"foo" != "bar"} {(x := "abc=")} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f"Skipping: {desc['db_id']} {foo('bar', x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(
@ -965,7 +965,7 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
log.info(
- "Skipping:"
- f" {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
+ f'Skipping: {"a" == "b" == "c" == "d"} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f"Skipping: {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(
@ -1406,7 +1406,7 @@ log.info(
)
log.info(
f'Skipping: {desc["db_id"]} {foo("bar", x=123)} {"foo" != "bar"} {(x := "abc=")} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f"Skipping: {desc['db_id']} {foo('bar', x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(
@ -1422,7 +1422,7 @@ log.info(
)
log.info(
f'Skipping: {"a" == "b" == "c" == "d"} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f"Skipping: {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(

View file

@ -1201,10 +1201,10 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
+ "With single quote: ' "
+ f" {my_dict['foo']}"
+ ' With double quote: " '
+ f' {my_dict["bar"]}'
+ f" {my_dict['bar']}"
)
+
+s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:\'{my_dict["foo"]}\''
+s = f"Lorem Ipsum is simply dummy text of the printing and typesetting industry:'{my_dict['foo']}'"
```
## Ruff Output
@ -1839,10 +1839,10 @@ s = (
"With single quote: ' "
f" {my_dict['foo']}"
' With double quote: " '
f' {my_dict["bar"]}'
f" {my_dict['bar']}"
)
s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:\'{my_dict["foo"]}\''
s = f"Lorem Ipsum is simply dummy text of the printing and typesetting industry:'{my_dict['foo']}'"
```
## Black Output

View file

@ -100,6 +100,8 @@ x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 8
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb' = } ccccccccccccccc"
# Multiple larger expressions which exceeds the line length limit. Here, we need to decide
# whether to split at the first or second expression. This should work similarly to the
@ -150,18 +152,37 @@ xxxxxxx = f"{
{'aaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbb', 'cccccccccccccccccccccccccc'}
}"
#############################################################################################
# Quotes
#############################################################################################
f"foo 'bar' {x}"
f"foo \"bar\" {x}"
f'foo "bar" {x}'
f'foo \'bar\' {x}'
f"foo {"bar"}"
f"foo {'\'bar\''}"
f"single quoted '{x}' double quoted \"{x}\"" # Same number of quotes => use preferred quote style
f"single quote ' {x} double quoted \"{x}\"" # More double quotes => use single quotes
f"single quoted '{x}' double quote \" {x}" # More single quotes => use double quotes
fr"single quotes ' {x}" # Keep double because `'` can't be escaped
fr'double quotes " {x}' # Keep single because `"` can't be escaped
fr'flip quotes {x}' # Use preferred quotes, because raw string contains now quotes.
# Here, the formatter will remove the escapes which is correct because they aren't allowed
# pre 3.12. This means we can assume that the f-string is used in the context of 3.12.
f"foo {'\'bar\''}"
f"foo {'\"bar\"'}"
# Quotes inside the expressions have no impact on the quote selection of the outer string.
# Required so that the following two examples result in the same formatting.
f'foo {10 + len("bar")}'
f"foo {10 + len('bar')}"
# Pre 312, preserve the outer quotes if the f-string contains quotes in the debug expression
f'foo {10 + len("bar")=}'
f'''foo {10 + len('''bar''')=}'''
f'''foo {10 + len('bar')=}''' # Fine to change the quotes because it uses triple quotes
# Triple-quoted strings
# It's ok to use the same quote char for the inner string if it's single-quoted.
@ -170,6 +191,16 @@ f"""test {"inner"}"""
# But if the inner string is also triple-quoted then we should preserve the existing quotes.
f"""test {'''inner'''}"""
# It's not okay to change the quote style if the inner string is triple quoted and contains a quote.
f'{"""other " """}'
f'{"""other " """ + "more"}'
f'{b"""other " """}'
f'{f"""other " """}'
# Not valid Pre 3.12
f"""test {f'inner {'''inner inner'''}'}"""
f"""test {f'''inner {"""inner inner"""}'''}"""
# Magic trailing comma
#
# The expression formatting will result in breaking it across multiple lines with a
@ -318,7 +349,7 @@ hello {
# Implicit concatenated f-string containing quotes
_ = (
'This string should change its quotes to double quotes'
f'This string uses double quotes in an expression {"woah"}'
f'This string uses double quotes in an expression {"it's a quote"}'
f'This f-string does not use any quotes.'
)
```
@ -429,13 +460,15 @@ aaaaaaaaaaa = (
# This should never add the optional parentheses because even after adding them, the
# f-string exceeds the line length limit.
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb"} ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'} ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 8
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
} ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb' = } ccccccccccccccc"
# Multiple larger expressions which exceeds the line length limit. Here, we need to decide
# whether to split at the first or second expression. This should work similarly to the
@ -496,18 +529,37 @@ xxxxxxx = f"{
}
}"
#############################################################################################
# Quotes
#############################################################################################
f"foo 'bar' {x}"
f'foo "bar" {x}'
f'foo "bar" {x}'
f"foo 'bar' {x}"
f"foo {"bar"}"
f"foo {'\'bar\''}"
f"foo {'bar'}"
f"single quoted '{x}' double quoted \"{x}\"" # Same number of quotes => use preferred quote style
f'single quote \' {x} double quoted "{x}"' # More double quotes => use single quotes
f"single quoted '{x}' double quote \" {x}" # More single quotes => use double quotes
rf"single quotes ' {x}" # Keep double because `'` can't be escaped
rf'double quotes " {x}' # Keep single because `"` can't be escaped
rf"flip quotes {x}" # Use preferred quotes, because raw string contains now quotes.
# Here, the formatter will remove the escapes which is correct because they aren't allowed
# pre 3.12. This means we can assume that the f-string is used in the context of 3.12.
f"foo {"'bar'"}"
f"foo {'"bar"'}"
# Quotes inside the expressions have no impact on the quote selection of the outer string.
# Required so that the following two examples result in the same formatting.
f"foo {10 + len('bar')}"
f"foo {10 + len('bar')}"
# Pre 312, preserve the outer quotes if the f-string contains quotes in the debug expression
f'foo {10 + len("bar")=}'
f"""foo {10 + len('''bar''')=}"""
f"""foo {10 + len('bar')=}""" # Fine to change the quotes because it uses triple quotes
# Triple-quoted strings
# It's ok to use the same quote char for the inner string if it's single-quoted.
@ -516,6 +568,16 @@ f"""test {"inner"}"""
# But if the inner string is also triple-quoted then we should preserve the existing quotes.
f"""test {'''inner'''}"""
# It's not okay to change the quote style if the inner string is triple quoted and contains a quote.
f'{"""other " """}'
f'{"""other " """ + "more"}'
f'{b"""other " """}'
f'{f"""other " """}'
# Not valid Pre 3.12
f"""test {f"inner {'''inner inner'''}"}"""
f"""test {f'''inner {"""inner inner"""}'''}"""
# Magic trailing comma
#
# The expression formatting will result in breaking it across multiple lines with a
@ -662,7 +724,7 @@ hello {
# Implicit concatenated f-string containing quotes
_ = (
"This string should change its quotes to double quotes"
f'This string uses double quotes in an expression {"woah"}'
f"This string uses double quotes in an expression {"it's a quote"}"
f"This f-string does not use any quotes."
)
```
@ -778,6 +840,8 @@ x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 8
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb' = } ccccccccccccccc"
# Multiple larger expressions which exceeds the line length limit. Here, we need to decide
# whether to split at the first or second expression. This should work similarly to the
@ -828,18 +892,37 @@ xxxxxxx = f"{
{'aaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbb', 'cccccccccccccccccccccccccc'}
}"
#############################################################################################
# Quotes
#############################################################################################
f"foo 'bar' {x}"
f'foo "bar" {x}'
f'foo "bar" {x}'
f"foo 'bar' {x}"
f"foo {"bar"}"
f"foo {'\'bar\''}"
f"single quoted '{x}' double quoted \"{x}\"" # Same number of quotes => use preferred quote style
f'single quote \' {x} double quoted "{x}"' # More double quotes => use single quotes
f"single quoted '{x}' double quote \" {x}" # More single quotes => use double quotes
rf"single quotes ' {x}" # Keep double because `'` can't be escaped
rf'double quotes " {x}' # Keep single because `"` can't be escaped
rf"flip quotes {x}" # Use preferred quotes, because raw string contains now quotes.
# Here, the formatter will remove the escapes which is correct because they aren't allowed
# pre 3.12. This means we can assume that the f-string is used in the context of 3.12.
f"foo {'\'bar\''}"
f"foo {'\"bar\"'}"
# Quotes inside the expressions have no impact on the quote selection of the outer string.
# Required so that the following two examples result in the same formatting.
f'foo {10 + len("bar")}'
f"foo {10 + len('bar')}"
# Pre 312, preserve the outer quotes if the f-string contains quotes in the debug expression
f'foo {10 + len("bar")=}'
f'''foo {10 + len('''bar''')=}'''
f"""foo {10 + len('bar')=}""" # Fine to change the quotes because it uses triple quotes
# Triple-quoted strings
# It's ok to use the same quote char for the inner string if it's single-quoted.
@ -848,6 +931,16 @@ f"""test {"inner"}"""
# But if the inner string is also triple-quoted then we should preserve the existing quotes.
f"""test {'''inner'''}"""
# It's not okay to change the quote style if the inner string is triple quoted and contains a quote.
f'{"""other " """}'
f'{"""other " """ + "more"}'
f'{b"""other " """}'
f'{f"""other " """}'
# Not valid Pre 3.12
f"""test {f'inner {'''inner inner'''}'}"""
f"""test {f'''inner {"""inner inner"""}'''}"""
# Magic trailing comma
#
# The expression formatting will result in breaking it across multiple lines with a
@ -994,7 +1087,7 @@ hello {
# Implicit concatenated f-string containing quotes
_ = (
'This string should change its quotes to double quotes'
f'This string uses double quotes in an expression {"woah"}'
f'This string uses double quotes in an expression {"it's a quote"}'
f'This f-string does not use any quotes.'
)
```
@ -1022,7 +1115,7 @@ _ = (
" f()\n"
# XXX: The following line changes depending on whether the tests
# are run through the interactive interpreter or with -m
@@ -67,64 +67,72 @@
@@ -67,29 +67,31 @@
x = f"{a}"
x = f"{
a = }"
@ -1052,16 +1145,17 @@ _ = (
# This should never add the optional parentheses because even after adding them, the
# f-string exceeds the line length limit.
-x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" } ccccccccccccccc"
+x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb"} ccccccccccccccc"
+x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'} ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
-x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 8
- "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" } ccccccccccccccc"
+x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 8
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+ 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
+} ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" = } ccccccccccccccc"
x = f"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { # comment 9
@@ -98,35 +100,41 @@
# Multiple larger expressions which exceeds the line length limit. Here, we need to decide
# whether to split at the first or second expression. This should work similarly to the
# assignment statement formatting where we split from right to left in preview mode.
@ -1119,7 +1213,7 @@ _ = (
x = f"{ # comment 13
{'x': 1, 'y': 2} = }"
# But, if there's a format specifier or a conversion flag then we don't need to add
@@ -139,7 +147,11 @@
@@ -141,7 +149,11 @@
}"
# And, split the expression itself because it exceeds the line length.
xxxxxxx = f"{
@ -1131,14 +1225,36 @@ _ = (
+ }
}"
# Quotes
@@ -152,13 +164,13 @@
#############################################################################################
@@ -151,7 +163,7 @@
f'foo "bar" {x}'
f'foo "bar" {x}'
f"foo 'bar' {x}"
-f"foo {"bar"}"
+f"foo {'bar'}"
f"single quoted '{x}' double quoted \"{x}\"" # Same number of quotes => use preferred quote style
f'single quote \' {x} double quoted "{x}"' # More double quotes => use single quotes
@@ -163,23 +175,23 @@
# Here, the formatter will remove the escapes which is correct because they aren't allowed
# pre 3.12. This means we can assume that the f-string is used in the context of 3.12.
-f"foo {'\'bar\''}"
-f"foo {'\"bar\"'}"
+f"foo {"'bar'"}"
+f"foo {'"bar"'}"
# Quotes inside the expressions have no impact on the quote selection of the outer string.
# Required so that the following two examples result in the same formatting.
-f'foo {10 + len("bar")}'
f"foo {10 + len('bar')}"
+f"foo {10 + len('bar')}"
# Pre 312, preserve the outer quotes if the f-string contains quotes in the debug expression
f'foo {10 + len("bar")=}'
-f'''foo {10 + len('''bar''')=}'''
+f"""foo {10 + len('''bar''')=}"""
f"""foo {10 + len('bar')=}""" # Fine to change the quotes because it uses triple quotes
# Triple-quoted strings
# It's ok to use the same quote char for the inner string if it's single-quoted.
@ -1148,7 +1264,16 @@ _ = (
# But if the inner string is also triple-quoted then we should preserve the existing quotes.
f"""test {'''inner'''}"""
@@ -171,63 +183,66 @@
@@ -190,7 +202,7 @@
f'{f"""other " """}'
# Not valid Pre 3.12
-f"""test {f'inner {'''inner inner'''}'}"""
+f"""test {f"inner {'''inner inner'''}"}"""
f"""test {f'''inner {"""inner inner"""}'''}"""
# Magic trailing comma
@@ -202,63 +214,66 @@
f"aaaaaaa {['aaaaaaaaaaaaaaa', 'bbbbbbbbbbbbb', 'ccccccccccccccccc', 'ddddddddddddddd', 'eeeeeeeeeeeeee']} aaaaaaa"
# And, if the trailing comma is already present, we still need to remove it.
@ -1243,7 +1368,7 @@ _ = (
# comment} cccccccccc"""
# Conversion flags
@@ -235,24 +250,21 @@
@@ -266,24 +281,21 @@
# This is not a valid Python code because of the additional whitespace between the `!`
# and conversion type. But, our parser isn't strict about this. This should probably be
# removed once we have a strict parser.
@ -1275,7 +1400,7 @@ _ = (
x = f"""
{ # comment 22
@@ -261,19 +273,19 @@
@@ -292,19 +304,19 @@
# Here, the debug expression is in a nested f-string so we should start preserving
# whitespaces from that point onwards. This means we should format the outer f-string.
@ -1303,7 +1428,7 @@ _ = (
# comment 27
# comment 28
} woah {x}"
@@ -287,27 +299,27 @@
@@ -318,27 +330,27 @@
if indent2:
foo = f"""hello world
hello {
@ -1343,9 +1468,10 @@ _ = (
# Implicit concatenated f-string containing quotes
_ = (
- 'This string should change its quotes to double quotes'
+ "This string should change its quotes to double quotes"
f'This string uses double quotes in an expression {"woah"}'
- f'This string uses double quotes in an expression {"it's a quote"}'
- f'This f-string does not use any quotes.'
+ "This string should change its quotes to double quotes"
+ f"This string uses double quotes in an expression {"it's a quote"}"
+ f"This f-string does not use any quotes."
)
```

View file

@ -10,6 +10,17 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression
# Quotes reuse
f"{'a'}"
# 312+, it's okay to change the outer quotes even when there's a debug expression using the same quotes
f'foo {10 + len("bar")=}'
f'''foo {10 + len("""bar""")=}'''
# 312+, it's okay to change the quotes here without creating an invalid f-string
f'{"""other " """}'
f'{"""other " """ + "more"}'
f'{b"""other " """}'
f'{f"""other " """}'
```
## Outputs
@ -35,6 +46,16 @@ source_type = Python
# Quotes reuse
f"{'a'}"
# 312+, it's okay to change the outer quotes even when there's a debug expression using the same quotes
f'foo {10 + len("bar")=}'
f'''foo {10 + len("""bar""")=}'''
# 312+, it's okay to change the quotes here without creating an invalid f-string
f'{"""other " """}'
f'{"""other " """ + "more"}'
f'{b"""other " """}'
f'{f"""other " """}'
```
@ -42,10 +63,22 @@ f"{'a'}"
```diff
--- Stable
+++ Preview
@@ -3,4 +3,4 @@
# version isn't set.
@@ -6,11 +6,11 @@
f"{'a'}"
# Quotes reuse
-f"{'a'}"
+f"{"a"}"
# 312+, it's okay to change the outer quotes even when there's a debug expression using the same quotes
-f'foo {10 + len("bar")=}'
-f'''foo {10 + len("""bar""")=}'''
+f"foo {10 + len("bar")=}"
+f"""foo {10 + len("""bar""")=}"""
# 312+, it's okay to change the quotes here without creating an invalid f-string
-f'{"""other " """}'
-f'{"""other " """ + "more"}'
-f'{b"""other " """}'
-f'{f"""other " """}'
+f"{'''other " '''}"
+f"{'''other " ''' + 'more'}"
+f"{b'''other " '''}"
+f"{f'''other " '''}"
```