astral-sh / ruff

An extremely fast Python linter and code formatter, written in Rust.
https://docs.astral.sh/ruff
MIT License
32.15k stars 1.08k forks source link

Feature: Support isort multi_line_output option #2600

Open mikelane opened 1 year ago

mikelane commented 1 year ago

The isort module provides many different ways of accomplishing the wrapping for a given project. From my experience, this is a widely used option in projects that use isort, so it would be nice to have this support in ruff.

Ideally, the ruff setting would be something like this:

[tool.ruff.isort]
multi_line_output = 3  # Vertical Hanging Indent

The output options would follow the options settings and option values listed in the isort documentation.

NeilGirdhar commented 1 year ago

If we're re-engineering this, a compact grid mode would be really nice. That is, try:

Choose the one with the fewest lines that fit within the maximum line width. I contributed something like this for isort. But that contribution only bumps to hanging grid when grid is impossible. It would be nice to also bump when hanging grid is shorter.

(Also, just my opinion, but mode 2 that uses line continuation \ should probably be deprecated?)

spaceone commented 1 year ago

We need multi_line_output=5 (vert-grid-grouped).

nicwolff commented 1 year ago

Same, we'd have moved from isort to ruff if it supported multi_line_output=5.

NeilGirdhar commented 1 year ago

Thinking about this more, I would like to see the options in Ruff be something like:

imports_allow_grid = true
imports_allow_vertical = true
imports_parenthesis_on_newline = false

Then the most common ISort modes correspond to:

And add an option to imports_choose_shortest that chooses the shortest representation allowed that fits the options. So just be cause you chose (true, true, false), doesn't mean that it should do somethign crazy like:

from alksdjflks_flaksjdflkajsdfljka_laskjdf_alksjdf_alksjdflaskd_skldj import (some_symbol,
                                                                               some_other_symbol,
                                                                               some_third_symbol,
                                                                               some_fourth_symbol)
# Instead:
from alksdjflks_flaksjdflkajsdfljka_laskjdf_alksjdf_alksjdflaskd_skldj import (
    some_symbol, some_other_symbol, some_third_symbol, some_fourth_symbol)

I'd love to stop using isort, but I don't want to lose my nice imports.

ThiefMaster commented 11 months ago

Would love to see support for multi_line_output=0, can't ditch isort until that's available :)

NeilGirdhar commented 11 months ago

@ThiefMaster That's the one I'm waiting for too. But really, what we need is for Ruff to support both vertical and grid formatting. If we had that, we would have it in the code and the imports.

dhirschfeld commented 11 months ago

I used to use black, ruff and isort to format my code. Now I just use ruff and isort.

When ruff supports multi_line_output=3 I'll be able to just use ruff.

Until such time... I'll continue to monitor this issue 😜

Aeron commented 11 months ago

@dhirschfeld, wait a second. The default formatting behavior is multi_line_output=3, right? It is the vertical hanging indent mode. Am I missing something? I briefly tested it against isort and saw no difference.

Full disclosure: I started working on this feature yesterday since I have some time and attention to spare, but I don’t want to promise anything yet.

MichaReiser commented 11 months ago

I understand that we have different preferences when it comes to formatting code. Black and ruff's formatter have sofar been leaning towards opinionated formatting with few options whereas Ruff's linter is extremely configurable. Ruff's isort is somewhere in between. I believe @charliermarsh expressed once that he intentionally didn't implement all isort options and we're considering making isort its own tool or integrating it into the formatter. This is why I think we should be very deliberate about supporting new isort options that are incompatible with the formatter because we either need to deprecate them again in the future, or they force us to change the direction of the formatter.

NeilGirdhar commented 11 months ago

nd we're considering making isort its own tool or integrating it into the formatter.

I think integrating it into the formatter makes perfect sense. After all, all of these "isort modes" that people are discussing are actually special cases of various formatter output preferences. Ruff currently supports only three output types (single line, hanging single line, and hanging multi-line).

This is why I think we should be very deliberate about supporting new isort options

I agree. I think it makes sense for the import statement formatting to be consistent with code formatting. Therefore, I don't think there should be any isort options at all. What we are really asking for is generalization of the formatter. I understand that that may not be a priority today, but hopefully it will come eventually.

Aeron commented 11 months ago

I had an idea those two could be separate things. The new built-in formatter may have a few opinionated options to organize imports or none at all, and the ruff-isort formatter can be its own thing for people who want a backward-compatible way of doing it.

But yeah, you’re right—formatting kicks after the import organization and ruins the latter if the result is incompatible with those three output types. So the option I described above only would work if users of ruff-isort ditch the new formatter, which is highly unlikely, considering everybody wants a complete package.

I’m good with the current vertical hanging indent approach since I’m using it anyway. But people want grids. Yet meddling with the new formatter is a different beast than adding support for isort modes separately.

Ok, I put my implementation on pause then. It’ll wait until a decision.

nineteendo commented 8 months ago

I believe this would also benefit RUF022:

__all__ = [
    "a", "b", "c",
]
eli-schwartz commented 8 months ago

I understand that we have different preferences when it comes to formatting code. Black and ruff's formatter have sofar been leaning towards opinionated formatting with few options whereas Ruff's linter is extremely configurable. Ruff's isort is somewhere in between. I believe @charliermarsh expressed once that he intentionally didn't implement all isort options and we're considering making isort its own tool or integrating it into the formatter. This is why I think we should be very deliberate about supporting new isort options that are incompatible with the formatter because we either need to deprecate them again in the future, or they force us to change the direction of the formatter.

As someone who is currently uninterested in the formatter, but interested in the linter, I would be happy if ruff check --select I supported all isort modes (mode 5 for me personally), and don't have an opinion on whether ruff format should.

Maybe it could raise a fatal error that says those modes aren't allowed in the formatter?

vkbo commented 6 months ago

I would love to see this feature added as well. A lack of mode 5 support is pretty much the only thing preventing me from using ruff. The current formatting option for imports is incredibly wasteful for code with a lot of short imports in few modules, like my Qt5-based project where you import a lot of GUI components in every file.