-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Option to sort re-exports in __all__
(sort_exports
from isort)
#1198
Comments
Is this undocumented behavior? |
isort has not had a release for over a year so it's one of the features that never ended up getting released. Actually, that reminds me of another (more important) feature that also has not been released yet, and seems like ruff isn't handling it properly either, will make an issue in a moment. |
Note that there's another functionality that is available in a released version of isort - sorting literals that are prepended with One thing that both of these don't support is |
Oh yeah, this was brought to my attention on Twitter. I think we could support this! There are some other things I need to get done before I spend time on it though. |
I have a suggestion to extend this feature request a bit and allow sorting by the definition order of names (functions/classes/variables) that are put in So for example: from .submodule import reexported_name
__all__ = (
"reexported_name",
"function_b",
"X",
"function_a",
"function_c",
"Y",
)
def function_b():
...
class X:
...
def function_a():
...
def function_c():
...
class Y:
... The reason for such a suggestion is that I think it makes it easier to find out what names of public APIs are missing in |
For reference, there's another tool available to sort I guess it could be used to get rid of |
Hmm, forget about That being said, regarding the sorting order, I also proposed to add support for another one that would be a case-insensitive lexicographical sorting. Not sure how popular or common this is. |
@cpendery - Yeah I'm open to including this. We'll need to decide how it should be categorized (i.e., does it go in the |
@charliermarsh I think it probably should be categorized as Ruff specific rule since it was never an officially released isort feature, especially if we extend it with the additional functionality of multiple sorting options |
This existed with isort's |
We've tried using isort's
We found a new package https://pypi.org/project/sort-all/ which fixes these issues, however that package has one drawback of removing the comments in the |
Adding to @harshil21 s comment, I'd like to mention that we're also interested in sorting |
I'm working on a PR to implement this feature. |
So, a question on this: what should ruff do if it encounters something like this? __all__ = [
"d",
"c",
# a comment introducing a new section for 'b' and 'a':
"b",
"a",
] Should it:
I think the thing we probably shouldn't do in this kind of situation is this: __all__ = [
"a",
"b",
# a comment introducing a new section for 'b' and 'a':
"c",
"d",
] |
For alphabetical definitely option 2. For sort by definition order I'm not really sure what would work best, I guess anything is fine though I would definitely prefer if whatever it does didn't require a manual fix. |
This is an interesting question. I would expand the example by one that uses a non-section defining comment: __all__ = [
"c",
# TODO: Remove once #0000 is complete
"a"
] In this case, I would expect the comment to move with From what I understand is that isort requires the use of isort suppression comments to suppress import sorting. What if we would do the same for __all__ = [
"c",
"d",
# a comment introducing a new section for 'b' and 'a':
"a", # noqa: RUFXXX Don't move
"b",
] or __all__ = [
"c",
"d",
# a comment introducing a new section for 'b' and 'a': # noqa: RUFXXX Don't move
"a",
"b",
] |
Yes, that's exactly the kind of thing I was worrying about w.r.t. Option (2) -- thanks!
That's an interesting idea! Let's call that Option (4). I worry with Option (4) that the precise semantics of the Here's three possible things the
I guess I'm leaning towards Option (3) in my original selection of options:
If neither of the above is what the user wants, they can just |
FWIW, my initial implementation of this rule is just going to do "sort by alphabetical order", so that I can get a MVP out there :) We can possibly implement "sort by definition order" as a followup. |
That's fair. Do you know how common the use of sections is? If they're uncommon, then disabling sorting for the entire Is there some sort of a community standard when it comes to formatting section comments, that we could use to identify them? If not, could we allow users to configure a regex to identify the section comments?
I fear that a project-level configuration might not be granular enough, but maybe it is. I really don't know.
That's an excellent plan. Let's get sorting working and figure out how to disable sorting at a later stage :) |
I think they're reasonably common, but I don't really know -- I might just think this because I spend a fair amount of time staring at
I don't think so, not really :( Historically, there hasn't been a well-established tool for people to check the ordering of their
Here's an idea: as well as simple __all__ = [ # ruff: sort-by-section
...
] ...then that would override the global config setting, and ruff would treat all comments taking up their own line in that |
I'm a bit hesitant of adding more "magic comments" because they're hard to remember and not easily understood. You can't click on them and get an explanation of what they do; you need to know in which places they're allowed, and they don't work well with auto formatters (formatter needs to understand them as well). That's why I would favor a solution that doesn't require a new pragma comment. |
## Summary This implements the rule proposed in #1198 (though it doesn't close the issue, as there are some open questions about configuration that might merit some further discussion). ## Test Plan `cargo test` / `cargo insta review`. I also ran this PR branch on the CPython codebase with `--fix --select=RUF022 --preview `, and the results looked pretty good to me. --------- Co-authored-by: Micha Reiser <[email protected]> Co-authored-by: Andrew Gallant <[email protected]>
Okay, #9474 has now been merged! The next release of Ruff should include a rule and autofix to keep your
Currently the rule is not configurable. We might consider adding some configuration options in the future, but for now we've decided to wait to see how much demand there is for that in the community. The rule has been added as RUF022 rather than as an isort rule, since it seems like it doesn't really have much to do with imports. While isort does have this functionality, it's never been documented. Enjoy tidying up your |
## Summary This PR introduces a new rule to sort `__slots__` and `__match_args__` according to a [natural sort](https://en.wikipedia.org/wiki/Natural_sort_order), as was requested in #1198 (comment). The implementation here generalises some of the machinery introduced in 3aae16f so that different kinds of sorts can be applied to lists of string literals. (We use an "isort-style" sort for `__all__`, but that isn't really appropriate for `__slots__` and `__match_args__`, where nearly all items will be snake_case.) Several sections of code have been moved from `sort_dunder_all.rs` to a new module, `sorting_helpers.rs`, which `sort_dunder_all.rs` and `sort_dunder_slots.rs` both make use of. `__match_args__` is very similar to `__all__`, in that it can only be a tuple or a list. `__slots__` differs from the other two, however, in that it can be any iterable of strings. If slots is a dictionary, the values are used by the builtin `help()` function as per-attribute docstrings that show up in the output of `help()`. (There's no particular use-case for making `__slots__` a set, but it's perfectly legal at runtime, so there's no reason for us not to handle it in this rule.) Note that we don't do an autofix for multiline `__slots__` if `__slots__` is a dictionary: that's out of scope. Everything else, we can nearly always fix, however. ## Test Plan `cargo test` / `cargo insta review`. I also ran this rule on CPython, and the diff looked pretty good --- Co-authored-by: Micha Reiser <[email protected]>
Isort allows sorting
__all__
whensort_reexports
is used:https://github.com/PyCQA/isort/blob/f547290178f86b6e5f0007cf1cb31d4736dcdaee/isort/core.py#L235-L241
The text was updated successfully, but these errors were encountered: