Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[925] Improve multiline dictionary and list indentation for sole function parameter #3964

Merged
merged 14 commits into from Oct 25, 2023
3 changes: 2 additions & 1 deletion CHANGES.md
Expand Up @@ -12,7 +12,8 @@

### Preview style

<!-- Changes that affect Black's preview style -->
- Multiline dictionaries and lists that are the sole argument to a function are now
indented less (#3964)

### Configuration

Expand Down
26 changes: 26 additions & 0 deletions docs/the_black_code_style/future_style.md
Expand Up @@ -113,6 +113,32 @@ my_dict = {
}
```

### Improved multiline dictionary and list indentation for sole function parameter
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved

For better readability and less verticality, _Black_ now pairs parantheses ("(", ")")
with braces ("{", "}") and square brackets ("[", "]") on the same line for single
parameter function calls. For example:

```python
foo(
[
1,
2,
3,
]
)
```

will be changed to:

```python
foo([
1,
2,
3,
])
```

### Improved multiline string handling

_Black_ is smarter when formatting multiline strings, especially in function arguments,
Expand Down
13 changes: 13 additions & 0 deletions src/black/linegen.py
Expand Up @@ -815,6 +815,19 @@ def _first_right_hand_split(
tail_leaves.reverse()
body_leaves.reverse()
head_leaves.reverse()

if Preview.hug_parens_with_braces_and_square_brackets in line.mode:
if (
tail_leaves[0].type == token.RPAR
and tail_leaves[0].value
and tail_leaves[0].opening_bracket is head_leaves[-1]
henriholopainen marked this conversation as resolved.
Show resolved Hide resolved
and body_leaves[-1].type in [token.RBRACE, token.RSQB]
and body_leaves[-1].opening_bracket is body_leaves[0]
henriholopainen marked this conversation as resolved.
Show resolved Hide resolved
):
head_leaves = head_leaves + body_leaves[:1]
tail_leaves = body_leaves[-1:] + tail_leaves
body_leaves = body_leaves[1:-1]

head = bracket_split_build_line(
head_leaves, line, opening_bracket, component=_BracketSplitComponent.head
)
Expand Down
1 change: 1 addition & 0 deletions src/black/mode.py
Expand Up @@ -190,6 +190,7 @@ class Preview(Enum):
module_docstring_newlines = auto()
accept_raw_docstrings = auto()
fix_power_op_line_length = auto()
hug_parens_with_braces_and_square_brackets = auto()
allow_empty_first_line_before_new_block_or_comment = auto()


Expand Down
273 changes: 273 additions & 0 deletions tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py
@@ -0,0 +1,273 @@
# flags: --preview
def foo_brackets(request):
return JsonResponse(
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved
{
"var_1": foo,
"var_2": bar,
}
)

def foo_square_brackets(request):
return JsonResponse(
[
"var_1",
"var_2",
]
)

func({"a": 37, "b": 42, "c": 927, "aaaaaaaaaaaaaaaaaaaaaaaaa": 11111111111111111111111111111111111111111})

func(["random_string_number_one","random_string_number_two","random_string_number_three","random_string_number_four"])

func(
{
# expand me
'a':37,
'b':42,
'c':927
}
)

func(
[
'a',
'b',
'c',
]
)

func( # a
[ # b
"c", # c
"d", # d
"e", # e
] # f
) # g

func( # a
{ # b
"c": 1, # c
"d": 2, # d
"e": 3, # e
} # f
) # g

func(
# preserve me
[
"c",
"d",
"e",
]
)

func(
[ # preserve me but hug brackets
"c",
"d",
"e",
]
)

func(
[
# preserve me but hug brackets
"c",
"d",
"e",
]
)

func(
[
"c",
# preserve me but hug brackets
"d",
"e",
]
)

func(
[
"c",
"d",
"e",
# preserve me but hug brackets
]
)

func(
[
"c",
"d",
"e",
] # preserve me but hug brackets
)

func(
[
"c",
"d",
"e",
]
# preserve me
)

func([x for x in "short line"])
func([x for x in "long line long line long line long line long line long line long line"])
func([x for x in [x for x in "long line long line long line long line long line long line long line"]])

func({"short line"})
func({"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"})
func({{"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"}})

foooooooooooooooooooo(
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
)

baaaaaaaaaaaaar(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], {x}, "a string", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
)

# output
def foo_brackets(request):
return JsonResponse({
"var_1": foo,
"var_2": bar,
})


def foo_square_brackets(request):
return JsonResponse([
"var_1",
"var_2",
])


func({
"a": 37,
"b": 42,
"c": 927,
"aaaaaaaaaaaaaaaaaaaaaaaaa": 11111111111111111111111111111111111111111,
})

func([
"random_string_number_one",
"random_string_number_two",
"random_string_number_three",
"random_string_number_four",
])

func({
# expand me
"a": 37,
"b": 42,
"c": 927,
})

func([
"a",
"b",
"c",
])

func([ # a # b
"c", # c
"d", # d
"e", # e
]) # f # g

func({ # a # b
"c": 1, # c
"d": 2, # d
"e": 3, # e
}) # f # g

func(
# preserve me
[
"c",
"d",
"e",
]
)

func([ # preserve me but hug brackets
"c",
"d",
"e",
])

func([
# preserve me but hug brackets
"c",
"d",
"e",
])

func([
"c",
# preserve me but hug brackets
"d",
"e",
])

func([
"c",
"d",
"e",
# preserve me but hug brackets
])

func([
"c",
"d",
"e",
]) # preserve me but hug brackets

func(
[
"c",
"d",
"e",
]
# preserve me
)

func([x for x in "short line"])
func([
x for x in "long line long line long line long line long line long line long line"
])
func([
x
for x in [
x
for x in "long line long line long line long line long line long line long line"
]
])

func({"short line"})
func({
"long line",
"long long line",
"long long long line",
"long long long long line",
"long long long long long line",
})
func({
{
"long line",
"long long line",
"long long long line",
"long long long long line",
"long long long long long line",
}
})

foooooooooooooooooooo(
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
)

baaaaaaaaaaaaar(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], {x}, "a string", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
)
22 changes: 10 additions & 12 deletions tests/data/cases/preview_long_strings__regression.py
Expand Up @@ -962,19 +962,17 @@ def who(self):
)


xxxxxxx_xxxxxx_xxxxxxx = xxx(
[
xxxxxxxxxxxx(
xxxxxx_xxxxxxx=(
'((x.aaaaaaaaa = "xxxxxx.xxxxxxxxxxxxxxxxxxxxx") || (x.xxxxxxxxx ='
' "xxxxxxxxxxxx")) && '
# xxxxx xxxxxxxxxxxx xxxx xxx (xxxxxxxxxxxxxxxx) xx x xxxxxxxxx xx xxxxxx.
"(x.bbbbbbbbbbbb.xxx != "
'"xxx:xxx:xxx::cccccccccccc:xxxxxxx-xxxx/xxxxxxxxxxx/xxxxxxxxxxxxxxxxx") && '
)
xxxxxxx_xxxxxx_xxxxxxx = xxx([
xxxxxxxxxxxx(
xxxxxx_xxxxxxx=(
'((x.aaaaaaaaa = "xxxxxx.xxxxxxxxxxxxxxxxxxxxx") || (x.xxxxxxxxx ='
' "xxxxxxxxxxxx")) && '
# xxxxx xxxxxxxxxxxx xxxx xxx (xxxxxxxxxxxxxxxx) xx x xxxxxxxxx xx xxxxxx.
"(x.bbbbbbbbbbbb.xxx != "
'"xxx:xxx:xxx::cccccccccccc:xxxxxxx-xxxx/xxxxxxxxxxx/xxxxxxxxxxxxxxxxx") && '
)
]
)
)
])

if __name__ == "__main__":
for i in range(4, 8):
Expand Down