Skip to content

fix: do not add a line continuation to a file without a trailing newline - #369

Open
Eljees wants to merge 1 commit into
PyCQA:masterfrom
Eljees:fix/360-no-trailing-newline
Open

fix: do not add a line continuation to a file without a trailing newline#369
Eljees wants to merge 1 commit into
PyCQA:masterfrom
Eljees:fix/360-no-trailing-newline

Conversation

@Eljees

@Eljees Eljees commented Aug 8, 2026

Copy link
Copy Markdown

docformatter --in-place appends a backslash to the last line of any file that
does not end with a newline, which leaves the file unparseable:

$ printf 'def foo():\n    """\n    Hello foo.\n    """\n    x = 1' > a.py   # no trailing newline
$ docformatter --in-place a.py
$ tail -1 a.py
    x = 1\
$ python -c "import ast; ast.parse(open('a.py').read())"
SyntaxError: unexpected EOF while parsing

This is a regression from #360 (4849fce), found by bisecting the test suite. That
commit changed is_newline_continuation() in classify.py from

and token.line.strip() in prev_token.line.strip()
and token.line not in {"\n", "\r\n"}

to

and token.line.strip()
and token.line.strip() in prev_token.line.strip()

The intent was to stop treating a blank line with trailing whitespace as a
continuation (#355). token.line.strip() also drops the synthetic NEWLINE token
that tokenize emits for a source without a trailing newline -- that token has
line=''. It stops counting as a continuation, _get_unmatched_start_end_indices
moves it onto the next row, and untokenize bridges the gap with a backslash.

The fix adds a small _is_blank_line() helper -- a line that is non-empty and all
whitespace -- so '' passes again while " \n" is still excluded. #355 stays
fixed; I kept its reproducer as a control and it is still green.

Only 3.10 and 3.11 are affected. Under PEP 701 the 3.12+ tokenizer reports the real
line for the synthetic NEWLINE, so the old branch keeps working:

interpreter tokenize for x = 1 without \n test_do_format_code.py
3.10.12, 3.10.20 NEWLINE '' line='' 10 failed, 61 passed
3.12.13 NEWLINE '' line='x = 1' 71 passed

pyproject.toml declares python = "^3.10", so this is a supported version.

Why CI is green

The version matrix does not run the versions it names. From the log of job
ubuntu-latest Python: 3.10, run 30781552231:

tox-gh-actions config: {'python': {'3.10': ['py310'], '3.11': ['py311'], ...}}
using the following factors to decide envlist: ['py313']
platform linux -- Python 3.13.14, pytest-9.1.1

tox is installed under setup-python 3.13, and tox -e py --skip-pkg-install
takes basepython from tox itself, so all six matrix jobs run 3.13.14. That is why
this survived on master for three weeks. Happy to send a separate PR for the
workflow if you want it -- I left it out of this one.

Verification

On e154acb, Python 3.10.12: master is 10 failed, 536 passed; with this change
546 passed, 4 skipped, plus the test added here. Reverting the code and keeping
the test turns exactly issue_360_no_trailing_newline red, with the diff
x = 1 -> x = 1\, while issue_355 stays green.

The synthetic NEWLINE token that tokenize emits for a source without a trailing newline has line='', so the strip() guard added in PyCQA#360 stopped counting it as a continuation and untokenize bridged the row gap with a backslash, corrupting the file. Exclude only blank-but-non-empty lines instead.

Signed-off-by: Eljees <3.14hell@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant