diff --git a/CHANGES.md b/CHANGES.md index 84d9061135a..4e5bd9ca771 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,8 @@ - Multiline dictionaries and lists that are the sole argument to a function are now indented less (#3964) +- Multiline list and dict unpacking as the sole argument to a function is now also + indented less (#3992) ### Configuration diff --git a/docs/the_black_code_style/future_style.md b/docs/the_black_code_style/future_style.md index c744902577d..944ffad033e 100644 --- a/docs/the_black_code_style/future_style.md +++ b/docs/the_black_code_style/future_style.md @@ -139,6 +139,26 @@ foo([ ]) ``` +This also applies to list and dictionary unpacking: + +```python +foo( + *[ + a_long_function_name(a_long_variable_name) + for a_long_variable_name in some_generator + ] +) +``` + +will become: + +```python +foo(*[ + a_long_function_name(a_long_variable_name) + for a_long_variable_name in some_generator +]) +``` + You can use a magic trailing comma to avoid this compacting behavior; by default, _Black_ will not reformat the following code: diff --git a/src/black/cache.py b/src/black/cache.py index 6baa096baca..6a332304981 100644 --- a/src/black/cache.py +++ b/src/black/cache.py @@ -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( diff --git a/src/black/linegen.py b/src/black/linegen.py index 5f5a69152d5..43bc08efbbd 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -817,16 +817,17 @@ def _first_right_hand_split( 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 if ( tail_leaves[0].type == token.RPAR 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[0] + and body_leaves[-1].opening_bracket is body_leaves[is_unpacking] ): - head_leaves = head_leaves + body_leaves[:1] + head_leaves = head_leaves + body_leaves[: 1 + is_unpacking] tail_leaves = body_leaves[-1:] + tail_leaves - body_leaves = body_leaves[1:-1] + body_leaves = body_leaves[1 + is_unpacking : -1] head = bracket_split_build_line( head_leaves, line, opening_bracket, component=_BracketSplitComponent.head diff --git a/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py b/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py index 6d10518133c..51fe516add5 100644 --- a/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py +++ b/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py @@ -137,6 +137,21 @@ 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] ) +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)]) + +foo( + **{ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": 1, + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": 2, + "ccccccccccccccccccccccccccccccccc": 3, + **other, + } +) + +foo(**{x: y for x, y in enumerate(["long long long long line","long long long long line"])}) + # output def foo_brackets(request): return JsonResponse({ @@ -287,3 +302,24 @@ def foo_square_brackets(request): baaaaaaaaaaaaar( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], {x}, "a string", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ) + +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) +]) + +foo(**{ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": 1, + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": 2, + "ccccccccccccccccccccccccccccccccc": 3, + **other, +}) + +foo(**{ + x: y for x, y in enumerate(["long long long long line", "long long long long line"]) +})