black icon indicating copy to clipboard operation
black copied to clipboard

Black result not equivalent to the source with multiline format string in a function

Open lczyk opened this issue 4 years ago • 0 comments

Describe the bug

TLDR: Black produced code that is not equivalent to the source on pass 1 when processing a multiline format string in the first line of the body of the function.

While this is a proper doctoring:

def fun_1():
    """hello from docstring"""

this isn't:

greeting = "hello"
def fun_2():
    f"""{greeting} from docstring (except not really)"""

Regardless, however, it is a valid python code, even though it might not produce the desired output:

> print(fun_1.__doc__)
hello from docstring
> print(fun_2.__doc__)
None

Black formats both of the above functions fine, but breaks when a newline is introduced after the trailing format string:

greeting, goodbye = "hello", "bye"
def fun_3():
    f"""{greeting} from docstring (except not really) {goodbye}
    """

See below for an example.

To Reproduce

This is the content of file.py:

def works():
    """hello from the only real docstring here"""

greeting = "hello"

def breaks():
    f"""breaks with the format string at the end: {greeting}
    """

def does_not_break():
    f"""but does not break with the {greeting} format in the middle
    """

def also_does_not_break():
    f"""also does not break without the newline after the format string {greeting}"""

print("all works")

It runs in python, but fails with black.

$ python file.py
all works
$ black file.py
error: cannot format file.py: INTERNAL ERROR: Black produced code that is not equivalent to the source on pass 1.  Please report a bug on https://github.com/psf/black/issues.  This diff might be helpful: /var/folders/bp/cww9_8pn6k93pptbnc2yjnf00000gn/T/blk_cvj57d2b.log
Oh no! 💥 💔 💥
1 file failed to reformat.

Here is the content of the diff file:

--- src
+++ dst
@@ -86,16 +86,10 @@
                         )  # /Load
                       id=
                         'greeting',  # str
                     )  # /Name
                 )  # /FormattedValue
-                Constant(
-                  kind=
-                    None,  # NoneType
-                  value=
-                    '',  # str
-                )  # /Constant
             )  # /JoinedStr
         )  # /Expr
       decorator_list=
       name=
         'breaks',  # str

Environment

  • Black version: Checked with the latest version of black (21.12b0) and using the online formatter
  • OS and Python version: MacOS/Python 3.9.4

lczyk avatar Dec 10 '21 15:12 lczyk