コード例 #1
0
ファイル: linegen.py プロジェクト: psf/black
def remove_await_parens(node: Node) -> None:
    if node.children[0].type == token.AWAIT and len(node.children) > 1:
        if (
            node.children[1].type == syms.atom
            and node.children[1].children[0].type == token.LPAR
        ):
            if maybe_make_parens_invisible_in_atom(
                node.children[1],
                parent=node,
                remove_brackets_around_comma=True,
            ):
                wrap_in_parentheses(node, node.children[1], visible=False)

            # Since await is an expression we shouldn't remove
            # brackets in cases where this would change
            # the AST due to operator precedence.
            # Therefore we only aim to remove brackets around
            # power nodes that aren't also await expressions themselves.
            # https://peps.python.org/pep-0492/#updated-operator-precedence-table
            # N.B. We've still removed any redundant nested brackets though :)
            opening_bracket = cast(Leaf, node.children[1].children[0])
            closing_bracket = cast(Leaf, node.children[1].children[-1])
            bracket_contents = cast(Node, node.children[1].children[1])
            if bracket_contents.type != syms.power:
                ensure_visible(opening_bracket)
                ensure_visible(closing_bracket)
            elif (
                bracket_contents.type == syms.power
                and bracket_contents.children[0].type == token.AWAIT
            ):
                ensure_visible(opening_bracket)
                ensure_visible(closing_bracket)
                # If we are in a nested await then recurse down.
                remove_await_parens(bracket_contents)
コード例 #2
0
ファイル: linegen.py プロジェクト: psf/black
def left_hand_split(line: Line, _features: Collection[Feature] = ()) -> Iterator[Line]:
    """Split line into many lines, starting with the first matching bracket pair.

    Note: this usually looks weird, only use this for function definitions.
    Prefer RHS otherwise.  This is why this function is not symmetrical with
    :func:`right_hand_split` which also handles optional parentheses.
    """
    tail_leaves: List[Leaf] = []
    body_leaves: List[Leaf] = []
    head_leaves: List[Leaf] = []
    current_leaves = head_leaves
    matching_bracket: Optional[Leaf] = None
    for leaf in line.leaves:
        if (
            current_leaves is body_leaves
            and leaf.type in CLOSING_BRACKETS
            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.append(leaf)
        if current_leaves is head_leaves:
            if leaf.type in OPENING_BRACKETS:
                matching_bracket = leaf
                current_leaves = body_leaves
    if not matching_bracket:
        raise CannotSplit("No brackets found")

    head = bracket_split_build_line(head_leaves, line, matching_bracket)
    body = bracket_split_build_line(body_leaves, line, matching_bracket, is_body=True)
    tail = bracket_split_build_line(tail_leaves, line, matching_bracket)
    bracket_split_succeeded_or_raise(head, body, tail)
    for result in (head, body, tail):
        if result:
            yield result
コード例 #3
0
def right_hand_split(
    line: Line,
    line_length: int,
    features: Collection[Feature] = (),
    omit: Collection[LeafID] = (),
) -> Iterator[Line]:
    """Split line into many lines, starting with the last matching bracket pair.

    If the split was by optional parentheses, attempt splitting without them, too.
    `omit` is a collection of closing bracket IDs that shouldn't be considered for
    this split.

    Note: running this function modifies `bracket_depth` on the leaves of `line`.
    """
    tail_leaves: List[Leaf] = []
    body_leaves: List[Leaf] = []
    head_leaves: List[Leaf] = []
    current_leaves = tail_leaves
    opening_bracket: Optional[Leaf] = None
    closing_bracket: Optional[Leaf] = None
    for leaf in reversed(line.leaves):
        if current_leaves is body_leaves:
            if leaf is opening_bracket:
                current_leaves = head_leaves if body_leaves else tail_leaves
        current_leaves.append(leaf)
        if current_leaves is tail_leaves:
            if leaf.type in CLOSING_BRACKETS and id(leaf) not in omit:
                opening_bracket = leaf.opening_bracket
                closing_bracket = leaf
                current_leaves = body_leaves
    if not (opening_bracket and closing_bracket and head_leaves):
        # If there is no opening or closing_bracket that means the split failed and
        # all content is in the tail.  Otherwise, if `head_leaves` are empty, it means
        # the matching `opening_bracket` wasn't available on `line` anymore.
        raise CannotSplit("No brackets found")

    tail_leaves.reverse()
    body_leaves.reverse()
    head_leaves.reverse()
    head = bracket_split_build_line(head_leaves, line, opening_bracket)
    body = bracket_split_build_line(body_leaves, line, opening_bracket, is_body=True)
    tail = bracket_split_build_line(tail_leaves, line, opening_bracket)
    bracket_split_succeeded_or_raise(head, body, tail)
    if (
        Feature.FORCE_OPTIONAL_PARENTHESES not in features
        # the opening bracket is an optional paren
        and opening_bracket.type == token.LPAR
        and not opening_bracket.value
        # the closing bracket is an optional paren
        and closing_bracket.type == token.RPAR
        and not closing_bracket.value
        # it's not an import (optional parens are the only thing we can split on
        # in this case; attempting a split without them is a waste of time)
        and not line.is_import
        # there are no standalone comments in the body
        and not body.contains_standalone_comments(0)
        # and we can actually remove the parens
        and can_omit_invisible_parens(body, line_length)
    ):
        omit = {id(closing_bracket), *omit}
        try:
            yield from right_hand_split(line, line_length, features=features, omit=omit)
            return

        except CannotSplit as e:
            if not (
                can_be_split(body)
                or is_line_short_enough(body, line_length=line_length)
            ):
                raise CannotSplit(
                    "Splitting failed, body is still too long and can't be split."
                ) from e

            elif head.contains_multiline_strings() or tail.contains_multiline_strings():
                raise CannotSplit(
                    "The current optional pair of parentheses is bound to fail to"
                    " satisfy the splitting algorithm because the head or the tail"
                    " contains multiline strings which by definition never fit one"
                    " line."
                ) from e

    ensure_visible(opening_bracket)
    ensure_visible(closing_bracket)
    for result in (head, body, tail):
        if result:
            yield result