diff --git a/isort/core.py b/isort/core.py index 10103854..472d914d 100644 --- a/isort/core.py +++ b/isort/core.py @@ -27,6 +27,8 @@ LITERAL_TYPE_MAPPING = {"(": "tuple", "[": "list", "{": "set"} +# Ignore DeepSource cyclomatic complexity check for this function. +# skipcq: PY-R1000 def process( input_stream: TextIO, output_stream: TextIO, @@ -75,7 +77,7 @@ def process( verbose_output: List[str] = [] lines_before: List[str] = [] is_reexport: bool = False - sort_section_pointer: int = 0 + reexport_rollback: int = 0 if config.float_to_top: new_input = "" @@ -134,7 +136,8 @@ def process( if code_sorting and code_sorting_section: if is_reexport: - output_stream.seek(sort_section_pointer, 0) + output_stream.seek(output_stream.tell() - reexport_rollback) + reexport_rollback = 0 sorted_code = textwrap.indent( isort.literal.assignment( code_sorting_section, @@ -150,7 +153,9 @@ def process( line_separator=line_separator, ignore_whitespace=config.ignore_whitespace, ) - sort_section_pointer += output_stream.write(sorted_code) + output_stream.write(sorted_code) + if is_reexport: + output_stream.truncate() else: stripped_line = line.strip() if stripped_line and not line_separator: @@ -236,8 +241,8 @@ def process( code_sorting_indent = line[: -len(line.lstrip())] not_imports = True code_sorting_section += line + reexport_rollback = len(line) is_reexport = True - sort_section_pointer -= len(line) elif code_sorting: if not stripped_line: sorted_code = textwrap.indent( @@ -256,8 +261,11 @@ def process( ignore_whitespace=config.ignore_whitespace, ) if is_reexport: - output_stream.seek(sort_section_pointer, 0) - sort_section_pointer += output_stream.write(sorted_code) + output_stream.seek(output_stream.tell() - reexport_rollback) + reexport_rollback = 0 + output_stream.write(sorted_code) + if is_reexport: + output_stream.truncate() not_imports = True code_sorting = False code_sorting_section = "" @@ -356,8 +364,6 @@ def process( else: not_imports = True - sort_section_pointer += len(line) - if not_imports: if not was_in_quote and config.lines_before_imports > -1: if line.strip() == "": diff --git a/tests/unit/test_isort.py b/tests/unit/test_isort.py index 7b6743c7..eff10f69 100644 --- a/tests/unit/test_isort.py +++ b/tests/unit/test_isort.py @@ -2,6 +2,7 @@ Should be ran using py.test by simply running py.test in the isort project directory """ + import os import os.path import subprocess @@ -5671,3 +5672,58 @@ def test_reexport_not_last_line() -> None: meme = "rickroll" """ assert isort.code(test_input, config=Config(sort_reexports=True)) == expd_output + + +def test_reexport_multiline_import() -> None: + test_input = """from m import ( + bar, + foo, +) +__all__ = [ + "foo", + "bar", +] +""" + expd_output = """from m import bar, foo + +__all__ = ['bar', 'foo'] +""" + assert isort.code(test_input, config=Config(sort_reexports=True)) == expd_output + + +def test_reexport_multiline_in_center() -> None: + test_input = """from m import ( + bar, + foo, +) +__all__ = [ + "foo", + "bar", +] + +test +""" + expd_output = """from m import bar, foo + +__all__ = ['bar', 'foo'] + +test +""" + assert isort.code(test_input, config=Config(sort_reexports=True)) == expd_output + + +def test_reexport_multiline_long_rollback() -> None: + test_input = """from m import foo, bar +__all__ = [ "foo", + "bar", +] + +test +""" + expd_output = """from m import bar, foo + +__all__ = ['bar', 'foo'] + +test +""" + assert isort.code(test_input, config=Config(sort_reexports=True)) == expd_output