Version: docformatter 1.7.8 (not present in: 1.7.7)
Config (pyproject.toml):
[tool.docformatter]
recursive = true
in-place = true
black = true
Description:
docformatter modifies string literals that are not docstrings when they appear as arguments to function calls (e.g. textwrap.dedent()). This corrupts valid, black-formatted code.
Steps to reproduce:
Start with the following black-formatted file (bug.py):
from dataclasses import dataclass
from textwrap import dedent
import pytest
@dataclass
class Finding:
line_number: int
secret: str
@pytest.mark.parametrize(
"arg1, arg2, arg3",
[
(
".env",
dedent("""KEY_ONE=value1
KEY_TWO=value2
KEY_THREE=value3."""),
[
Finding(line_number=2, secret="KEY_ONE=value1"),
Finding(
line_number=3,
secret="KEY_TWO=value2",
),
],
),
(
"",
dedent("""
-----BEGIN EXAMPLE BLOCK-----
c29tZWJhc2U2NGVuY29kZWRjb250ZW50
-----END EXAMPLE BLOCK-----
"""),
[
Finding(line_number=2, secret="-----BEGIN EXAMPLE BLOCK-----"),
],
),
],
)
def test_fun(arg1, arg2, arg3):
pass
Run:
docformatter --config pyproject.toml --diff bug.py
Actual output (docformatter rewrites the file to):
@dataclass
class Finding:
line_number: int
secret: str
@pytest.mark.parametrize( # ← blank lines between class and decorator removed
"arg1, arg2, arg3",
[
(
".env",
dedent(\ # ← backslash continuation injected
"""KEY_ONE=value1 KEY_TWO=value2 KEY_THREE=value3."""
), # ← trailing blank line + mangled indentation
...
),
(
"",
dedent(\ # ← same corruption on multiline string
"""-----BEGIN EXAMPLE BLOCK-----
c29tZWJhc2U2NGVuY29kZWRjb250ZW50
-----END EXAMPLE BLOCK-----
"""
),
...
),
],
)
def test_fun(arg1, arg2, arg3):
pass
Expected behavior:
docformatter should not touch string literals that are not docstrings. Arguments passed to dedent() (or any other function) are data, not documentation, and must be left unchanged. The black-formatted input is the correct output.
Observed issues (summary):
- Blank lines eaten — the two blank lines between the
@dataclass class body and the next decorator are removed, violating PEP 8 and black's output.
- Backslash continuation injected —
dedent("""...""") is rewritten to dedent(\↵ """..."""), which changes the AST and breaks indentation-sensitive code like textwrap.dedent.
- Trailing blank lines added inside the argument — a spurious blank line is inserted before the closing
) of the dedent() call.
- Indentation of closing parenthesis mangled — the
) is placed at a column that matches neither black's style nor the original.
Issues 2–4 together change runtime behaviour: textwrap.dedent receives a differently-indented string, so the result of the call changes.
Workaround:
None found. The --skip-string-normalization flag does not apply here; there is no per-call-site escape hatch.
Version: docformatter 1.7.8 (not present in: 1.7.7)
Config (
pyproject.toml):Description:
docformatter modifies string literals that are not docstrings when they appear as arguments to function calls (e.g.
textwrap.dedent()). This corrupts valid, black-formatted code.Steps to reproduce:
Start with the following black-formatted file (
bug.py):Run:
Actual output (docformatter rewrites the file to):
Expected behavior:
docformatter should not touch string literals that are not docstrings. Arguments passed to
dedent()(or any other function) are data, not documentation, and must be left unchanged. The black-formatted input is the correct output.Observed issues (summary):
@dataclassclass body and the next decorator are removed, violating PEP 8 and black's output.dedent("""...""")is rewritten todedent(\↵ """..."""), which changes the AST and breaks indentation-sensitive code liketextwrap.dedent.)of thededent()call.)is placed at a column that matches neither black's style nor the original.Issues 2–4 together change runtime behaviour:
textwrap.dedentreceives a differently-indented string, so the result of the call changes.Workaround:
None found. The
--skip-string-normalizationflag does not apply here; there is no per-call-site escape hatch.