Repository: psf/black
File: src/black/linegen.py (Python)

Code before:
        yield from self.visit_default(leaf)

    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 visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
        if is_docstring(leaf) and "\\\n" not in leaf.value:
            # We're ignoring docstrings with backslash newline escapes because changing
            # indentation of those changes the AST representation of the code.
            if Preview.normalize_docstring_quotes_and_prefixes_properly in self.mode:
                # There was a bug where --skip-string-normalization wouldn't stop us
                # from normalize docstring prefixes. To maintain stability, we can only
                # address this buggy behaviour while the preview style is enabled.
                if self.mode.string_normalization:
                    docstring = normalize_string_prefix(leaf.value)
                    # visit_default() does handle string normalization for us, but
                    # since this method acts differently depending on quote style (ex.
                    # see padding logic below), there's a possibility for unstable
                    # formatting as visit_default() is called *after*. To avoid a
                    # situation where this function formats a docstring differently on
                    # the second pass, normalize it early.
                    docstring = normalize_string_quotes(docstring)
                else:
                    docstring = leaf.value
            else:
                # ... otherwise, we'll keep the buggy behaviour >.<
                docstring = normalize_string_prefix(leaf.value)
            prefix = get_string_prefix(docstring)
            docstring = docstring[len(prefix) :]  # Remove the prefix
            quote_char = docstring[0]
            # A natural way to remove the outer quotes is to do:
            #   docstring = docstring.strip(quote_char)
            # but that breaks on """""x""" (which is '""x').
            # So we actually need to remove the first character and the next two
            # characters but only if they are the same as the first.
            quote_len = 1 if docstring[1] != quote_char else 3
            docstring = docstring[quote_len:-quote_len]

Review comment (suggestion):
```suggestion
                # from normalizing docstring prefixes. To maintain stability, we can only
```

Code after:
        yield from self.visit_default(leaf)

    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 visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
        if is_docstring(leaf) and "\\\n" not in leaf.value:
            # We're ignoring docstrings with backslash newline escapes because changing
            # indentation of those changes the AST representation of the code.
            if Preview.normalize_docstring_quotes_and_prefixes_properly in self.mode:
                # There was a bug where --skip-string-normalization wouldn't stop us
                # from normalizing docstring prefixes. To maintain stability, we can
                # only address this buggy behaviour while the preview style is enabled.
                if self.mode.string_normalization:
                    docstring = normalize_string_prefix(leaf.value)
                    # visit_default() does handle string normalization for us, but
                    # since this method acts differently depending on quote style (ex.
                    # see padding logic below), there's a possibility for unstable
                    # formatting as visit_default() is called *after*. To avoid a
                    # situation where this function formats a docstring differently on
                    # the second pass, normalize it early.
                    docstring = normalize_string_quotes(docstring)
                else:
                    docstring = leaf.value
            else:
                # ... otherwise, we'll keep the buggy behaviour >.<
                docstring = normalize_string_prefix(leaf.value)
            prefix = get_string_prefix(docstring)
            docstring = docstring[len(prefix) :]  # Remove the prefix
            quote_char = docstring[0]
            # A natural way to remove the outer quotes is to do:
            #   docstring = docstring.strip(quote_char)
            # but that breaks on """""x""" (which is '""x').
            # So we actually need to remove the first character and the next two
            # characters but only if they are the same as the first.
            quote_len = 1 if docstring[1] != quote_char else 3
            docstring = docstring[quote_len:-quote_len]