black
black copied to clipboard
Black removes blank lines in between a function and a decorated class in a stub file
Describe the bug
Black reformats the following .pyi stub file:
def foo(): ...
@decorator
class Bar: ...
to this:
def foo(): ...
@decorator
class Bar: ...
If Bar does not have a decorator, black permits the empty line between the two definitions. I think the empty line improves readability here quite a bit, so I'd prefer it if black would allow (or even enforce it). Decorated classes haven't historically been very common in stub files (previously, I think the only major one was maybe @final?), but we'll get more of them now that we have @deprecated: see https://github.com/python/typeshed/pull/11488
In the playground, it looks like your proposed style is already in use? See #1646
In the playground, it looks like your proposed style is already in use? See #1646
Only if it's a class immediately above a decorated class. Not if it's a function immediately above a decorated class: https://black.vercel.app/?version=stable&state=_Td6WFoAAATm1rRGAgAhARYAAAB0L-Wj4ACKAF9dAD2IimZxl1N_WlbvK5V9KEd0sx-TZ0FnYDKJ6OX-sy6nZgP3nGXyHJgcqCH6v6tfJav-EW9IH8hqY465hu6wVnOUHSfDHFhNX3vof0-eHIaWUPgs2FTjIfQkXhvXF0MDAABGu4hcNTXESAABe4sBAAAAOc863LHEZ_sCAAAAAARZWg==
I tried fixing this but ran into some issues. Writing this as a reference for anyone else who decides to try.
For context, Black’s current style is to add blank lines around all stub classes. No blank lines are added between function stubs. The issue is that both classes and functions can be decorated. Decorated stub classes next to each other behave correctly since there’s always a blank line around them. We want to keep stub functions together, even if there’s a decorator, which works well. The issue arises when you mix and match stub functions, stub classes, and decorators.
Take the example raised in this issue:
def foo(): ...
@decorator
class Bar: ...
While determining whether to add empty lines around a line of code, Black has access to the current and previous lines of code. We can't add a line before @decorator() because the following line could be a def, and defs should always stay together. We can't add a line after def foo(): ... simply because it currently has no way of knowing what comes next, and that there should be a blank line there.
There’s probably still a fix here, but it’d require more substantial refactors to Black’s code.