123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- import copy
- import re
- from typing import List, Optional, Sequence
- from .settings import DEFAULT_CONFIG, Config
- from .wrap_modes import WrapModes as Modes
- from .wrap_modes import formatter_from_string
- def import_statement(
- import_start: str,
- from_imports: List[str],
- comments: Sequence[str] = (),
- line_separator: str = "\n",
- config: Config = DEFAULT_CONFIG,
- multi_line_output: Optional[Modes] = None,
- ) -> str:
- """Returns a multi-line wrapped form of the provided from import statement."""
- formatter = formatter_from_string((multi_line_output or config.multi_line_output).name)
- dynamic_indent = " " * (len(import_start) + 1)
- indent = config.indent
- line_length = config.wrap_length or config.line_length
- statement = formatter(
- statement=import_start,
- imports=copy.copy(from_imports),
- white_space=dynamic_indent,
- indent=indent,
- line_length=line_length,
- comments=comments,
- line_separator=line_separator,
- comment_prefix=config.comment_prefix,
- include_trailing_comma=config.include_trailing_comma,
- remove_comments=config.ignore_comments,
- )
- if config.balanced_wrapping:
- lines = statement.split(line_separator)
- line_count = len(lines)
- if len(lines) > 1:
- minimum_length = min(len(line) for line in lines[:-1])
- else:
- minimum_length = 0
- new_import_statement = statement
- while len(lines[-1]) < minimum_length and len(lines) == line_count and line_length > 10:
- statement = new_import_statement
- line_length -= 1
- new_import_statement = formatter(
- statement=import_start,
- imports=copy.copy(from_imports),
- white_space=dynamic_indent,
- indent=indent,
- line_length=line_length,
- comments=comments,
- line_separator=line_separator,
- comment_prefix=config.comment_prefix,
- include_trailing_comma=config.include_trailing_comma,
- remove_comments=config.ignore_comments,
- )
- lines = new_import_statement.split(line_separator)
- if statement.count(line_separator) == 0:
- return _wrap_line(statement, line_separator, config)
- return statement
- def line(content: str, line_separator: str, config: Config = DEFAULT_CONFIG) -> str:
- """Returns a line wrapped to the specified line-length, if possible."""
- wrap_mode = config.multi_line_output
- if len(content) > config.line_length and wrap_mode != Modes.NOQA: # type: ignore
- line_without_comment = content
- comment = None
- if "#" in content:
- line_without_comment, comment = content.split("#", 1)
- for splitter in ("import ", ".", "as "):
- exp = r"\b" + re.escape(splitter) + r"\b"
- if re.search(exp, line_without_comment) and not line_without_comment.strip().startswith(
- splitter
- ):
- line_parts = re.split(exp, line_without_comment)
- if comment and not (config.use_parentheses and "noqa" in comment):
- _comma_maybe = (
- ","
- if (
- config.include_trailing_comma
- and config.use_parentheses
- and not line_without_comment.rstrip().endswith(",")
- )
- else ""
- )
- line_parts[
- -1
- ] = f"{line_parts[-1].strip()}{_comma_maybe}{config.comment_prefix}{comment}"
- next_line = []
- while (len(content) + 2) > (
- config.wrap_length or config.line_length
- ) and line_parts:
- next_line.append(line_parts.pop())
- content = splitter.join(line_parts)
- if not content:
- content = next_line.pop()
- cont_line = _wrap_line(
- config.indent + splitter.join(next_line).lstrip(),
- line_separator,
- config,
- )
- if config.use_parentheses:
- if splitter == "as ":
- output = f"{content}{splitter}{cont_line.lstrip()}"
- else:
- _comma = "," if config.include_trailing_comma and not comment else ""
- if wrap_mode in (
- Modes.VERTICAL_HANGING_INDENT, # type: ignore
- Modes.VERTICAL_GRID_GROUPED, # type: ignore
- ):
- _separator = line_separator
- else:
- _separator = ""
- _comment = ""
- if comment and "noqa" in comment:
- _comment = f"{config.comment_prefix}{comment}"
- cont_line = cont_line.rstrip()
- _comma = "," if config.include_trailing_comma else ""
- output = (
- f"{content}{splitter}({_comment}"
- f"{line_separator}{cont_line}{_comma}{_separator})"
- )
- lines = output.split(line_separator)
- if config.comment_prefix in lines[-1] and lines[-1].endswith(")"):
- content, comment = lines[-1].split(config.comment_prefix, 1)
- lines[-1] = content + ")" + config.comment_prefix + comment[:-1]
- return line_separator.join(lines)
- return f"{content}{splitter}\\{line_separator}{cont_line}"
- elif len(content) > config.line_length and wrap_mode == Modes.NOQA and "# NOQA" not in content: # type: ignore
- return f"{content}{config.comment_prefix} NOQA"
- return content
- _wrap_line = line
|