From 0383c3668d289db2d41a43165b564f75bb5e64ff Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Wed, 30 Dec 2020 16:26:36 -0800 Subject: [PATCH] Fix indented identification isort --- isort/identify.py | 30 +++++++++++----------- tests/unit/test_identify.py | 50 ++++++++++++++++++++++++++++++++++++- tests/unit/test_isort.py | 9 +++---- tests/unit/test_main.py | 2 +- 4 files changed, 70 insertions(+), 21 deletions(-) diff --git a/isort/identify.py b/isort/identify.py index 1f8185cbe..dbab7f6ae 100644 --- a/isort/identify.py +++ b/isort/identify.py @@ -47,17 +47,17 @@ def imports( in_quote = "" indexed_input = enumerate(input_stream) - for index, line in indexed_input: + for index, raw_line in indexed_input: (skipping_line, in_quote) = skip_line( - line, in_quote=in_quote, index=index, section_comments=config.section_comments + raw_line, in_quote=in_quote, index=index, section_comments=config.section_comments ) - if top_only and not in_quote and line.startswith(STATEMENT_DECLARATIONS): + if top_only and not in_quote and raw_line.startswith(STATEMENT_DECLARATIONS): break if skipping_line: continue - stripped_line = line.strip().split("#")[0] + stripped_line = raw_line.strip().split("#")[0] if stripped_line.startswith("raise") or stripped_line.startswith("yield"): if stripped_line == "yield": while not stripped_line or stripped_line == "yield": @@ -76,16 +76,16 @@ def imports( stripped_line = next_line.strip().split("#")[0] continue - line, *end_of_line_comment = line.split("#", 1) + line, *end_of_line_comment = raw_line.split("#", 1) statements = [line.strip() for line in line.split(";")] if end_of_line_comment: statements[-1] = f"{statements[-1]}#{end_of_line_comment[0]}" for statement in statements: line, _raw_line = _normalize_line(statement) - if line.lstrip().startswith(("import ", "cimport ")): + if line.startswith(("import ", "cimport ")): type_of_import = "straight" - elif line.lstrip().startswith("from "): + elif line.startswith("from "): type_of_import = "from" else: continue @@ -101,7 +101,7 @@ def imports( identified_import = partial( Import, index + 1, # line numbers use 1 based indexing - line.startswith(" ") or line.startswith("\n"), + raw_line.startswith((" ", "\t")), cimport=cimports, file_path=file_path, ) @@ -177,18 +177,20 @@ def imports( direct_imports.remove("as") just_imports[1:] = direct_imports if attribute == alias and config.remove_redundant_aliases: - pass + yield identified_import(top_level_module, attribute) else: yield identified_import(top_level_module, attribute, alias=alias) else: module = just_imports[as_index - 1] alias = just_imports[as_index + 1] - direct_imports.remove(alias) - direct_imports.remove("as") - just_imports[1:] = direct_imports - if not (module == alias and config.remove_redundant_aliases): - yield identified_import(module, alias) + just_imports.remove(alias) + just_imports.remove("as") + just_imports.remove(module) + if module == alias and config.remove_redundant_aliases: + yield identified_import(module) + else: + yield identified_import(module, alias=alias) if just_imports: if type_of_import == "from": diff --git a/tests/unit/test_identify.py b/tests/unit/test_identify.py index 8515d459e..64c9f28a9 100644 --- a/tests/unit/test_identify.py +++ b/tests/unit/test_identify.py @@ -1,7 +1,7 @@ from io import StringIO from typing import List -from isort import identify +from isort import Config, identify def imports_in_code(code: str, **kwargs) -> List[identify.Import]: @@ -198,3 +198,51 @@ def generator_function(): ) == 2 ) + + +def test_complex_examples(): + assert ( + len( + imports_in_code( + """ +import a, b, c; import n + +x = ( + 1, + 2, + 3 +) + +import x +from os \\ + import path +from os ( + import path +) +from os import ( \\""" + ) + ) + == 7 + ) + assert not imports_in_code("from os import \\") + + +def test_aliases(): + assert imports_in_code("import os as os")[0].alias == "os" + assert not imports_in_code( + "import os as os", + config=Config( + remove_redundant_aliases=True, + ), + )[0].alias + + assert imports_in_code("from os import path as path")[0].alias == "path" + assert not imports_in_code( + "from os import path as path", config=Config(remove_redundant_aliases=True) + )[0].alias + + +def test_indented(): + assert not imports_in_code("import os")[0].indented + assert imports_in_code(" import os")[0].indented + assert imports_in_code("\timport os")[0].indented diff --git a/tests/unit/test_isort.py b/tests/unit/test_isort.py index 9655d9f66..125bd0dfa 100644 --- a/tests/unit/test_isort.py +++ b/tests/unit/test_isort.py @@ -4946,13 +4946,12 @@ def test_find_imports_in_code() -> None: ":3 import second_straight", ":4 import first_from.first_from_function_1", ":4 import first_from.first_from_function_2", - ":5 import bad_name.good_name", - ":5 import bad_name", + ":5 import bad_name as good_name", ":6 import parent.some_bad_defs.bad_name_1 as ok_name_1", ":6 import parent.some_bad_defs.bad_name_2 as ok_name_2", - ":12 import needed_in_bla_2", - ":15 import needed_in_bla", - ":18 import needed_in_bla_bla", + ":12 indented import needed_in_bla_2", + ":15 indented import needed_in_bla", + ":18 indented import needed_in_bla_bla", ":22 import needed_in_end", ] diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 7291cb5fe..d1ae50214 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -995,7 +995,7 @@ def test_only_modified_flag(tmpdir, capsys): def test_identify_imports_main(tmpdir, capsys): - file_content = "import mod2\n import mod2\n" "a = 1\n" "import mod1\n" + file_content = "import mod2\nimport mod2\n" "a = 1\n" "import mod1\n" some_file = tmpdir.join("some_file.py") some_file.write(file_content) file_imports = f"{some_file}:1 import mod2\n{some_file}:4 import mod1\n"