fix: fix PEP 646 support of tuple unpacking (#4440)

This change fixes unpacking a tuple or generic type when *args is a type
variable tuple.
This commit is contained in:
Terence Honles 2024-08-26 17:09:59 +02:00 committed by GitHub
parent 699b45aef7
commit 823a7b0ff0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 27 additions and 3 deletions

View File

@ -14,6 +14,9 @@
<!-- Changes that affect Black's preview style --> <!-- 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 ### Configuration
<!-- Changes to how Black can be configured --> <!-- Changes to how Black can be configured -->

View File

@ -36,6 +36,8 @@ Currently, the following features are included in the preview style:
`case` blocks. `case` blocks.
- `parens_for_long_if_clauses_in_case_block`: Adds parentheses to `if` clauses in `case` - `parens_for_long_if_clauses_in_case_block`: Adds parentheses to `if` clauses in `case`
blocks when the line is too long 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)= (labels/unstable-features)=

View File

@ -206,6 +206,7 @@ class Preview(Enum):
docstring_check_for_newline = auto() docstring_check_for_newline = auto()
remove_redundant_guard_parens = auto() remove_redundant_guard_parens = auto()
parens_for_long_if_clauses_in_case_block = auto() parens_for_long_if_clauses_in_case_block = auto()
pep646_typed_star_arg_type_var_tuple = auto()
UNSTABLE_FEATURES: Set[Preview] = { UNSTABLE_FEATURES: Set[Preview] = {

View File

@ -254,9 +254,15 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool, mode: Mode) -> str: # no
elif ( elif (
prevp.type == token.STAR prevp.type == token.STAR
and parent_type(prevp) == syms.star_expr 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 return NO
elif prevp.type in VARARGS_SPECIALS: elif prevp.type in VARARGS_SPECIALS:

View File

@ -90,7 +90,8 @@
"is_simple_lookup_for_doublestar_expression", "is_simple_lookup_for_doublestar_expression",
"docstring_check_for_newline", "docstring_check_for_newline",
"remove_redundant_guard_parens", "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." "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."

View File

@ -0,0 +1,8 @@
# flags: --minimum-version=3.11 --preview
def fn(*args: *tuple[*A, B]) -> None:
pass
fn.__annotations__

View File

@ -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[*b]", {Feature.VARIADIC_GENERICS})
self.check_features_used("a[x, *y(), z] = t", {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: *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: pass", set())
self.check_features_used("with a, b: pass", set()) self.check_features_used("with a, b: pass", set())