Skip to content

Commit

Permalink
Merge pull request #1693 from PyCQA/issue/1645
Browse files Browse the repository at this point in the history
Issue/1645
  • Loading branch information
timothycrosley committed Mar 17, 2021
2 parents 9042488 + cb896cd commit 359c105
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,7 @@ Find out more about isort's release policy [here](https://pycqa.github.io/isort/
- Implemented #1638 / #1644: Provide a flag `--overwrite-in-place` to ensure same file handle is used after sorting.
- Implemented #1684: Added support for extending skips with `--extend-skip` and `--extend-skip-glob`.
- Implemented #1688: Auto identification and skipping of some invalid import statements.
- Implemented #1645: Ability to reverse the import sorting order.
- Documented #1685: Skip doesn't support plain directory names, but skip_glob does.

### 5.7.0 December 30th 2020
Expand Down
6 changes: 6 additions & 0 deletions isort/main.py
Expand Up @@ -562,6 +562,12 @@ def _build_arg_parser() -> argparse.ArgumentParser:
action="store_true",
help="Reverse order of relative imports.",
)
output_group.add_argument(
"--reverse-sort",
dest="reverse_sort",
action="store_true",
help="Reverses the ordering of imports.",
)
inline_args_group.add_argument(
"--sl",
"--force-single-line-imports",
Expand Down
6 changes: 5 additions & 1 deletion isort/output.py
Expand Up @@ -54,12 +54,15 @@ def sorted_imports(
key=lambda key: sorting.module_key(
key, config, section_name=section, straight_import=True
),
reverse=config.reverse_sort,
)

from_modules = parsed.imports[section]["from"]
if not config.only_sections:
from_modules = sorting.naturally(
from_modules, key=lambda key: sorting.module_key(key, config, section_name=section)
from_modules,
key=lambda key: sorting.module_key(key, config, section_name=section),
reverse=config.reverse_sort,
)

straight_imports = _with_straight_imports(
Expand Down Expand Up @@ -233,6 +236,7 @@ def _with_from_imports(
config.force_alphabetical_sort_within_sections,
section_name=section,
),
reverse=config.reverse_sort,
)
if remove_imports:
from_imports = [
Expand Down
1 change: 1 addition & 0 deletions isort/settings.py
Expand Up @@ -210,6 +210,7 @@ class _Config:
honor_case_in_force_sorted_sections: bool = False
sort_relative_in_force_sorted_sections: bool = False
overwrite_in_place: bool = False
reverse_sort: bool = False

def __post_init__(self):
py_version = self.py_version
Expand Down
6 changes: 4 additions & 2 deletions isort/sorting.py
Expand Up @@ -96,7 +96,9 @@ def section_key(line: str, config: Config) -> str:
return f"{section}{len(line) if config.length_sort else ''}{line}"


def naturally(to_sort: Iterable[str], key: Optional[Callable[[str], Any]] = None) -> List[str]:
def naturally(
to_sort: Iterable[str], key: Optional[Callable[[str], Any]] = None, reverse: bool = False
) -> List[str]:
"""Returns a naturally sorted list"""
if key is None:
key_callback = _natural_keys
Expand All @@ -105,7 +107,7 @@ def naturally(to_sort: Iterable[str], key: Optional[Callable[[str], Any]] = None
def key_callback(text: str) -> List[Any]:
return _natural_keys(key(text)) # type: ignore

return sorted(to_sort, key=key_callback)
return sorted(to_sort, key=key_callback, reverse=reverse)


def _atoi(text: str) -> Any:
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/test_ticketed_features.py
Expand Up @@ -1029,3 +1029,33 @@ def test_isort_auto_detects_and_ignores_invalid_from_imports_issue_1688():
from package3 import also_ok
"""
)


def test_isort_allows_reversing_sort_order_issue_1645():
"""isort allows reversing the sort order for those who prefer Z or longer imports first.
see: https://github.com/PyCQA/isort/issues/1688
"""
assert (
isort.code(
"""
from xxx import (
g,
hi,
def,
abcd,
)
""",
profile="black",
reverse_sort=True,
length_sort=True,
line_length=20,
)
== """
from xxx import (
abcd,
def,
hi,
g,
)
"""
)

0 comments on commit 359c105

Please sign in to comment.