Black shouldn't merge multi-line string when last character on the line is '\n'
Describe the style change
It may be related to https://github.com/psf/black/issues/1467, but it seems #1467 is fixed when trying on https://black.now.sh/ while this one still fail.
Currently, string split in multiple lines are merged together.
Input:
ValueError(
'Invalid input:\n'
f' * x={x}\n'
f' * y={y}\n'
f' * z={z}'
)
When the last character of the line is a \n, the code formatting match how the string will be displayed:
Invalid input:
* x=12
* y=41
* z=0
Examples in the current Black style
Black merge all lines together, while keeping segments separated, which hurts readability:
ValueError("Invalid input:\n" f" * x={x}\n" f" * y={y}\n" f" * z={z}")
Desired style
Black shouldn't merge the lines together and keep the original formatting:
ValueError(
'Invalid input:\n'
f' * x={x}\n'
f' * y={y}\n'
f' * z={z}'
)
Looks like a duplicate of #1467 (not sure, this should stay open for now). IMHO, I wouldn't exactly trust the online Black demo at https://black.now.sh, from my experience it seems unreliable for certain reproducing conditions.
@Conchylicultor With the introduction of #1132, the segments are now merged together.
@Conchylicultor With the introduction of #1132, the segments are now merged together.
But I don't want black to merge the string. Black should respect the \n, similarly to https://github.com/psf/black/issues/1467.
msg = (
'Instructions:\n'
' 1) ...\n'
' 2) ...\n'
' 3) ...'
)
Is more readable than:
msg = 'Instructions:\n 1) ...\n 2) ...\n 3) ...'
As code formatting match the way the string is displayed.
@Conchylicultor The case described by this issue is a bit different than #1467, since #1467 relates directly to #1132, whereas this issue does not.
I'm not saying that black shouldn't act the way you describe in this isue and the way described in #1467. I'm just pointing out that the code changes necessary in the two cases are very different.
@bbugyi200, thank you for the clarification. I understand now that #1132 wasn't trying to solve this issue.
As a workaround you can put explicit + operators to prevent black from merging the string.
using explicit "+" still results in the strings merging into 1 (using version=black, 21.12b0)
My personal opinion is that this issue should be closed and #1467 should remain open.
Moreover, I think that this issue's example should continue to be formatted as it is currently (when the --experimental-string-processing flag is set, that is), since short strings should always be merged into one string when possible IMO. When string splitting / wrapping is necessary (i.e. for long strings), however, I agree that black should try to respect newlines in the string.
This issue is kind of popularizes use of "+" for string concatenation for me. 🥲
a = (
"&SortByValue=priority&SortByOrder=asc"
+ "&IndexToStartPaging={3}"
+ "&NumberOfElementsToShow={2}"
+ "&CacheDurationMinutes=0"
+ "&AllowAlternativeResults=false"
)
Responding to a few previous points:
- The issue as originally written makes sense to me and I'd welcome a PR adding this change to our preview style. We'll have to see how much impact this has on existing codebases though.
- Regarding the discussion on whether this is a dupe of #1467, that issue is specific to the unstable string-processing feature, while this issue affects Black's current stable style, so I think they're best kept separate.
- Re @Andrej730's comment: your example isn't affected by this issue since there are no
\nin the string. However, maybe a case should be made that Black also shouldn't put adjacent strings on the same line even if they don't contain newlines.
The simplest and most effective rule is to add line breaks after each string literal, regardless of the content (e.g. "\n"), if the number of concatenated string literals is ≥ 2.
Inputs:
f(
"Data: "
f"{foo: <4} | "
f"{bar:8d} | "
f"{qux: >16}"
)
f( "Data: " f"{foo: <4} | "
f"{bar:8d} | " f"{qux: >16}" )
f( "Data: " f"{foo: <4} | " f"{bar:8d} | " f"{qux: >16}" )
Desired output 😀:
f(
"Data: "
f"{foo: <4} | "
f"{bar:8d} | "
f"{qux: >16}"
)
Current output ☹️:
f("Data: " f"{foo: <4} | " f"{bar:8d} | " f"{qux: >16}")
(Copied over from closed duplicate.)