Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions isort/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,11 @@ def process(
if not_imports:
above_import_section: str = ""
if not was_in_quote and config.lines_before_imports > -1:
if line.strip() == "" and not end_of_file:
# A pending ``next_import_section`` means ``line`` was emptied because an
# import at another indentation level starts a new section; it is not a
# blank line and must not be deferred, or the current section is only
# flushed at the end of the file and the next one is never written.
if line.strip() == "" and not end_of_file and not next_import_section:
Comment thread
Copilot marked this conversation as resolved.
lines_before += line
continue
if not import_section:
Expand Down Expand Up @@ -548,7 +552,14 @@ def process(
ignore_whitespace=config.ignore_whitespace,
)
output_stream.write(sorted_import_section)
if not line and not indent and next_import_section:
if (
not line
and not indent
and next_import_section
and config.lines_before_imports == -1
):
# With ``lines_before_imports`` set, the next section is
# already preceded by exactly that many blank lines.
output_stream.write(line_separator)

if indent:
Expand Down
40 changes: 40 additions & 0 deletions tests/unit/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2748,3 +2748,43 @@ def test_float_to_top_keeps_indented_semicolon_imports_in_place() -> None:
isort.code("def f():\n import b; import a # comment\n", float_to_top=True)
== "def f():\n import a # comment\n import b\n"
)


def test_lines_before_imports_keeps_import_after_indented_block() -> None:
"""A top-level import that follows an indented import block must not be dropped
when ``lines_before_imports`` is set.

The indentation change empties ``line`` to start the next section, and the
``lines_before_imports`` handling took that for a blank line and deferred it. The
indented section was then only flushed at the end of the file, and the top-level
one queued behind it was never written. Once written, it is preceded by exactly
``lines_before_imports`` blank lines, like any other import section.
"""
code = "if sys:\n import a\n\nimport b\n"
for lines_before_imports in (0, 1, 2):
expected = "if sys:\n import a\n" + "\n" * lines_before_imports + "import b\n"
output = isort.code(code, lines_before_imports=lines_before_imports)
assert output == expected
assert isort.code(output, lines_before_imports=lines_before_imports) == output

code = (
"import sys\n"
"\n"
"if sys.version_info >= (3, 11):\n"
" from typing import Never\n"
"else:\n"
" from typing_extensions import Never\n"
"\n"
"import third_party_library\n"
)
assert isort.code(code, lines_before_imports=1) == (
"\n"
"import sys\n"
"\n"
"if sys.version_info >= (3, 11):\n"
" from typing import Never\n"
"else:\n"
" from typing_extensions import Never\n"
"\n"
"import third_party_library\n"
)
Loading