From d4907b936e03a313c2b0305f63fe57a6c333cb52 Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Tue, 16 Mar 2021 21:03:38 -0700 Subject: [PATCH 1/4] Add config option for reversing sort order --- isort/main.py | 6 ++++++ isort/settings.py | 1 + 2 files changed, 7 insertions(+) diff --git a/isort/main.py b/isort/main.py index 5ed22cc26..d16626f5f 100644 --- a/isort/main.py +++ b/isort/main.py @@ -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", diff --git a/isort/settings.py b/isort/settings.py index a62c27bf6..dc3754ef8 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -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 From 080501975cb6cf200d4fff6ae17e08eb82c8f65f Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Tue, 16 Mar 2021 21:04:38 -0700 Subject: [PATCH 2/4] Add to changelog Implemented #1645: Ability to reverse the import sorting order. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53271c104..72bebd8c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From 7802b4f88e92a4a9534b9044527cd1f37c965755 Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Wed, 17 Mar 2021 00:31:46 -0700 Subject: [PATCH 3/4] Add test case for issue #1645: Allowing sort order to be reversed --- tests/unit/test_ticketed_features.py | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/unit/test_ticketed_features.py b/tests/unit/test_ticketed_features.py index dddb31bc2..6bed59a66 100644 --- a/tests/unit/test_ticketed_features.py +++ b/tests/unit/test_ticketed_features.py @@ -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, +) +""" + ) From cb896cd47962034f681171d3eced45a82f0ddf0b Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Wed, 17 Mar 2021 00:32:36 -0700 Subject: [PATCH 4/4] Add support for reversing import sort --- isort/output.py | 6 +++++- isort/sorting.py | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/isort/output.py b/isort/output.py index 6b3401089..ee7406ca8 100644 --- a/isort/output.py +++ b/isort/output.py @@ -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( @@ -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 = [ diff --git a/isort/sorting.py b/isort/sorting.py index 2cfe60bf5..e8c355bab 100644 --- a/isort/sorting.py +++ b/isort/sorting.py @@ -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 @@ -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: