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

Allow newlines after block open (or not) #9745

Open
vaughnkoch opened this issue Jan 31, 2024 · 12 comments
Open

Allow newlines after block open (or not) #9745

vaughnkoch opened this issue Jan 31, 2024 · 12 comments
Labels
formatter Related to the formatter style How should formatted code look

Comments

@vaughnkoch
Copy link

Hi, I'm opening this issue per a suggestion from @MichaReiser, based on this closed issue: #8893.

The formatting question is whether Ruff should automatically remove a blank line after a block definition:

def some_func():

    some_more_code()

to

def some_func():
    some_more_code()

The alternative is "allow zero or one" newlines, i.e. not to remove the newline if it exists, but also not to automatically add one. This is the approach that Black chose in their 2024 preview style. Full Black discussion here: psf/black#4043.

@MichaReiser MichaReiser added formatter Related to the formatter style How should formatted code look labels Jan 31, 2024
@cbandera
Copy link

Yes I can second this request as well. While investigating the transition to ruff, this inconsistency to black is causing many changes across our code base.

@MichaReiser
Copy link
Member

Yes I can second this request as well. While investigating the transition to ruff, this inconsistency to black is causing many changes across our code base.

Thanks for reporting. Do you mainly mind that there are many differences or did you prefer black's formatting? Would you be able to share some examples where you preferred black's formatting over ruff's?

@cbandera
Copy link

Yes I can second this request as well. While investigating the transition to ruff, this inconsistency to black is causing many changes across our code base.

Thanks for reporting. Do you mainly mind that there are many differences or did you prefer black's formatting? Would you be able to share some examples where you preferred black's formatting over ruff's?

For me it's mainly about the diff that is created. Working in a big monorepo, it's always easier for us toolies to roll out changes if we don't need to touch the other devs code. Having read that ruff would be a "drop-in" replacement for black, my expectation was that I would see no diff at all.

Having said that and after looking at the known deviations I can't say that I don't agree with ruff's design decisions though...

@chicheng
Copy link

Hi, yes please add an option to preserve up to 1 empty line.

As empty lines used for separating/grouping lines, the first line(s) stay closer to block head but not the remaining parts feel like it's part of the block head (since empty line inside block content is inevitable), e.g.

block head
   part of block head

   block content
   block content
   block content

   block content
   block content

so I prefer to read as

block head

   block content
   block content
   block content

   block content
   block content

Personally I always insert an empty line at the beginning of the block, except 2 scenarios:

class B(A):

    def single_line(self):    # an empty line after `class B`, because single_line() is not closer to B than other methods
        return something    # Two exceptions that no empty line after `def instance_methods():`: 1. one liner, otherwises a few one lines consecutively will feel strange as there are equal space between block head and content and next block head and content

    def override_super(self):
        super().override_super()    # 2. `super()...` call (easier to tell whether non-one-liner class method called super or not? just personal preference probably)

        remaining_codes = ...

    def function(
        self, data: torch.Tensor | tuple[torch.Tensor, ...], other_argument: int
    ) -> torch.Tensor | tuple[torch.Tensor, ...]:
        something = do_something(data)    # An empty line above please, this line is part of method body, not head. borrowed from black issue comment

        return something

@alechouse97
Copy link

Any updates on this? This is one the last remaining issues for ruff to finally replace black in my workflow.

@michaelhball
Copy link

Also checking in to say the same as above, I think this is our last remaining "issue" with ruff.

@dcnadler
Copy link

dcnadler commented Aug 1, 2024

Yes I can second this request as well. While investigating the transition to ruff, this inconsistency to black is causing many changes across our code base.

Agreed, this is what's blocking us from adopting Ruff. Too many diffs - not a "drop-in".

Looking forward to updates, thanks!

@thclark
Copy link

thclark commented Sep 13, 2024

From the perspective of someone with dyslexia; this really makes code harder to read - I need whitespace around the block to help parse what's in it.

@plynch-chwy
Copy link

I was looking to make the switch to ruff and use the handful of ignored linting rules we use with pre-commit. After a couple of hours I only just found that this is an option I can't ignore or set as unfixable? It's kinda unfortunate that this issue is still open for almost a year as I was excited to switch.

@alechouse97 alechouse97 mentioned this issue Nov 25, 2024
29 tasks
@hankertrix
Copy link

Second this change. I only adopted black as a formatter after they implemented this change as I find it very difficult to read code without the extra newline. This is especially so when the start of the block is very long, and there's a comment right underneath the block.

For example:

if long_boolean_variable_name and another_long_conditional:
    # A pretty long comment documenting what the block does
    print("Do stuff")

I find this to be much easier to read:

if long_boolean_variable_name and another_long_conditional:

    # A pretty long comment documenting what the block does
    print("Do stuff")

For formatters in other languages that don't support this extra new line, I use a hack to force a new line:

if (long_boolean_variable_name && another_long_conditional) {
    //

    // A pretty long comment documenting what the block does
    console.log("Do stuff")
}

Since the Pylsp formatter and black already allow an extra new line, I don't bother doing this hack for my Python code. It would be great to have Ruff support this.

@laymonage
Copy link

Hi, what's the status on this? If I'm not mistaken, Black already made this stable in 2024.

I see that this was discussed for #8678 in #8893. Then it was briefly mentioned in the plans for the 2025 style guide in #13371 (comment), but it wasn't planned.

We've switched from black to ruff and loving it, but this issue prevents us from formatting Django migrations without the unnecessary noise of removing empty newlines after the class header that Black leaves as-is.

@dduarteo
Copy link

Was excited to start moving all of our codebases to ruff but discovered this issue with the blank line after func definitions. I second that it makes code much easier to read.

Hopefully this gets implemented in the near future! For now back to black.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
formatter Related to the formatter style How should formatted code look
Projects
None yet
Development

No branches or pull requests