fix: preserve trailing comments when sorting literals - #2647
Open
Manny7717 wants to merge 1 commit into
Open
Conversation
Sorting a literal (sort_reexports or # isort: list/dict/tuple) silently
dropped any trailing comment on the assignment line, e.g.
'__all__ = ["b", "a"] # exports' became '__all__ = ["a", "b"]'.
It also crashed with 'too many values to unpack' whenever the comment
(or a string inside the literal) contained '=', because both call sites
used split("=") without a maxsplit.
- literal.assignment: split on the first '=' only, and re-append
everything after the parsed value's end position (the AST node end)
so trailing comments survive the rewrite.
- core reexport detection: split on the first '=' only.
Closes PyCQA#2646
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Sorting a literal drops a trailing comment, and crashes when the comment (or a string inside the literal) contains
=.Repro (with
--sort-reexports):isort currently produces:
The comment
# public namesis silently deleted. With a comment containing=(or any literal containing=in a string), isort crashes instead:This affects both
--sort-reexportsand the# isort: list/# isort: dict/# isort: tuple/# isort: setinline directives. Closes #2646.Root cause
Two
split("=")calls without amaxsplit:isort/core.pyreexport detection:_, rhs = stripped_line.split("=")— the comment# note: key = valuecontains two=, so the unpacking fails.isort/literal.pyassignment():variable_name, literal = code.split("=")— same crash when the comment or a string element (e.g.["a=b", "c"]) contains=.Separately,
assignment()rebuilt the line as<name> = <sorted literal>and then only re-appended the trailing whitespace of the original line (code[len(code.rstrip()):]), so anything that followed the literal — i.e. a trailing comment — was discarded.Fix
isort/core.py: split on the first=only (split("=", 1)).isort/literal.py:=only;ast.parse(..., mode="eval")(still evaluated viaast.literal_eval), then use the value node's end position to re-append everything that followed the literal verbatim — trailing comments and any trailing whitespace survive the rewrite.Tests
tests/unit/test_literal.py(4 new): trailing comment preserved; trailing comment containing=preserved; literal with=inside a string sorts; trailing comment on a multi-line literal preserved.tests/unit/test_isort.py(3 new): end-to-end--sort-reexportsand# isort: listcases, including a comment containing=(the exact crash from the issue).Regression-proven: all 7 new tests fail on pre-fix
main(4 crash withValueError: too many values to unpack, 3 silently drop the comment) and pass with the fix. The no-comment path is unchanged (existingtest_reexport_*suite still green).Verification
issue_909,issue_938,issue_970,issue_1732) are pre-existingFileNotFoundErrorenv noise, byte-identical on cleanmain.tests/integration/: 12 passed, 1 skipped.mypy isort/literal.py isort/core.py: clean.ruff check/ruff format --check/flake8/ isort self-check on changed files: clean.Note: this PR intentionally does not change the separate "statement after the literal" handling (that's #2286 / PR #2627's scope); it only fixes the comment-drop and the
=crash.AI assistance disclosure: this contribution was developed with assistance from an AI coding agent (Hermes/Lappy on behalf of Manny7717). All changes were locally reproduced, regression-tested (failing before the fix), and verified against the full test suite before opening.