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

Black removes blank lines in between a function and a decorated class in a stub file #4256

Open
AlexWaygood opened this issue Feb 28, 2024 · 3 comments
Labels
T: bug Something isn't working

Comments

@AlexWaygood
Copy link
Contributor

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 python/typeshed#11488

@AlexWaygood AlexWaygood added the T: bug Something isn't working label Feb 28, 2024
@cobaltt7
Copy link
Contributor

cobaltt7 commented Mar 4, 2024

In the playground, it looks like your proposed style is already in use? See #1646

@AlexWaygood
Copy link
Contributor Author

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==

@cobaltt7
Copy link
Contributor

cobaltt7 commented Mar 8, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants