Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit ba46bac

Browse files
committed
Add blank linkes after group of top-level imports
1 parent bd235c9 commit ba46bac

File tree

4 files changed

+54
-7
lines changed

4 files changed

+54
-7
lines changed

rewrite/rewrite/python/_parser_visitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ def visit_Import(self, node):
584584
False,
585585
JContainer(
586586
Space.EMPTY,
587-
[self.__pad_list_element(self.__convert(n), i == len(node.names) - 1) for i, n in
587+
[self.__pad_list_element(self.__convert(n), i == len(node.names) - 1, pad_last=False) for i, n in
588588
enumerate(node.names)],
589589
Markers.EMPTY
590590
)

rewrite/rewrite/python/format/blank_lines.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from typing import Optional, TypeVar, cast
44

55
from rewrite import Tree, P, Cursor
6-
from rewrite.java import J, Space, Statement, JRightPadded, Block, ClassDeclaration, MethodDeclaration
7-
from rewrite.python import PythonVisitor, BlankLinesStyle, CompilationUnit
6+
from rewrite.java import J, Space, Statement, JRightPadded, Block, ClassDeclaration, MethodDeclaration, Import
7+
from rewrite.python import PythonVisitor, BlankLinesStyle, CompilationUnit, MultiImport
88
from rewrite.visitor import T
99

1010
J2 = TypeVar('J2', bound=J)
@@ -26,10 +26,21 @@ def visit_statement(self, statement: Statement, p: P) -> J:
2626

2727
parent_cursor = self.cursor.parent_tree_cursor()
2828
top_level = isinstance(parent_cursor.value, CompilationUnit)
29-
if top_level and statement != cast(CompilationUnit, parent_cursor.value).statements[0]:
30-
statement = minimum_lines_for_tree(statement, self._style.minimum.around_top_level_classes_functions)
31-
elif top_level:
32-
statement = statement.with_prefix(statement.prefix.with_whitespace(''))
29+
if top_level and isinstance(statement, (Import, MultiImport)):
30+
parent_cursor.put_message('previous_import', True)
31+
prev_import = False
32+
else:
33+
prev_import = top_level and parent_cursor.get_message('previous_import', False)
34+
if prev_import:
35+
parent_cursor.put_message('previous_import', False)
36+
37+
if top_level:
38+
if statement == cast(CompilationUnit, parent_cursor.value).statements[0]:
39+
statement = statement.with_prefix(statement.prefix.with_whitespace(''))
40+
else:
41+
min_lines = max(self._style.minimum.around_top_level_classes_functions if isinstance(statement, (ClassDeclaration, MethodDeclaration)) else 0,
42+
self._style.minimum.after_top_level_imports if prev_import else 0)
43+
statement = minimum_lines_for_tree(statement, min_lines)
3344
else:
3445
in_block = isinstance(parent_cursor.value, Block)
3546
in_class = in_block and isinstance(parent_cursor.parent_tree_cursor().value, ClassDeclaration)

rewrite/rewrite/visitor.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ class Cursor:
2525
def get_message(self, key: str, default_value: O) -> O:
2626
return default_value if self.messages is None else cast(O, self.messages.get(key))
2727

28+
def put_message(self, key: str, value: object) -> None:
29+
if self.messages is None:
30+
object.__setattr__(self, 'messages', {})
31+
self.messages[key] = value
32+
2833
def parent_tree_cursor(self) -> Optional[Cursor]:
2934
c = self.parent
3035
while c is not None:

rewrite/tests/python/all/format/blank_lines_test.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,34 @@ class Nested:
8383
from_visitor(BlankLinesVisitor(IntelliJ.blank_lines()))
8484
)
8585
)
86+
87+
88+
def test_blank_lines_after_top_level_imports():
89+
style = IntelliJ.blank_lines()
90+
style = style.with_minimum(
91+
style.minimum.with_after_top_level_imports(3)
92+
)
93+
rewrite_run(
94+
# language=python
95+
python(
96+
"""\
97+
import os
98+
import sys
99+
class Foo:
100+
pass
101+
""",
102+
"""\
103+
import os
104+
import sys
105+
106+
107+
108+
class Foo:
109+
pass
110+
"""
111+
),
112+
spec=RecipeSpec()
113+
.with_recipes(
114+
from_visitor(BlankLinesVisitor(style))
115+
)
116+
)

0 commit comments

Comments
 (0)