Skip to content
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

Add a command-line flag to sort __all__ re-exports (#1862) #1863

Merged
merged 1 commit into from Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 21 additions & 2 deletions isort/core.py
Expand Up @@ -24,6 +24,11 @@
"# isort: unique-tuple",
"# isort: assignments",
)
LITERAL_TYPE_MAPPING = {
"(": "tuple",
"[": "list",
"{": "dict",
}


def process(
Expand Down Expand Up @@ -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 = ""
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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(
Expand All @@ -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 = ""
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions isort/main.py
Expand Up @@ -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."
Expand Down
1 change: 1 addition & 0 deletions isort/settings.py
Expand Up @@ -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
Expand Down