psf / black

The uncompromising Python code formatter
https://black.readthedocs.io/en/stable/
MIT License
37.87k stars 2.4k forks source link

Black is inconsistent with empty lines before an inner function after code block open, with or without leading comments #3300

Open yilei opened 1 year ago

yilei commented 1 year ago

To Reproduce

Unformatted code:

def main():
    if a:

        # Comment
        def b():
            pass

    if b:
        def c():
            pass

Running black --preview:

def main():
    if a:
        # Comment
        def b():
            pass

    if b:

        def c():
            pass

Expected behavior

Empty line should be consistent added (or removed) between the code block open and inner function:

def main():
    if a:

        # Comment
        def b():
            pass

    if b:

        def c():
            pass

Or,

def main():
    if a:
        # Comment
        def b():
            pass

    if b:
        def c():
            pass

Additional context

I did a bisect and this was caused by https://github.com/psf/black/pull/3035.

Note that if the inner function doesn't have a leading comment, it won't remove the empty line:

def main():
    if a:

        def b():
            pass

        def c():
            pass

Thus I believe this is an undesired behavior change in #3035?

yilei commented 1 year ago

246 is possibly related since that's also caused by a comment before the function def.

ichard26 commented 1 year ago

I agree this should be fixed.

yilei commented 1 year ago

Looking at EmptyLineTracker, it is indeed the same underlying issue as #246, that the tracker isn't capable of doing this when there are preceding standalone comments. I'll take a stab at a fix.

felix-hilden commented 1 year ago

Having a look at #3035, I'd expect the newline to be removed before the first function regardless of the comment. Would you prefer otherwise?

yilei commented 1 year ago

I would actually personally prefer the newline to be removed after a block open.

I saw this is inconsistent with or without the comment, plus the current Black style says:

It will also insert proper spacing before and after function definitions. It’s one line before and after inner functions...

This is the "inner function" case.

So I'm slightly in favor of changing the preview style to always remove the newline before an inner function and immediately after a block open, with or without the leading comment (I'm strong on making the behavior consistent with or without comment). I can send a separate PR to do that once we make decision. Meanwhile I updated #3302 to keep the current behavior for this case.

felix-hilden commented 1 year ago

I'm fully in favor of doing it, but it's fine to keep the original behavior if you'd like to 👍 I think the inner function spacing rule is secondary to the "no space in a new block" rule.

yilei commented 1 year ago

@felix-hilden Thanks. Mind approve #3302 and get it merged to fix #246? Then I'll send a follow-up PR to for this issue.

felix-hilden commented 1 year ago

Done, we'll wait for another approval since Jelle's is a bit stale. Thanks!