Wemake-python-styleguide: Multiline string indentation

Created on 26 Nov 2019  路  12Comments  路  Source: wemake-services/wemake-python-styleguide

Rule request

Thesis

Flake8 has no opinion about multiline strings at all. Everything in this example is correct:

def f():
    a = """
        text
        text
    """
    a = """
        text
        text
        """
    a = """text
        text
        """
    a = """text
        text"""
    a = """
text
text
"""
    return a

And so on.

Let's choose the only option.

The best option

I vote for the second one:

def f():
    something = """
        text
        text
    """

Because it matches with braces style by PEP-8:

def f():
    something = (
        text,
        text,
    )

Reasoning

Consistency and readability. Let's not allow to break block indentation in such a rough way.

Solution

The motivation behind allowing such awful things is newlines and indentation preserving in multiline strings. However, you should never rely on it because that variable could be moved in constants, function turned into a method, part of the code wrapped into with statement, and a lot more ways how indentation for statement can be changed. So, always use textwrap.dedent, textwrap.indent, and str.strip to get expected indentation and newlines for a multiline string.

help wanted starter rule request

All 12 comments

Awesome!

I see two viable cases:

  • Single lines docstrings are ok:
def test():
    """Docstring."""
  • In multiline string expressions quotes should be located under each other:
def test():
     """
     First line.

     Details.
     """
  • Assignment and other usages should match the indentation:
x = """some text
lines.
"""

Docstrings shouldn't be checked in this violation. There are a lot of plugins that do it by a lot more of much smarter rules.

@orsinium agreed.

@orsinium Since you said that a lot of other plugins have much smarter rules for this functionality, does that mean you don't want this change? Should this issue be closed or does it still need to be addressed?

Still needs, @andreaestrada. But just not the docstring part.

Only

def test():
     x = """
     a
     """

vs

def test():
     x = """
     a
"""

The rule should check all multiline strings except docstrings. Docstrings are checked by other plugins, multiline strings checked by none of them.

Hi, I did some research on this issue and I might have figured out the solution for the assignment case - check indentation against the indentation of two tokens before.
Other usages I thought about, that is comparisons and function calls, look tricky. Shall multiline strings be allowed to use directly (without assigning to a variable)?

Thanks a lot!

Shall multiline strings be allowed to use directly (without assigning to a variable)?

Nope, looks quite unreadable.

Cool, then if you let me do it, I can work on these two multiline string violations

  • usage other that in docstring and assignment
  • wrong indentation in assignment

Or should they be joined / there is something else I haven't thought about?

I would say these two are different violation. The first one is the best practice, the second one is consistency.

Okay, thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sobolevn picture sobolevn  路  4Comments

jtpavlock picture jtpavlock  路  4Comments

orsinium picture orsinium  路  3Comments

sobolevn picture sobolevn  路  4Comments

vnmabus picture vnmabus  路  4Comments