def normalize_invisible_parens(node: Node, parens_after: Set[str], *, preview: bool) -> None: """Make existing optional parentheses invisible or create new ones. `parens_after` is a set of string leaf values immediately after which parens should be put. Standardizes on visible parentheses for single-element tuples, and keeps existing visible parentheses for other tuples and generator expressions. """ for pc in list_comments(node.prefix, is_endmarker=False, preview=preview): if pc.value in FMT_OFF: # This `node` has a prefix with `# fmt: off`, don't mess with parens. return check_lpar = False for index, child in enumerate(list(node.children)): # Fixes a bug where invisible parens are not properly stripped from # assignment statements that contain type annotations. if isinstance(child, Node) and child.type == syms.annassign: normalize_invisible_parens(child, parens_after=parens_after, preview=preview) # Add parentheses around long tuple unpacking in assignments. if (index == 0 and isinstance(child, Node) and child.type == syms.testlist_star_expr): check_lpar = True if check_lpar: if child.type == syms.atom: if maybe_make_parens_invisible_in_atom( child, parent=node, preview=preview, ): wrap_in_parentheses(node, child, visible=False) elif is_one_tuple(child): wrap_in_parentheses(node, child, visible=True) elif node.type == syms.import_from: # "import from" nodes store parentheses directly as part of # the statement if is_lpar_token(child): assert is_rpar_token(node.children[-1]) # make parentheses invisible child.value = "" node.children[-1].value = "" elif child.type != token.STAR: # insert invisible parentheses node.insert_child(index, Leaf(token.LPAR, "")) node.append_child(Leaf(token.RPAR, "")) break elif not (isinstance(child, Leaf) and is_multiline_string(child)): wrap_in_parentheses(node, child, visible=False) check_lpar = isinstance(child, Leaf) and child.value in parens_after
def visit_factor(self, node: Node) -> Iterator[Line]: """Force parentheses between a unary op and a binary power: -2 ** 8 -> -(2 ** 8) """ _operator, operand = node.children if (operand.type == syms.power and len(operand.children) == 3 and operand.children[1].type == token.DOUBLESTAR): lpar = Leaf(token.LPAR, "(") rpar = Leaf(token.RPAR, ")") index = operand.remove() or 0 node.insert_child(index, Node(syms.atom, [lpar, operand, rpar])) yield from self.visit_default(node)
def wrap_in_parentheses(parent: Node, child: LN, *, visible: bool = True) -> None: """Wrap `child` in parentheses. This replaces `child` with an atom holding the parentheses and the old child. That requires moving the prefix. If `visible` is False, the leaves will be valueless (and thus invisible). """ lpar = Leaf(token.LPAR, "(" if visible else "") rpar = Leaf(token.RPAR, ")" if visible else "") prefix = child.prefix child.prefix = "" index = child.remove() or 0 new_child = Node(syms.atom, [lpar, child, rpar]) new_child.prefix = prefix parent.insert_child(index, new_child)