Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stubs: preserve blank line between attributes and methods #2736

Merged
merged 1 commit into from Jan 7, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -17,6 +17,8 @@
- Tuple unpacking on `return` and `yield` constructs now implies 3.8+ (#2700)
- Unparenthesized tuples on annotated assignments (e.g
`values: Tuple[int, ...] = 1, 2, 3`) now implies 3.8+ (#2708)
- For stubs, one blank line between class attributes and methods is now kept if there's
at least one pre-existing blank line (#2736)

### Packaging

Expand Down
21 changes: 17 additions & 4 deletions src/black/lines.py
Expand Up @@ -448,7 +448,14 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
depth = current_line.depth
while self.previous_defs and self.previous_defs[-1] >= depth:
if self.is_pyi:
before = 0 if depth else 1
assert self.previous_line is not None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary given self.previous_defs?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this was added to please mypy.

if depth and not current_line.is_def and self.previous_line.is_def:
# Empty lines between attributes and methods should be preserved.
before = min(1, before)
elif depth:
before = 0
else:
before = 1
else:
if depth:
before = 1
Expand Down Expand Up @@ -532,9 +539,15 @@ def _maybe_empty_lines_for_class_or_def(
elif (
current_line.is_def or current_line.is_decorator
) and not self.previous_line.is_def:
# Blank line between a block of functions (maybe with preceding
# decorators) and a block of non-functions
newlines = 1
if not current_line.depth:
# Blank line between a block of functions (maybe with preceding
# decorators) and a block of non-functions
newlines = 1
else:
# In classes empty lines between attributes and methods should
# be preserved. The +1 offset is to negate the -1 done later as
# this function is indented.
newlines = min(2, before + 1)
else:
newlines = 0
else:
Expand Down
27 changes: 25 additions & 2 deletions tests/data/stub.pyi
Expand Up @@ -2,32 +2,55 @@ X: int

def f(): ...


class D:
...


class C:
...

class B:
...
this_lack_of_newline_should_be_kept: int
def b(self) -> None: ...

but_this_newline_should_also_be_kept: int

class A:
attr: int
attr2: str

def f(self) -> int:
...

def g(self) -> str: ...



def g():
...

def h(): ...


# output
X: int

def f(): ...

class D: ...
class C: ...
class B: ...

class B:
this_lack_of_newline_should_be_kept: int
def b(self) -> None: ...

but_this_newline_should_also_be_kept: int

class A:
attr: int
attr2: str

def f(self) -> int: ...
def g(self) -> str: ...

Expand Down