From 3cac92021a9065f394e29e43688f76e0523e83d2 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 4 Dec 2021 22:25:01 +0000 Subject: [PATCH] Add 'sort-reexports' CLI option --- isort/core.py | 23 +++++++++++++++++++++-- isort/main.py | 6 ++++++ isort/settings.py | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/isort/core.py b/isort/core.py index c9ba7ac56..e9a2977b3 100644 --- a/isort/core.py +++ b/isort/core.py @@ -24,6 +24,11 @@ "# isort: unique-tuple", "# isort: assignments", ) +LITERAL_TYPE_MAPPING = { + "(": "tuple", + "[": "list", + "{": "dict", +} def process( @@ -73,6 +78,8 @@ def process( end_of_file: bool = False verbose_output: List[str] = [] lines_before: List[str] = [] + auto_reexporting: bool = False + line_index: int = 0 if config.float_to_top: new_input = "" @@ -145,7 +152,7 @@ def process( line_separator=line_separator, ignore_whitespace=config.ignore_whitespace, ) - output_stream.write(sorted_code) + line_index += output_stream.write(sorted_code) else: stripped_line = line.strip() if stripped_line and not line_separator: @@ -225,6 +232,13 @@ def process( code_sorting = stripped_line.split("isort: ")[1].strip() code_sorting_indent = line[: -len(line.lstrip())] not_imports = True + elif config.sort_reexports and stripped_line.startswith("__all__"): + code_sorting = LITERAL_TYPE_MAPPING[stripped_line.split(" = ")[1][0]] + code_sorting_indent = line[: -len(line.lstrip())] + not_imports = True + code_sorting_section += line + auto_reexporting = True + line_index -= len(line) - 1 elif code_sorting: if not stripped_line: sorted_code = textwrap.indent( @@ -242,11 +256,14 @@ def process( line_separator=line_separator, ignore_whitespace=config.ignore_whitespace, ) - output_stream.write(sorted_code) + if auto_reexporting: + output_stream.seek(line_index, 0) + line_index += output_stream.write(sorted_code) not_imports = True code_sorting = False code_sorting_section = "" code_sorting_indent = "" + auto_reexporting = False else: code_sorting_section += line line = "" @@ -333,6 +350,8 @@ def process( else: not_imports = True + line_index += len(line) + if not_imports: if not was_in_quote and config.lines_before_imports > -1: diff --git a/isort/main.py b/isort/main.py index 08301a1e4..40725a6a6 100644 --- a/isort/main.py +++ b/isort/main.py @@ -322,6 +322,12 @@ def _build_arg_parser() -> argparse.ArgumentParser: dest="format_success", help="Override the format used to print success.", ) + general_group.add_argument( + "--sort-reexports", + dest="sort_reexports", + action="store_true", + help="Automatically sort all re-exports (module level __all__ collections)", + ) target_group.add_argument( "files", nargs="*", help="One or more Python source files that need their imports sorted." diff --git a/isort/settings.py b/isort/settings.py index 681d7b46e..f13afade5 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -242,6 +242,7 @@ class _Config: format_error: str = "{error}: {message}" format_success: str = "{success}: {message}" sort_order: str = "natural" + sort_reexports: bool = False def __post_init__(self) -> None: py_version = self.py_version