ikamensh / flynt

A tool to automatically convert old string literal formatting to f-strings
MIT License
682 stars 33 forks source link

Newline escapes are removed #83

Open jdufresne opened 3 years ago

jdufresne commented 3 years ago

input:

from textwrap import dedent

def f():
    arg = "text"
    return dedent(
        """\
        some {}
        lorem ipsum
        """.format(arg)
    )

expected:

from textwrap import dedent

def f():
    arg = "text"
    return dedent(
        f"""\
        some {arg}
        lorem ipsum
        """
    )

actual:

from textwrap import dedent

def f():
    arg = "text"
    return dedent(
        f"""        some {arg}
        lorem ipsum
        """
    )

The newline escape was intentionally introduced to make the dedent block more readable.

ikamensh commented 3 years ago

Hi, thanks for reporting the bug. Similarly to #55 the problem lays in the symbols being gone from the parsed expression (escaping the newline has the specific purpose of removing this newline as seen by the interpreter).

I imagine a solution would be to find the diff on the parsed version of the code, and then apply this diff to the original section of the code. From fast research, this library could do this: https://pypi.org/project/diff-match-patch/. Yet this means very deep reworking of the library internals to adopt this new method of deriving new code. I can't provide any ETA on this.

akx commented 1 year ago

I think doing this robustly would require something like https://github.com/Instagram/LibCST instead of just working with the AST.