Better manage return annotation brackets (#2990)
Allows us to better control placement of return annotations by: a) removing redundant parens b) moves very long type annotations onto their own line Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
parent
f6188ce6dc
commit
98fcccee55
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<!-- Changes that affect Black's preview style -->
|
<!-- Changes that affect Black's preview style -->
|
||||||
|
|
||||||
|
- Parentheses around return annotations are now managed (#2990)
|
||||||
- Remove unnecessary parentheses from `with` statements (#2926)
|
- Remove unnecessary parentheses from `with` statements (#2926)
|
||||||
|
|
||||||
### _Blackd_
|
### _Blackd_
|
||||||
|
@ -144,6 +144,33 @@ def visit_stmt(
|
|||||||
|
|
||||||
yield from self.visit(child)
|
yield from self.visit(child)
|
||||||
|
|
||||||
|
def visit_funcdef(self, node: Node) -> Iterator[Line]:
|
||||||
|
"""Visit function definition."""
|
||||||
|
if Preview.annotation_parens not in self.mode:
|
||||||
|
yield from self.visit_stmt(node, keywords={"def"}, parens=set())
|
||||||
|
else:
|
||||||
|
yield from self.line()
|
||||||
|
|
||||||
|
# Remove redundant brackets around return type annotation.
|
||||||
|
is_return_annotation = False
|
||||||
|
for child in node.children:
|
||||||
|
if child.type == token.RARROW:
|
||||||
|
is_return_annotation = True
|
||||||
|
elif is_return_annotation:
|
||||||
|
if child.type == syms.atom and child.children[0].type == token.LPAR:
|
||||||
|
if maybe_make_parens_invisible_in_atom(
|
||||||
|
child,
|
||||||
|
parent=node,
|
||||||
|
remove_brackets_around_comma=False,
|
||||||
|
):
|
||||||
|
wrap_in_parentheses(node, child, visible=False)
|
||||||
|
else:
|
||||||
|
wrap_in_parentheses(node, child, visible=False)
|
||||||
|
is_return_annotation = False
|
||||||
|
|
||||||
|
for child in node.children:
|
||||||
|
yield from self.visit(child)
|
||||||
|
|
||||||
def visit_match_case(self, node: Node) -> Iterator[Line]:
|
def visit_match_case(self, node: Node) -> Iterator[Line]:
|
||||||
"""Visit either a match or case statement."""
|
"""Visit either a match or case statement."""
|
||||||
normalize_invisible_parens(node, parens_after=set(), preview=self.mode.preview)
|
normalize_invisible_parens(node, parens_after=set(), preview=self.mode.preview)
|
||||||
@ -326,7 +353,6 @@ def __post_init__(self) -> None:
|
|||||||
else:
|
else:
|
||||||
self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
|
self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
|
||||||
self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
|
self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
|
||||||
self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
|
|
||||||
self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
|
self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
|
||||||
self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
|
self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
|
||||||
self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
|
self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
|
||||||
@ -478,7 +504,10 @@ def left_hand_split(line: Line, _features: Collection[Feature] = ()) -> Iterator
|
|||||||
current_leaves is body_leaves
|
current_leaves is body_leaves
|
||||||
and leaf.type in CLOSING_BRACKETS
|
and leaf.type in CLOSING_BRACKETS
|
||||||
and leaf.opening_bracket is matching_bracket
|
and leaf.opening_bracket is matching_bracket
|
||||||
|
and isinstance(matching_bracket, Leaf)
|
||||||
):
|
):
|
||||||
|
ensure_visible(leaf)
|
||||||
|
ensure_visible(matching_bracket)
|
||||||
current_leaves = tail_leaves if body_leaves else head_leaves
|
current_leaves = tail_leaves if body_leaves else head_leaves
|
||||||
current_leaves.append(leaf)
|
current_leaves.append(leaf)
|
||||||
if current_leaves is head_leaves:
|
if current_leaves is head_leaves:
|
||||||
|
@ -129,6 +129,7 @@ class Preview(Enum):
|
|||||||
string_processing = auto()
|
string_processing = auto()
|
||||||
remove_redundant_parens = auto()
|
remove_redundant_parens = auto()
|
||||||
one_element_subscript = auto()
|
one_element_subscript = auto()
|
||||||
|
annotation_parens = auto()
|
||||||
|
|
||||||
|
|
||||||
class Deprecated(UserWarning):
|
class Deprecated(UserWarning):
|
||||||
|
222
tests/data/return_annotation_brackets.py
Normal file
222
tests/data/return_annotation_brackets.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
# Control
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
# Remove the brackets
|
||||||
|
def double(a: int) -> (int):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
# Some newline variations
|
||||||
|
def double(a: int) -> (
|
||||||
|
int):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
def double(a: int) -> (int
|
||||||
|
):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
def double(a: int) -> (
|
||||||
|
int
|
||||||
|
):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
# Don't lose the comments
|
||||||
|
def double(a: int) -> ( # Hello
|
||||||
|
int
|
||||||
|
):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
def double(a: int) -> (
|
||||||
|
int # Hello
|
||||||
|
):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
# Really long annotations
|
||||||
|
def foo() -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def foo() -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def foo() -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def foo(a: int, b: int, c: int,) -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def foo(a: int, b: int, c: int,) -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# Split args but no need to split return
|
||||||
|
def foo(a: int, b: int, c: int,) -> int:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# Deeply nested brackets
|
||||||
|
# with *interesting* spacing
|
||||||
|
def double(a: int) -> (((((int))))):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
def double(a: int) -> (
|
||||||
|
( (
|
||||||
|
((int)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
return 2*a
|
||||||
|
|
||||||
|
def foo() -> (
|
||||||
|
( (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
)
|
||||||
|
)):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# Return type with commas
|
||||||
|
def foo() -> (
|
||||||
|
tuple[int, int, int]
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def foo() -> tuple[loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong, loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong, loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong]:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# Magic trailing comma example
|
||||||
|
def foo() -> tuple[int, int, int,]:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# Long string example
|
||||||
|
def frobnicate() -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
|
||||||
|
pass
|
||||||
|
|
||||||
|
# output
|
||||||
|
# Control
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
# Remove the brackets
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
# Some newline variations
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
# Don't lose the comments
|
||||||
|
def double(a: int) -> int: # Hello
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
def double(a: int) -> int: # Hello
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
# Really long annotations
|
||||||
|
def foo() -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def foo() -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def foo() -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
| intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def foo(
|
||||||
|
a: int,
|
||||||
|
b: int,
|
||||||
|
c: int,
|
||||||
|
) -> intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def foo(
|
||||||
|
a: int,
|
||||||
|
b: int,
|
||||||
|
c: int,
|
||||||
|
) -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
| intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# Split args but no need to split return
|
||||||
|
def foo(
|
||||||
|
a: int,
|
||||||
|
b: int,
|
||||||
|
c: int,
|
||||||
|
) -> int:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# Deeply nested brackets
|
||||||
|
# with *interesting* spacing
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
def double(a: int) -> int:
|
||||||
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
|
def foo() -> (
|
||||||
|
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# Return type with commas
|
||||||
|
def foo() -> tuple[int, int, int]:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def foo() -> (
|
||||||
|
tuple[
|
||||||
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# Magic trailing comma example
|
||||||
|
def foo() -> (
|
||||||
|
tuple[
|
||||||
|
int,
|
||||||
|
int,
|
||||||
|
int,
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# Long string example
|
||||||
|
def frobnicate() -> (
|
||||||
|
"ThisIsTrulyUnreasonablyExtremelyLongClassName |"
|
||||||
|
" list[ThisIsTrulyUnreasonablyExtremelyLongClassName]"
|
||||||
|
):
|
||||||
|
pass
|
@ -83,6 +83,7 @@
|
|||||||
"remove_except_parens",
|
"remove_except_parens",
|
||||||
"remove_for_brackets",
|
"remove_for_brackets",
|
||||||
"one_element_subscript",
|
"one_element_subscript",
|
||||||
|
"return_annotation_brackets",
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCES: List[str] = [
|
SOURCES: List[str] = [
|
||||||
|
Loading…
Reference in New Issue
Block a user