This might be an XY-problem regarding the question about textwrap.wrap. I don't need to use textwrap.wrap if there's an easier way.

I want to satisfy the following three criteria:

  • Printed output text maximum line length of 70
  • Source code maximum line length of 80
  • Black code formatting

Here is an example text that I want to print:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

The expected output is therefore:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.

I get this output by using textwrap.wrap like this:

print("\n".join(textwrap.wrap("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")))

To statisfy Black and code line length, I changed that into:

print(
    "\n".join(
        textwrap.wrap(
            """
            Lorem ipsum dolor sit amet, consectetur
            adipiscing elit, sed do eiusmod tempor
            incididunt ut labore et dolore magna aliqua.
            Ut enim ad minim veniam, quis nostrud
            exercitation ullamco laboris nisi ut aliquip
            ex ea commodo consequat. Duis aute irure dolor
            in reprehenderit in voluptate velit esse
            cillum dolore eu fugiat nulla pariatur.
            Excepteur sint occaecat cupidatat non
            proident, sunt in culpa qui officia deserunt
            mollit anim id est laborum.

            """
        )
    )
)

(The print is already indented some levels, so these lines are shorter than 80.)

However, since drop_whitespace=True (default) of textwrap.wrap happens after wrapping, this is the output:

             Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor             incididunt ut
labore et dolore magna aliqua.             Ut enim ad minim veniam,
quis nostrud             exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor             in
reprehenderit in voluptate velit esse             cillum dolore eu
fugiat nulla pariatur.             Excepteur sint occaecat cupidatat
non             proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.

I could obviously replace the whitespace myself, before calling textwrap.wrap but I feel like this is getting out of hand. Surely, there must be a better way...?

1

There are 1 best solutions below

0
On

First of all, one level of indentation can be saved by using textwrap.fill instead of chaining str.join and textwrap.wrap. Afterwards, it probably comes down to everyone's personal taste which one of the following improvements "look least ugly".

  • Adding textwrap.dedent the get rid of the whitespace at the beginning of the lines and \ to take care of the first line break:

    print(
        textwrap.fill(
            textwrap.dedent(
                """\
                Lorem ipsum dolor sit amet, consectetur
                adipiscing elit, sed do eiusmod tempor
                incididunt ut labore et dolore magna aliqua.
                Ut enim ad minim veniam, quis nostrud
                exercitation ullamco laboris nisi ut aliquip
                ex ea commodo consequat. Duis aute irure dolor
                in reprehenderit in voluptate velit esse
                cillum dolore eu fugiat nulla pariatur.
                Excepteur sint occaecat cupidatat non
                proident, sunt in culpa qui officia deserunt
                mollit anim id est laborum.
    
                """
            )
        )
    )
    
  • Without textwrap.dedent we'd have to write the string differently:

    print(
        textwrap.fill(
            "Lorem ipsum dolor sit amet, consectetur adipiscing "
            "elit, sed do eiusmod tempor incididunt ut labore et "
            "dolore magna aliqua. Ut enim ad minim veniam, quis "
            "nostrud exercitation ullamco laboris nisi ut aliquip "
            "ex ea commodo consequat. Duis aute irure dolor in "
            "reprehenderit in voluptate velit esse cillum dolore "
            "eu fugiat nulla pariatur. Excepteur sint occaecat "
            "cupidatat non proident, sunt in culpa qui officia "
            "deserunt mollit anim id est laborum."
        )
    )
    
  • Or even without keeping the indentation level:

    print(
        textwrap.fill(
            """Lorem ipsum dolor sit amet, consectetur adipiscing
    elit, sed do eiusmod tempor incididunt ut labore et dolore
    magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
    ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
    aute irure dolor in reprehenderit in voluptate velit esse cillum
    dolore eu fugiat nulla pariatur. Excepteur sint occaecat
    cupidatat non proident, sunt in culpa qui officia deserunt
    mollit anim id est laborum."""
        )
    )
    
  • Alternatively, it might be an option to keep the string literal in a different part of the code as a constant:

    LOREM_IPSUM = (
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
        "sed do eiusmod tempor incididunt ut labore et dolore magna "
        "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
        "ullamco laboris nisi ut aliquip ex ea commodo consequat. "
        "Duis aute irure dolor in reprehenderit in voluptate velit "
        "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
        "occaecat cupidatat non proident, sunt in culpa qui officia "
        "deserunt mollit anim id est laborum."
    )
    
    print(textwrap.fill(LOREM_IPSUM))
    
  • A custom function to format the string is also an option. The commands will chain inside that function and not lead to many indentation levels later:

    def custom_format(text):
        return textwrap.fill(re.sub(r"\s+", " ", text.strip()))
    
    print(
        custom_format(
            """
            Lorem ipsum dolor sit amet, consectetur adipiscing
            elit, sed do eiusmod tempor incididunt ut labore et
            dolore magna aliqua. Ut enim ad minim veniam, quis
            nostrud exercitation ullamco laboris nisi ut aliquip
            ex ea commodo consequat. Duis aute irure dolor in
            reprehenderit in voluptate velit esse cillum dolore
            eu fugiat nulla pariatur. Excepteur sint occaecat
            cupidatat non proident, sunt in culpa qui officia
            deserunt mollit anim id est laborum.
    
            """
        )
    )