Skip to content

Commit

Permalink
fix: fix PEP 646 support of tuple unpacking (#4440)
Browse files Browse the repository at this point in the history
This change fixes unpacking a tuple or generic type when *args is a type
variable tuple.
  • Loading branch information
terencehonles committed Aug 26, 2024
1 parent 699b45a commit 823a7b0
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

<!-- Changes that affect Black's preview style -->

- Fix type annotation spacing between * and more complex type variable tuple (i.e. `def
fn(*args: *tuple[*Ts, T]) -> None: pass`) (#4440)

### Configuration

<!-- Changes to how Black can be configured -->
Expand Down
2 changes: 2 additions & 0 deletions docs/the_black_code_style/future_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Currently, the following features are included in the preview style:
`case` blocks.
- `parens_for_long_if_clauses_in_case_block`: Adds parentheses to `if` clauses in `case`
blocks when the line is too long
- `pep646_typed_star_arg_type_var_tuple`: fix type annotation spacing between * and more
complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`)

(labels/unstable-features)=

Expand Down
1 change: 1 addition & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class Preview(Enum):
docstring_check_for_newline = auto()
remove_redundant_guard_parens = auto()
parens_for_long_if_clauses_in_case_block = auto()
pep646_typed_star_arg_type_var_tuple = auto()


UNSTABLE_FEATURES: Set[Preview] = {
Expand Down
10 changes: 8 additions & 2 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,15 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool, mode: Mode) -> str: # no
elif (
prevp.type == token.STAR
and parent_type(prevp) == syms.star_expr
and parent_type(prevp.parent) == syms.subscriptlist
and (
parent_type(prevp.parent) == syms.subscriptlist
or (
Preview.pep646_typed_star_arg_type_var_tuple in mode
and parent_type(prevp.parent) == syms.tname_star
)
)
):
# No space between typevar tuples.
# No space between typevar tuples or unpacking them.
return NO

elif prevp.type in VARARGS_SPECIALS:
Expand Down
3 changes: 2 additions & 1 deletion src/black/resources/black.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@
"is_simple_lookup_for_doublestar_expression",
"docstring_check_for_newline",
"remove_redundant_guard_parens",
"parens_for_long_if_clauses_in_case_block"
"parens_for_long_if_clauses_in_case_block",
"pep646_typed_star_arg_type_var_tuple"
]
},
"description": "Enable specific features included in the `--unstable` style. Requires `--preview`. No compatibility guarantees are provided on the behavior or existence of any unstable features."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# flags: --minimum-version=3.11 --preview


def fn(*args: *tuple[*A, B]) -> None:
pass


fn.__annotations__
3 changes: 3 additions & 0 deletions tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,9 @@ def test_get_features_used(self) -> None:
self.check_features_used("a[*b]", {Feature.VARIADIC_GENERICS})
self.check_features_used("a[x, *y(), z] = t", {Feature.VARIADIC_GENERICS})
self.check_features_used("def fn(*args: *T): pass", {Feature.VARIADIC_GENERICS})
self.check_features_used(
"def fn(*args: *tuple[*T]): pass", {Feature.VARIADIC_GENERICS}
)

self.check_features_used("with a: pass", set())
self.check_features_used("with a, b: pass", set())
Expand Down

0 comments on commit 823a7b0

Please sign in to comment.