Skip to content

1.7.8 rewrites the contents of a non-docstring triple-quoted string, silently changing its value #366

Description

@alexander-turner

docformatter 1.7.8 treats a triple-quoted string that opens a parenthesized concatenation as a docstring and reformats its contents: it splits the first sentence off, indents the remainder by four spaces, and moves the closing quotes onto their own line. The file still compiles, so the only effect is that the string the program builds is wrong.

Reproducer

X = (
    """#!/bin/bash
# Ends here.
# A second line.
_real="""
    + "y"
)
$ docformatter --in-place t.py
$ python3 -c "ns={}; exec(open('t.py').read(), ns); print(repr(ns['X']))"
version value of X
1.7.7 '#!/bin/bash\n# Ends here.\n# A second line.\n_real=y'
1.7.8 '#!/bin/bash\n# Ends here.\n\n # A second line.\n _real=\n y'

No config file and no flags are needed. The trigger is the string's position: the same literal assigned directly to a name is left alone.

# Ends here. matters because the trailing period is what makes docformatter treat the first line as a summary and split a description off after it.

Scale

Running 1.7.7 and 1.7.8 over the same 1,257-file tree, one file at a time, on CPython 3.11: of the 1,250 files both versions processed without error, 475 come out different. Most are docstring-formatting changes that look intentional, but this class is in there and is invisible: the output parses, so nothing downstream complains.

Root cause

git bisect between v1.7.7 and 1b3f03d names 926d9f0 ("refactor: split long functions into smaller functions", #318) as the first bad commit. Its parent fe1a85f is clean. Being a refactor, the behavior change looks unintended.

This is the same family as #344 (non-docstring literals in call arguments), but a different position: a parenthesized concatenation rather than a call argument, so #364 does not cover it. The reproducer above works as a test case.

Environment

CPython 3.11.15, Linux x86-64, docformatter==1.7.8 from PyPI. Still present on master.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C: conventionRelates to docstring format conventionP: bugPEP 257 violation or existing functionality that doesn't work as documentedU: high

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions