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

Issue/1688 #1692

Merged
merged 3 commits into from
Mar 16, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 37 additions & 30 deletions isort/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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

Expand Down
8 changes: 8 additions & 0 deletions isort/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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])
Expand All @@ -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])
Expand All @@ -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 (
Expand All @@ -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
Expand Down
21 changes: 21 additions & 0 deletions tests/unit/test_ticketed_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
)