Versioning
Black 19.10b0, OS Windows 10 1803 and Python 3.7.2.
Is your feature request related to a problem? Please describe.
The problem is related to how black currently wraps arrays. For instance, smaller arrays such as [1,2,3] formats correctly to [1, 2, 3] while staying on a single line. Longer arrays, such as

becomes

Which uses too many lines. Note how a comma , is automatically added at the end of the array, thus likely triggering a phenomenon of this type. Removing the comma changes nothing, as it simply comes back. See ie. the black playground.
Describe the solution you'd like. I wish to use black for formatting, but with wrapping behavior similar to (or equal to) that of autopep8's formatting for such arrays as described. Which gives:

Describe alternatives you've considered
# fmt: off before a code block, and # fmt: on after. While this works, the array a) remains unformatted and b) stays only on one line that introduces a scrollbar which must be used to check the full content18.4a0 appear to be equivalent to fmt effect, primarily because formatting then appears to not be applied at all. I have not explored the consequences this has with other formatting behavior not related to this test case. The next version, 18.4a1, produces the exact same behavior as the behavior of 19.10b0 (also with the extra comma at the end of the then vertically formatted array)settings.json
C#
{
"python.pythonPath": ".venv\\Scripts\\python.exe",
"editor.acceptSuggestionOnEnter": "off",
"python.formatting.provider": "black",
//"python.formatting.provider": "autopep8",
"editor.formatOnSave": true,
"python.formatting.blackArgs": [
"--line-length",
"88"
],
"python.formatting.autopep8Args": [
"--max-line-length",
"88",
"--experimental"
]
}
I kind of agree with this. I wish long lists of scalar values would just wrap instead of being expanded one item per line. But that's what fmt:on/off is for. So trying to introduce heuristics to format lists in many different ways is perhaps complexity black should not have,
Maybe a simple threshold would be enough? Like "wrap to one line per item iif the wrap to the fewest lines needed would make the max number of items per lines less than
This way we would have:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2 ,3 ,4,
5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
with longest line containing 16 items > N, but since
long_items = ["long_item_number_1", "long_item_number_2",
"long_item_number_3", "long_item_number_4"]
has longest line only 2 items long < N, it would becomes
long_items = [
"long_item_number_1",
"long_item_number_2",
"long_item_number_3",
"long_item_number_4",
]
instead?
I'm going to try and work on this issue. My solution will split the list on the least amount of lines possible while meeting the pycodestyle standards, similar to what @iago-lito suggested.
Btw, this is not black's style
array = [1, 2, 3
4, 5, 6
]
This is
```
array = [
1, 2, 3, 4, 5, 6
]
@PravinthR Splitting to "the least amount of lines possible" leads to transforming
long_items = [
"long_item_number_1",
"long_item_number_2",
"long_item_number_3",
"long_item_number_4",
]
into
long_items = ["long_item_number_1", "long_item_number_2",
"long_item_number_3", "long_item_number_4"]
.. right? I think we want it the other way round :
@iago-lito good point, I forgot to add that I'd be following your idea of fewest line constraints in my implementation (where if splitting to the least amount of lines possible results in < N lines, then it will just put each item on a separate line)
I kind of like the way Black format list at the moment, but I agree that once you have a long list, it should wrap it.
In order to achieve that, I suggest adding a --list-line-length variable that indicates what is the maximum number of items that should be on each row. By default, this is set to 1 (keeping the existing behavior of Black)
For example:
Runnin black --list-line-length=8 on:
a = [1, 2, 3, 4, 5, 6, 7]
b = [1, 2, 3, 4, 5, 6, 7, 8]
Would keep it the same, but running on:
c = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Would format it into:
c = [
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11
]
What do you think?
@saroad2 Would this interact with this former suggestion? Or should only one be picked?
@iago-lito If I understand you correctly you suggest going the other way around: Wrap in one line as many elements as you can, and split to different lines if the number of elements is too small?
@saroad2 Yes. I am not sure the two ideas are completely opposite, tought :) For instance (correct if I'm wrong), with the min-max N=8, the following
long_items = [
"item_n_1", "item_n_2", "item_n_3", "item_n_4", "item_n_5", "item_n_6", "item_n_7",
"item_n_8", "item_n_9", "item_n10",
]
is not good, because it only has 7 items on its longest line,
so it would be reformatted to:
long_items = [
"item_n_1",
"item_n_2",
"item_n_3",
"item_n_4",
"item_n_5",
"item_n_6",
"item_n_7",
"item_n_8",
"item_n_9",
"item_n10",
]
if --list-line-length=1, but to
long_items = [
"item_n_1", "item_n_2",
"item_n_3", "item_n_4",
"item_n_5", "item_n_6",
"item_n_7", "item_n_8",
"item_n_9", "item_n10",
]
if --list-line-length=2, right?
Put it another way, I see the
I'll formulate this yet another way. Let us first distinguish between the line "length" (number of characters) and the line, say, "weight" (number of items).
small_list = ["a", "b", "c"]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2 ,3 ,4,
5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
--list-line-length-long. This is to encourage eitherlong_items = [
"item_n_1",
"item_n_2",
"item_n_3",
"item_n_4",
"item_n_5",
"item_n_6",
"item_n_7",
"item_n_8",
"item_n_9",
]
(by default), or
long_items = [
"item_n_1", "item_n_2",
"item_n_3", "item_n_4",
"item_n_5", "item_n_6",
"item_n_7", "item_n_8",
"item_n_9",
]
depending on user's preferences. Of course, if --list-line-length items do not even fit on one line, forget the user set option and reduce the value until they do.
What do you think?
(As a personal position, I suspect I would always prefer --list-line-length=1 for it eases reordering. But this opinion may not be shared.)
Your breakdown of the process is awesome! It is really making sense of everything.
Hope this would give the owners a few ideas for the future.
Any updates? I think this feature is a great idea, I've been struggling with some arrays splitting into a lot of ugly lines =(
Most helpful comment
Maybe a simple threshold would be enough? Like "" with N=5 or 6?
wrap to one line per itemiif thewrap to the fewest lines neededwould make the max number of items per lines less thanThis way we would have:
with longest line containing 16 items > N, but since
has longest line only 2 items long < N, it would becomes
instead?