From a3e8d4d9ea007679eabfd20929550bffa6fbd481 Mon Sep 17 00:00:00 2001 From: Timothy Crosley Date: Sat, 4 Jan 2020 23:11:26 -0800 Subject: Initial work toward cimport support --- isort/api.py | 41 ++++++++++++++++++++++++++++++++++++----- isort/parse.py | 24 ++++++++++++++---------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/isort/api.py b/isort/api.py index 0aae7711..b7126999 100644 --- a/isort/api.py +++ b/isort/api.py @@ -18,6 +18,9 @@ from .io import File from .settings import DEFAULT_CONFIG, FILE_SKIP_COMMENTS, Config IMPORT_START_IDENTIFIERS = ("from ", "from.import", "import ", "import*") + +CIMPORT_IDENTIFIERS = ("cimport ", "cimport*", "from.cimport") +IMPORT_START_IDENTIFIERS = ("from ", "from.import", "import ", "import*") + CIMPORT_IDENTIFIERS COMMENT_INDICATORS = ('"""', "'''", "'", '"', "#") @@ -149,6 +152,7 @@ def sort_imports( line_separator: str = config.line_ending add_imports: List[str] = [format_natural(addition) for addition in config.add_imports] import_section: str = "" + next_import_section: str = "" in_quote: str = "" first_comment_index_start: int = -1 first_comment_index_end: int = -1 @@ -158,6 +162,7 @@ def sort_imports( section_comments = [f"# {heading}" for heading in config.import_headings.values()] indent: str = "" isort_off: bool = False + cimports: bool = False for index, line in enumerate(chain(input_stream, (None,))): if line is None: @@ -226,7 +231,7 @@ def sort_imports( contains_imports = True indent = line[: -len(line.lstrip())] - import_section += line + import_statement = line while stripped_line.endswith("\\") or ( "(" in stripped_line and ")" not in stripped_line ): @@ -234,12 +239,32 @@ def sort_imports( while stripped_line and stripped_line.endswith("\\"): line = input_stream.readline() stripped_line = line.strip().split("#")[0] - import_section += line + import_statement += line else: while ")" not in stripped_line: line = input_stream.readline() stripped_line = line.strip().split("#")[0] - import_section += line + 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 + ): + cimport_statement = True + + if cimport_statement != cimports: + if import_section: + next_import_section = import_statement + import_statement = "" + not_imports = True + line = "" + else: + cimports = cimport_statement + + import_section + import_statement else: not_imports = True @@ -277,7 +302,10 @@ def sort_imports( line.lstrip() for line in import_section.split(line_separator) ) sorted_import_section = output.sorted_imports( - parse.file_contents(import_section, config=config), config, extension + parse.file_contents(import_section, config=config), + config, + extension, + import_type="cimport" if cimports else "import", ) if indent: sorted_import_section = ( @@ -291,7 +319,10 @@ def sort_imports( indent = "" contains_imports = False - import_section = "" + if next_import_section: + cimports = not cimports + import_section = next_import_section + next_import_section = "" else: output_stream.write(line) not_imports = False diff --git a/isort/parse.py b/isort/parse.py index 6089c08b..3bfa3b0f 100644 --- a/isort/parse.py +++ b/isort/parse.py @@ -11,8 +11,6 @@ from isort.settings import DEFAULT_CONFIG, Config from .comments import parse as parse_comments from .finders import FindersManager -IMPORT_START_IDENTIFIERS = ("from ", "from.import", "import ", "import*") - if TYPE_CHECKING: from mypy_extensions import TypedDict @@ -46,8 +44,10 @@ def _normalize_line(raw_line: str) -> Tuple[str, str]: Returns (normalized_line: str, raw_line: str) """ line = raw_line.replace("from.import ", "from . import ") + line = raw_line.replace("from.cimport ", "from . cimport ") line = line.replace("import*", "import *") line = line.replace(" .import ", " . import ") + line = line.replace(" .cimport ", " . cimport ") line = line.replace("\t", " ") return (line, raw_line) @@ -56,7 +56,7 @@ def import_type(line: str) -> Optional[str]: """If the current line is an import line it will return its type (from or straight)""" if "isort:skip" in line or "isort: skip" in line or "NOQA" in line: return None - elif line.startswith("import "): + elif line.startswith(("import ", "cimport ")): return "straight" elif line.startswith("from "): return "from" @@ -68,7 +68,7 @@ def _strip_syntax(import_string: str) -> str: for remove_syntax in ["\\", "(", ")", ","]: import_string = import_string.replace(remove_syntax, " ") import_list = import_string.split() - for key in ("from", "import"): + for key in ("from", "import", "cimport"): if key in import_list: import_list.remove(key) import_string = " ".join(import_list) @@ -108,7 +108,7 @@ def skip_line( if ";" in line: for part in (part.strip() for part in line.split(";")): - if part and not part.startswith("from ") and not part.startswith("import "): + if part and not part.startswith("from ") and not part.startswith(("import ", "cimport ")): skip_line = True return (bool(skip_line or in_quote), in_quote) @@ -267,18 +267,22 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte and new_comment ): nested_comments[stripped_line] = comments[-1] - if import_string.strip().endswith(" import") or line.strip().startswith( - "import " - ): + if import_string.strip().endswith((" import", " cimport")) or line.strip().startswith(("import ", "cimport ")): import_string += line_separator + line else: import_string = import_string.rstrip().rstrip("\\") + " " + line.lstrip() if type_of_import == "from": + cimport: bool import_string = import_string.replace("import(", "import (") - parts = import_string.split(" import ") + if " cimport " in import_string: + parts = import_string.split(" cimport ") + cimport = True + else: + parts = import_string.split(" import ") + cimport = False from_import = parts[0].split(" ") - import_string = " import ".join( + import_string = " cimport " if cimport else " import ".join( [from_import[0] + " " + "".join(from_import[1:])] + parts[1:] ) -- cgit v1.2.1