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

isort: Add support for the from-first setting #8663

Merged
merged 3 commits into from
Nov 21, 2023

Conversation

jelmer
Copy link
Contributor

@jelmer jelmer commented Nov 13, 2023

Summary

This setting behaves similarly to the from_first setting in isort upstream, and sorts "from X import Y" type imports before straight imports.

Like the other PR I added, happy to refactor if this is better in another form.

Fixes #8662

Test plan

I've added a unit test, and ran this on a large codebase that relies on this setting in isort to verify it doesn't have unexpected side effects.

Copy link
Contributor

github-actions bot commented Nov 13, 2023

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@jelmer jelmer marked this pull request as ready for review November 13, 2023 20:27
@charliermarsh charliermarsh added the isort Related to import sorting label Nov 14, 2023
Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we instead explore incorporating this into ModuleKey and MemberKey? We carved those out recently to make the sorting easier to modify.

@jelmer
Copy link
Contributor Author

jelmer commented Nov 14, 2023

Could we instead explore incorporating this into ModuleKey and MemberKey? We carved those out recently to make the sorting easier to modify.

How to do that doesn't seem obvious to me - I'd be grateful for some feedback.

from_first applies in isort even if force_within_sections is not enabled; see https://github.com/PyCQA/isort/blob/c574c4c190ceddb66b10330ae811a95306f07b74/isort/output.py#L90

I could add something like ModuleKey, e.g. ImportTypeKey?

Alternatively perhaps a preferred_import_type: Option<bool> (set to Some(true) for ImportFrom when first_from is enabled, and Some(true) for Imports if it is not enabled) to ModuleKey, and make from_first imply force_sort_within_sections. That's diverging slightly from isort, but I'm not sure if that's a big deal?

@charliermarsh
Copy link
Member

@bluthej - Curious if you have any thoughts on how from-first could be rolled into the new sort key design?

@bluthej
Copy link
Contributor

bluthej commented Nov 14, 2023

I guess I would have done something along those lines, the only thing is I don't see why we need a Box in there... I'll take a closer look when I get a chance!

The alternative would be to add an item in ModuleKey that should be positioned appropriately to either have straight and from imports one way, the other way or mixed (with force-sort-within-sections).

FWI I just submitted a quick PR that moves some of this logic into order.rd. This was only a small refactor to make things a bit more tidy but I thought I'd mention it just in case :)

@jelmer
Copy link
Contributor Author

jelmer commented Nov 14, 2023

I guess I would have done something along those lines, the only thing is I don't see why we need a Box in there... I'll take a closer look when I get a chance!

The alternative would be to add an item in ModuleKey that should be positioned appropriately to either have straight and from imports one way, the other way or mixed (with force-sort-within-sections).

FWI I just submitted a quick PR that moves some of this logic into order.rd. This was only a small refactor to make things a bit more tidy but I thought I'd mention it just in case :)

I had trouble coercing rust into thinking that the two iterators were the same type - the only way I managed to was with a box. That's probably just my ignorance on the rust side..

This setting behaves similarly to the ``from_first`` setting in isort
upstream, and sorts "from X import Y" type imports before straight
imports.

Fixes astral-sh#8662
@jelmer
Copy link
Contributor Author

jelmer commented Nov 16, 2023

@charliermarsh PTAL; now updated after the recent refactoring. It no longer uses box, and mimicks the behaviour in isort.

@bluthej
Copy link
Contributor

bluthej commented Nov 18, 2023

@charliermarsh I had a closer look at the changes (sorry for the delay, I've been kind of swamped). I personally think this implementation is the way to go. In my mind, the items in ModuleKey are useful for when we really have to do the comparison on a per import basis, whereas here we are ordering two broad classes of imports (namely straight and from imports). We would be doing way more comparisons than by just doing one if statement to order the blocks, as proposed here. Plus it's not like there's a "dynamic range" of import types for this setting, there's just straight and from imports.

@jelmer I had a feeling collect would help get rid of the Boxes ;)

My only comment is that there does not seem to be any interaction between this setting and force-sort-within-sections. When force-sort-within-sections = true I don't think we should be placing blank lines between straight and from imports. Plus I just tested it on the latest Ruff release and setting both options currently has an odd behavior, namely it will only place a blank line before the first from import that appears after a straight import!
If you both agree, I think it would be nice to fix it in this PR, but I'd be happy to submit a separate PR after this one if you prefer :)

@charliermarsh
Copy link
Member

If you both agree, I think it would be nice to fix it in this PR, but I'd be happy to submit a separate PR after this one if you prefer :)

I agree. Do you have a sense of how to make that change? It may just be easier to put up a separate PR on top of this one and I can merge them in order.

@bluthej
Copy link
Contributor

bluthej commented Nov 19, 2023

The most straightforward way to fix it would be to add && !settings.force_sort_within_sections in the if statements that add the lines. Of course there should be a test for that!
@jelmer would you like to take care of it or should I make a PR on top of yours?

But I don't know what the general policy is regarding incompatible settings in Ruff, do you usually make one setting silently override the other or do you throw an error and notify the user that their config is inconsistent?

@jelmer
Copy link
Contributor Author

jelmer commented Nov 20, 2023

@bluthej My setup actually relies on both force-sort-within-sections and from-first together in our isort config, with only a single empty line appearing before the first from import - although it might only make sense if you only use no_sections.

The force_alphabetical_sort setting in isort specifically sets these options together:

https://github.com/PyCQA/isort/blob/b67a6a595803710f6af52865d82d996f264224c6/isort/settings.py#L278

@bluthej
Copy link
Contributor

bluthej commented Nov 20, 2023

@jelmer I'm sorry my message was totally confusing, what I really meant to say was that there does not seem to be any interaction between force_sort_within_sections and lines_between_types, which is loosely related to from_first because you had to handle the insertion of blank lines. That's something I hadn't noticed prior to looking at your PR, that's why I was mentioning it.

@bluthej
Copy link
Contributor

bluthej commented Nov 20, 2023

But that makes me think this PR is fine, I'll open a separate issue for that.

@jelmer
Copy link
Contributor Author

jelmer commented Nov 21, 2023

@jelmer I'm sorry my message was totally confusing, what I really meant to say was that there does not seem to be any interaction between force_sort_within_sections and lines_between_types, which is loosely related to from_first because you had to handle the insertion of blank lines. That's something I hadn't noticed prior to looking at your PR, that's why I was mentioning it.

Ah, sorry, I did indeed misunderstand. That makes sense to me though - both your comments on force_sort_within_sections and lines_between_types interactions, and doing that as a separate change.

Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@charliermarsh charliermarsh enabled auto-merge (squash) November 21, 2023 23:31
@charliermarsh charliermarsh merged commit f1ed0f2 into astral-sh:main Nov 21, 2023
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
isort Related to import sorting
Projects
None yet
Development

Successfully merging this pull request may close these issues.

isort: support for from_first setting
3 participants