Python: fix ChangeImport leaving stray leading newline when import is the only statement#7433
Merged
knutwannheden merged 1 commit intomainfrom Apr 20, 2026
Merged
Conversation
…is the only statement When `ChangeImport` replaced the only statement in a file, the scheduled `AddImport` pass ran against an empty statement list and fell through to the "inserting after existing imports" branch, prefixing the new import with `\n` and producing `\nfrom collections.abc import Callable\n`. Handle the empty-statement-list case explicitly: the new import becomes the sole statement with empty prefix; the trailing newline stays in `cu.eof`.
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.
Motivation
rewrite.python.recipes.ChangeImportleft a stray leading\nat the start of the file when it replaced an import that was the only statement in the file. The bug is masked whenever the test snippet has a statement after the import (the leading\nends up between two lines instead of at file start and isn't visible inprint_all()output), but surfaces for import-only files.Discovered while converting search-only recipes in
moderneinc/rewrite-migrate-pythonto useChangeImport. As a data point,rewrite-migrate-python'styping_deprecations.py_make_pep585_editorexplicitly strips a leading\nfrom the first remaining statement's prefix invisit_compilation_unitas a workaround — this fix should make that workaround unnecessary.Example
Summary
ChangeImportreplaced the only statement in a file, the scheduledAddImportpass ran against an empty statement list and fell through to the "inserting after existing imports" branch, prefixing the new import with\n.add_import.py::_add_import: the new import becomes the sole statement with empty prefix; the trailing newline stays incu.eof.test_change_import_only_statementcovering the import-only case.Test plan
test_change_import_only_statementregression test reproduces the bug and now passesChangeImporttests passtest_add_import.py,test_remove_import.py,tests/recipes/) pass