Handle more huggable immediately nested parens/brackets. (#4012)
Fixes #4011
This commit is contained in:
parent
d93a942a79
commit
11da02da72
@ -14,6 +14,9 @@
|
||||
|
||||
<!-- Changes that affect Black's preview style -->
|
||||
|
||||
- Additional cases of immediately nested tuples, lists, and dictionaries are now
|
||||
indented less (#4012)
|
||||
|
||||
### Configuration
|
||||
|
||||
<!-- Changes to how Black can be configured -->
|
||||
|
12
docs/conf.py
12
docs/conf.py
@ -149,15 +149,13 @@ def make_pypi_svg(version: str) -> None:
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(
|
||||
latex_documents = [(
|
||||
master_doc,
|
||||
"black.tex",
|
||||
"Documentation for Black",
|
||||
"Łukasz Langa and contributors to Black",
|
||||
"manual",
|
||||
)
|
||||
]
|
||||
)]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
@ -172,8 +170,7 @@ def make_pypi_svg(version: str) -> None:
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
texinfo_documents = [(
|
||||
master_doc,
|
||||
"Black",
|
||||
"Documentation for Black",
|
||||
@ -181,8 +178,7 @@ def make_pypi_svg(version: str) -> None:
|
||||
"Black",
|
||||
"The uncompromising Python code formatter",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
)]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
@ -116,8 +116,7 @@ my_dict = {
|
||||
### Improved multiline dictionary and list indentation for sole function parameter
|
||||
|
||||
For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
|
||||
with braces ("{", "}") and square brackets ("[", "]") on the same line for single
|
||||
parameter function calls. For example:
|
||||
with braces ("{", "}") and square brackets ("[", "]") on the same line. For example:
|
||||
|
||||
```python
|
||||
foo(
|
||||
@ -127,6 +126,14 @@ foo(
|
||||
3,
|
||||
]
|
||||
)
|
||||
|
||||
nested_array = [
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
will be changed to:
|
||||
@ -137,6 +144,12 @@ foo([
|
||||
2,
|
||||
3,
|
||||
])
|
||||
|
||||
nested_array = [[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]]
|
||||
```
|
||||
|
||||
This also applies to list and dictionary unpacking:
|
||||
|
@ -124,9 +124,9 @@ def filtered_cached(self, sources: Iterable[Path]) -> Tuple[Set[Path], Set[Path]
|
||||
|
||||
def write(self, sources: Iterable[Path]) -> None:
|
||||
"""Update the cache file data and write a new cache file."""
|
||||
self.file_data.update(**{
|
||||
str(src.resolve()): Cache.get_file_data(src) for src in sources
|
||||
})
|
||||
self.file_data.update(
|
||||
**{str(src.resolve()): Cache.get_file_data(src) for src in sources}
|
||||
)
|
||||
try:
|
||||
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
with tempfile.NamedTemporaryFile(
|
||||
|
@ -17,16 +17,13 @@
|
||||
from black.output import out
|
||||
from black.report import NothingChanged
|
||||
|
||||
TRANSFORMED_MAGICS = frozenset(
|
||||
(
|
||||
TRANSFORMED_MAGICS = frozenset((
|
||||
"get_ipython().run_cell_magic",
|
||||
"get_ipython().system",
|
||||
"get_ipython().getoutput",
|
||||
"get_ipython().run_line_magic",
|
||||
)
|
||||
)
|
||||
TOKENS_TO_IGNORE = frozenset(
|
||||
(
|
||||
))
|
||||
TOKENS_TO_IGNORE = frozenset((
|
||||
"ENDMARKER",
|
||||
"NL",
|
||||
"NEWLINE",
|
||||
@ -34,10 +31,8 @@
|
||||
"DEDENT",
|
||||
"UNIMPORTANT_WS",
|
||||
"ESCAPED_NL",
|
||||
)
|
||||
)
|
||||
PYTHON_CELL_MAGICS = frozenset(
|
||||
(
|
||||
))
|
||||
PYTHON_CELL_MAGICS = frozenset((
|
||||
"capture",
|
||||
"prun",
|
||||
"pypy",
|
||||
@ -45,8 +40,7 @@
|
||||
"python3",
|
||||
"time",
|
||||
"timeit",
|
||||
)
|
||||
)
|
||||
))
|
||||
TOKEN_HEX = secrets.token_hex
|
||||
|
||||
|
||||
|
@ -817,22 +817,63 @@ def _first_right_hand_split(
|
||||
body_leaves.reverse()
|
||||
head_leaves.reverse()
|
||||
|
||||
if Preview.hug_parens_with_braces_and_square_brackets in line.mode:
|
||||
is_unpacking = 1 if body_leaves[0].type in [token.STAR, token.DOUBLESTAR] else 0
|
||||
body: Optional[Line] = None
|
||||
if (
|
||||
tail_leaves[0].type == token.RPAR
|
||||
Preview.hug_parens_with_braces_and_square_brackets in line.mode
|
||||
and tail_leaves[0].value
|
||||
and tail_leaves[0].opening_bracket is head_leaves[-1]
|
||||
and body_leaves[-1].type in [token.RBRACE, token.RSQB]
|
||||
and body_leaves[-1].opening_bracket is body_leaves[is_unpacking]
|
||||
):
|
||||
head_leaves = head_leaves + body_leaves[: 1 + is_unpacking]
|
||||
tail_leaves = body_leaves[-1:] + tail_leaves
|
||||
body_leaves = body_leaves[1 + is_unpacking : -1]
|
||||
inner_body_leaves = list(body_leaves)
|
||||
hugged_opening_leaves: List[Leaf] = []
|
||||
hugged_closing_leaves: List[Leaf] = []
|
||||
is_unpacking = body_leaves[0].type in [token.STAR, token.DOUBLESTAR]
|
||||
unpacking_offset: int = 1 if is_unpacking else 0
|
||||
while (
|
||||
len(inner_body_leaves) >= 2 + unpacking_offset
|
||||
and inner_body_leaves[-1].type in CLOSING_BRACKETS
|
||||
and inner_body_leaves[-1].opening_bracket
|
||||
is inner_body_leaves[unpacking_offset]
|
||||
):
|
||||
if unpacking_offset:
|
||||
hugged_opening_leaves.append(inner_body_leaves.pop(0))
|
||||
unpacking_offset = 0
|
||||
hugged_opening_leaves.append(inner_body_leaves.pop(0))
|
||||
hugged_closing_leaves.insert(0, inner_body_leaves.pop())
|
||||
|
||||
if hugged_opening_leaves and inner_body_leaves:
|
||||
inner_body = bracket_split_build_line(
|
||||
inner_body_leaves,
|
||||
line,
|
||||
hugged_opening_leaves[-1],
|
||||
component=_BracketSplitComponent.body,
|
||||
)
|
||||
if (
|
||||
line.mode.magic_trailing_comma
|
||||
and inner_body_leaves[-1].type == token.COMMA
|
||||
):
|
||||
should_hug = True
|
||||
else:
|
||||
line_length = line.mode.line_length - sum(
|
||||
len(str(leaf))
|
||||
for leaf in hugged_opening_leaves + hugged_closing_leaves
|
||||
)
|
||||
if is_line_short_enough(
|
||||
inner_body, mode=replace(line.mode, line_length=line_length)
|
||||
):
|
||||
# Do not hug if it fits on a single line.
|
||||
should_hug = False
|
||||
else:
|
||||
should_hug = True
|
||||
if should_hug:
|
||||
body_leaves = inner_body_leaves
|
||||
head_leaves.extend(hugged_opening_leaves)
|
||||
tail_leaves = hugged_closing_leaves + tail_leaves
|
||||
body = inner_body # No need to re-calculate the body again later.
|
||||
|
||||
head = bracket_split_build_line(
|
||||
head_leaves, line, opening_bracket, component=_BracketSplitComponent.head
|
||||
)
|
||||
if body is None:
|
||||
body = bracket_split_build_line(
|
||||
body_leaves, line, opening_bracket, component=_BracketSplitComponent.body
|
||||
)
|
||||
|
@ -128,6 +128,19 @@ def foo_square_brackets(request):
|
||||
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"}})
|
||||
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")))
|
||||
func([["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]])
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func({"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"})
|
||||
func(("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"))
|
||||
func(["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"])
|
||||
func(**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"})
|
||||
func(*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----"))
|
||||
array = [{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}]
|
||||
array = [("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")]
|
||||
array = [["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]]
|
||||
|
||||
foooooooooooooooooooo(
|
||||
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
|
||||
@ -137,6 +150,13 @@ def foo_square_brackets(request):
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], {x}, "a string", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
)
|
||||
|
||||
nested_mapping = {"key": [{"a very long key 1": "with a very long value", "a very long key 2": "with a very long value"}]}
|
||||
nested_array = [[["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]]]
|
||||
explicit_exploding = [[["short", "line",],],]
|
||||
single_item_do_not_explode = Context({
|
||||
"version": get_docs_version(),
|
||||
})
|
||||
|
||||
foo(*["long long long long long line", "long long long long long line", "long long long long long line"])
|
||||
|
||||
foo(*[str(i) for i in range(100000000000000000000000000000000000000000000000000000000000)])
|
||||
@ -152,6 +172,9 @@ def foo_square_brackets(request):
|
||||
|
||||
foo(**{x: y for x, y in enumerate(["long long long long line","long long long long line"])})
|
||||
|
||||
# Edge case when deciding whether to hug the brackets without inner content.
|
||||
very_very_very_long_variable = very_very_very_long_module.VeryVeryVeryVeryLongClassName([[]])
|
||||
|
||||
for foo in ["a", "b"]:
|
||||
output.extend([
|
||||
individual
|
||||
@ -276,9 +299,9 @@ def foo_square_brackets(request):
|
||||
)
|
||||
|
||||
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 "long line long line long line long line long line long line long line"]
|
||||
)
|
||||
func([
|
||||
x
|
||||
for x in [
|
||||
@ -295,15 +318,60 @@ def foo_square_brackets(request):
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
})
|
||||
func({
|
||||
{
|
||||
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",
|
||||
))
|
||||
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",
|
||||
]])
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func(
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
)
|
||||
func(
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
)
|
||||
func(
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
)
|
||||
func(
|
||||
**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"}
|
||||
)
|
||||
func(
|
||||
*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----")
|
||||
)
|
||||
array = [
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
]
|
||||
array = [
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
]
|
||||
array = [
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
]
|
||||
|
||||
foooooooooooooooooooo(
|
||||
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
|
||||
@ -313,6 +381,31 @@ def foo_square_brackets(request):
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], {x}, "a string", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
)
|
||||
|
||||
nested_mapping = {
|
||||
"key": [{
|
||||
"a very long key 1": "with a very long value",
|
||||
"a very long key 2": "with a very long value",
|
||||
}]
|
||||
}
|
||||
nested_array = [[[
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
]]]
|
||||
explicit_exploding = [
|
||||
[
|
||||
[
|
||||
"short",
|
||||
"line",
|
||||
],
|
||||
],
|
||||
]
|
||||
single_item_do_not_explode = Context({
|
||||
"version": get_docs_version(),
|
||||
})
|
||||
|
||||
foo(*[
|
||||
"long long long long long line",
|
||||
"long long long long long line",
|
||||
@ -334,6 +427,11 @@ def foo_square_brackets(request):
|
||||
x: y for x, y in enumerate(["long long long long line", "long long long long line"])
|
||||
})
|
||||
|
||||
# Edge case when deciding whether to hug the brackets without inner content.
|
||||
very_very_very_long_variable = very_very_very_long_module.VeryVeryVeryVeryLongClassName(
|
||||
[[]]
|
||||
)
|
||||
|
||||
for foo in ["a", "b"]:
|
||||
output.extend([
|
||||
individual
|
||||
|
@ -611,14 +611,13 @@ def foo():
|
||||
|
||||
class A:
|
||||
def foo():
|
||||
XXXXXXXXXXXX.append(
|
||||
(
|
||||
"xxx_xxxxxxxxxx(xxxxx={}, xxxx={}, xxxxx, xxxx_xxxx_xxxxxxxxxx={})"
|
||||
.format(xxxxx, xxxx, xxxx_xxxx_xxxxxxxxxx),
|
||||
XXXXXXXXXXXX.append((
|
||||
"xxx_xxxxxxxxxx(xxxxx={}, xxxx={}, xxxxx, xxxx_xxxx_xxxxxxxxxx={})".format(
|
||||
xxxxx, xxxx, xxxx_xxxx_xxxxxxxxxx
|
||||
),
|
||||
my_var,
|
||||
my_other_var,
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
class A:
|
||||
|
Loading…
Reference in New Issue
Block a user