diff --git a/CHANGELOG.md b/CHANGELOG.md index 72bebd8c1..2de5058ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Find out more about isort's release policy [here](https://pycqa.github.io/isort/ - 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. + - Implemented #1504: Ability to push star imports to the top to avoid overriding explicitly defined imports. - Documented #1685: Skip doesn't support plain directory names, but skip_glob does. ### 5.7.0 December 30th 2020 diff --git a/isort/main.py b/isort/main.py index d16626f5f..b6954d249 100644 --- a/isort/main.py +++ b/isort/main.py @@ -666,6 +666,12 @@ def _build_arg_parser() -> argparse.ArgumentParser: dest="ext_format", help="Tells isort to format the given files according to an extensions formatting rules.", ) + output_group.add_argument( + "--star-first", + help="Forces star imports above others to avoid overriding directly imported variables.", + dest="star_first", + action="store_true", + ) section_group.add_argument( "--sd", diff --git a/isort/output.py b/isort/output.py index ee7406ca8..01abbe27d 100644 --- a/isort/output.py +++ b/isort/output.py @@ -65,6 +65,16 @@ def sorted_imports( reverse=config.reverse_sort, ) + if config.star_first: + star_modules = [] + other_modules = [] + for module in from_modules: + if "*" in parsed.imports[section]["from"][module]: + star_modules.append(module) + else: + other_modules.append(module) + from_modules = star_modules + other_modules + straight_imports = _with_straight_imports( parsed, config, straight_modules, section, remove_imports, import_type ) diff --git a/isort/settings.py b/isort/settings.py index dc3754ef8..c2cd9624a 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -211,6 +211,7 @@ class _Config: sort_relative_in_force_sorted_sections: bool = False overwrite_in_place: bool = False reverse_sort: bool = False + star_first: bool = False def __post_init__(self): py_version = self.py_version diff --git a/tests/unit/test_ticketed_features.py b/tests/unit/test_ticketed_features.py index 6bed59a66..a0e5e1640 100644 --- a/tests/unit/test_ticketed_features.py +++ b/tests/unit/test_ticketed_features.py @@ -1059,3 +1059,26 @@ def test_isort_allows_reversing_sort_order_issue_1645(): ) """ ) + + +def test_isort_can_push_star_imports_above_others_issue_1504(): + """isort should provide a way to push star imports above other imports to avoid explicit + imports from being overwritten. + see: https://github.com/PyCQA/isort/issues/1504 + """ + assert ( + ( + isort.code( + """ +from ._bar import Any, All, Not +from ._foo import a, * +""", + star_first=True, + ) + ) + == """ +from ._foo import * +from ._foo import a +from ._bar import All, Any, Not +""" + )