From ec3ac4dc2f2b77937321015393fac09173711c00 Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Mon, 15 Mar 2021 22:40:49 -0700 Subject: [PATCH 1/3] Add entry to changelog for issue #1688 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0107444b..53271c104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Find out more about isort's release policy [here](https://pycqa.github.io/isort/ - Implemented #1668: Added a safeguard against accidental usage against /. - Implemented #1638 / #1644: Provide a flag `--overwrite-in-place` to ensure same file handle is used after sorting. - 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. - Documented #1685: Skip doesn't support plain directory names, but skip_glob does. ### 5.7.0 December 30th 2020 From 2bce0f2c197a6c7b70c7ae2a6c9c0cbded2a6600 Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Mon, 15 Mar 2021 23:04:37 -0700 Subject: [PATCH 2/3] Add test case to ensure incorrectly formatted from statements dont disapear --- tests/unit/test_ticketed_features.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/unit/test_ticketed_features.py b/tests/unit/test_ticketed_features.py index 130ef67c7..dddb31bc2 100644 --- a/tests/unit/test_ticketed_features.py +++ b/tests/unit/test_ticketed_features.py @@ -1008,3 +1008,24 @@ def function(): import numpy as np """ ) + + +def test_isort_auto_detects_and_ignores_invalid_from_imports_issue_1688(): + """isort should automatically detect and ignore incorrectly written from import statements + see: https://github.com/PyCQA/isort/issues/1688 + """ + assert ( + isort.code( + """ +from package1 import alright +from package2 imprt and_its_gone +from package3 import also_ok +""" + ) + == """ +from package1 import alright + +from package2 imprt and_its_gone +from package3 import also_ok +""" + ) From 9c18cbb630749925b71f9904e4581a8657c33d3a Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Mon, 15 Mar 2021 23:04:57 -0700 Subject: [PATCH 3/3] Fix issue #1688: from statements removed when invalid --- isort/core.py | 67 ++++++++++++++++++++++++++++---------------------- isort/parse.py | 8 ++++++ 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/isort/core.py b/isort/core.py index 598789984..d763ad469 100644 --- a/isort/core.py +++ b/isort/core.py @@ -246,9 +246,6 @@ def process( ): import_section += line elif stripped_line.startswith(IMPORT_START_IDENTIFIERS): - did_contain_imports = contains_imports - contains_imports = True - new_indent = line[: -len(line.lstrip())] import_statement = line stripped_line = line.strip().split("#")[0] @@ -266,37 +263,47 @@ def process( stripped_line = line.strip().split("#")[0] import_statement += line - cimport_statement: bool = False if ( - import_statement.lstrip().startswith(CIMPORT_IDENTIFIERS) - or " cimport " in import_statement - or " cimport*" in import_statement - or " cimport(" in import_statement - or ".cimport" in import_statement - ): - cimport_statement = True - - if cimport_statement != cimports or ( - new_indent != indent - and import_section - and (not did_contain_imports or len(new_indent) < len(indent)) + import_statement.lstrip().startswith("from") + and "import" not in import_statement ): - indent = new_indent - if import_section: - next_cimports = cimport_statement - next_import_section = import_statement - import_statement = "" - not_imports = True - line = "" - else: - cimports = cimport_statement + line = import_statement + not_imports = True else: - if new_indent != indent: - if import_section and did_contain_imports: - import_statement = indent + import_statement.lstrip() + did_contain_imports = contains_imports + contains_imports = True + + cimport_statement: bool = False + if ( + import_statement.lstrip().startswith(CIMPORT_IDENTIFIERS) + or " cimport " in import_statement + or " cimport*" in import_statement + or " cimport(" in import_statement + or ".cimport" in import_statement + ): + cimport_statement = True + + if cimport_statement != cimports or ( + new_indent != indent + and import_section + and (not did_contain_imports or len(new_indent) < len(indent)) + ): + indent = new_indent + if import_section: + next_cimports = cimport_statement + next_import_section = import_statement + import_statement = "" + not_imports = True + line = "" else: - indent = new_indent - import_section += import_statement + cimports = cimport_statement + else: + if new_indent != indent: + if import_section and did_contain_imports: + import_statement = indent + import_statement.lstrip() + else: + indent = new_indent + import_section += import_statement else: not_imports = True diff --git a/isort/parse.py b/isort/parse.py index 307015e74..714e39abd 100644 --- a/isort/parse.py +++ b/isort/parse.py @@ -260,6 +260,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte for statement in statements: line, raw_line = _normalize_line(statement) type_of_import = import_type(line, config) or "" + raw_lines = [raw_line] if not type_of_import: out_lines.append(raw_line) continue @@ -288,6 +289,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte ): nested_comments[stripped_line] = comments[-1] import_string += line_separator + line + raw_lines.append(line) else: while line.strip().endswith("\\"): line, new_comment = parse_comments(in_lines[index]) @@ -310,6 +312,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte ): nested_comments[stripped_line] = comments[-1] import_string += line_separator + line + raw_lines.append(line) while not line.split("#")[0].strip().endswith(")") and index < line_count: line, new_comment = parse_comments(in_lines[index]) @@ -325,6 +328,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte ): nested_comments[stripped_line] = comments[-1] import_string += line_separator + line + raw_lines.append(line) stripped_line = _strip_syntax(line).strip() if ( @@ -348,6 +352,10 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte .replace("\\", " ") .replace("\n", " ") ) + if "import " not in import_string: + out_lines.extend(raw_lines) + continue + if " cimport " in import_string: parts = import_string.split(" cimport ") cimports = True