Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make trailing comma logic more consise #4202

Merged
merged 9 commits into from Feb 28, 2024
26 changes: 7 additions & 19 deletions src/black/linegen.py
Expand Up @@ -31,12 +31,12 @@
BRACKETS,
CLOSING_BRACKETS,
OPENING_BRACKETS,
RARROW,
STANDALONE_COMMENT,
STATEMENT,
WHITESPACE,
Visitor,
ensure_visible,
get_annotation_type,
is_arith_like,
is_async_stmt_or_funcdef,
is_atom_with_invisible_parens,
Expand Down Expand Up @@ -1037,11 +1037,12 @@ def bracket_split_build_line(
result.inside_brackets = True
result.depth += 1
if leaves:
# Ensure a trailing comma for imports and standalone function arguments, but
# be careful not to add one after any comments or within type annotations.
no_commas = (
# Ensure a trailing comma for imports and standalone function arguments
original.is_def
# Don't add one after any comments or within type annotations
and opening_bracket.value == "("
# Don't add one if there's already one there
and not any(
leaf.type == token.COMMA
and (
Expand All @@ -1050,22 +1051,9 @@ def bracket_split_build_line(
)
for leaf in leaves
)
# In particular, don't add one within a parenthesized return annotation.
# Unfortunately the indicator we're in a return annotation (RARROW) may
# be defined directly in the parent node, the parent of the parent ...
# and so on depending on how complex the return annotation is.
# This isn't perfect and there's some false negatives but they are in
# contexts were a comma is actually fine.
and not any(
node.prev_sibling.type == RARROW
for node in (
leaves[0].parent,
getattr(leaves[0].parent, "parent", None),
)
if isinstance(node, Node) and isinstance(node.prev_sibling, Leaf)
)
# Except the false negatives above for PEP 604 unions where we
# can't add the comma.
# Don't add one inside parenthesized return annotations
and not get_annotation_type(leaves[0]) == "return"
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved
# Don't add one inside PEP 604 unions
and not (
leaves[0].parent
and leaves[0].parent.next_sibling
Expand Down
28 changes: 22 additions & 6 deletions src/black/nodes.py
Expand Up @@ -3,7 +3,18 @@
"""

import sys
from typing import Final, Generic, Iterator, List, Optional, Set, Tuple, TypeVar, Union
from typing import (
Final,
Generic,
Iterator,
List,
Literal,
Optional,
Set,
Tuple,
TypeVar,
Union,
)

if sys.version_info >= (3, 10):
from typing import TypeGuard
Expand Down Expand Up @@ -951,16 +962,21 @@ def is_number_token(nl: NL) -> TypeGuard[Leaf]:
return nl.type == token.NUMBER


def is_part_of_annotation(leaf: Leaf) -> bool:
"""Returns whether this leaf is part of type annotations."""
def get_annotation_type(leaf: Leaf) -> Optional[Literal["return", "param"]]:
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved
"""Returns the type of annotation this leaf is part of, if any."""
ancestor = leaf.parent
while ancestor is not None:
if ancestor.prev_sibling and ancestor.prev_sibling.type == token.RARROW:
return True
return "return"
if ancestor.parent and ancestor.parent.type == syms.tname:
return True
return "param"
ancestor = ancestor.parent
return False
return None


def is_part_of_annotation(leaf: Leaf) -> bool:
"""Returns whether this leaf is part of a type annotation."""
return get_annotation_type(leaf) is not None


def first_leaf(node: LN) -> Optional[Leaf]:
Expand Down