Mini Shell
"""Defines all wrap modes that can be used when outputting formatted imports"""
import enum
from inspect import signature
from typing import Any, Callable, Dict, List
import isort.comments
_wrap_modes: Dict[str, Callable[..., str]] = {}
def from_string(value: str) -> "WrapModes":
return getattr(WrapModes, str(value), None) or WrapModes(int(value))
def formatter_from_string(name: str) -> Callable[..., str]:
return _wrap_modes.get(name.upper(), grid)
def _wrap_mode_interface(
statement: str,
imports: List[str],
white_space: str,
indent: str,
line_length: int,
comments: List[str],
line_separator: str,
comment_prefix: str,
include_trailing_comma: bool,
remove_comments: bool,
) -> str:
"""Defines the common interface used by all wrap mode functions"""
return ""
def _wrap_mode(function: Callable[..., str]) -> Callable[..., str]:
"""Registers an individual wrap mode. Function name and order are significant and used for
creating enum.
"""
_wrap_modes[function.__name__.upper()] = function
function.__signature__ = signature(_wrap_mode_interface) # type: ignore
function.__annotations__ = _wrap_mode_interface.__annotations__
return function
@_wrap_mode
def grid(**interface: Any) -> str:
if not interface["imports"]:
return ""
interface["statement"] += "(" + interface["imports"].pop(0)
while interface["imports"]:
next_import = interface["imports"].pop(0)
next_statement = isort.comments.add_to_line(
interface["comments"],
interface["statement"] + ", " + next_import,
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
if (
len(next_statement.split(interface["line_separator"])[-1]) + 1
> interface["line_length"]
):
lines = [f"{interface['white_space']}{next_import.split(' ')[0]}"]
for part in next_import.split(" ")[1:]:
new_line = f"{lines[-1]} {part}"
if len(new_line) + 1 > interface["line_length"]:
lines.append(f"{interface['white_space']}{part}")
else:
lines[-1] = new_line
next_import = interface["line_separator"].join(lines)
interface["statement"] = (
isort.comments.add_to_line(
interface["comments"],
f"{interface['statement']},",
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ f"{interface['line_separator']}{next_import}"
)
interface["comments"] = []
else:
interface["statement"] += ", " + next_import
return f"{interface['statement']}{',' if interface['include_trailing_comma'] else ''})"
@_wrap_mode
def vertical(**interface: Any) -> str:
if not interface["imports"]:
return ""
first_import = (
isort.comments.add_to_line(
interface["comments"],
interface["imports"].pop(0) + ",",
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ interface["line_separator"]
+ interface["white_space"]
)
_imports = ("," + interface["line_separator"] + interface["white_space"]).join(
interface["imports"]
)
_comma_maybe = "," if interface["include_trailing_comma"] else ""
return f"{interface['statement']}({first_import}{_imports}{_comma_maybe})"
def _hanging_indent_end_line(line: str) -> str:
if not line.endswith(" "):
line += " "
return line + "\\"
@_wrap_mode
def hanging_indent(**interface: Any) -> str:
if not interface["imports"]:
return ""
line_length_limit = interface["line_length"] - 3
next_import = interface["imports"].pop(0)
next_statement = interface["statement"] + next_import
# Check for first import
if len(next_statement) > line_length_limit:
next_statement = (
_hanging_indent_end_line(interface["statement"])
+ interface["line_separator"]
+ interface["indent"]
+ next_import
)
interface["statement"] = next_statement
while interface["imports"]:
next_import = interface["imports"].pop(0)
next_statement = interface["statement"] + ", " + next_import
if len(next_statement.split(interface["line_separator"])[-1]) > line_length_limit:
next_statement = (
_hanging_indent_end_line(interface["statement"] + ",")
+ f"{interface['line_separator']}{interface['indent']}{next_import}"
)
interface["statement"] = next_statement
interface[
"statement"
] = f"{interface['statement']}{',' if interface['include_trailing_comma'] else ''}"
if interface["comments"]:
statement_with_comments = isort.comments.add_to_line(
interface["comments"],
interface["statement"],
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
if len(statement_with_comments.split(interface["line_separator"])[-1]) <= (
line_length_limit + 2
):
return statement_with_comments
return (
_hanging_indent_end_line(interface["statement"])
+ str(interface["line_separator"])
+ isort.comments.add_to_line(
interface["comments"],
interface["indent"],
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"].lstrip(),
)
)
return str(interface["statement"])
@_wrap_mode
def vertical_hanging_indent(**interface: Any) -> str:
_line_with_comments = isort.comments.add_to_line(
interface["comments"],
"",
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
_imports = ("," + interface["line_separator"] + interface["indent"]).join(interface["imports"])
_comma_maybe = "," if interface["include_trailing_comma"] else ""
return (
f"{interface['statement']}({_line_with_comments}{interface['line_separator']}"
f"{interface['indent']}{_imports}{_comma_maybe}{interface['line_separator']})"
)
def _vertical_grid_common(need_trailing_char: bool, **interface: Any) -> str:
if not interface["imports"]:
return ""
interface["statement"] += (
isort.comments.add_to_line(
interface["comments"],
"(",
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ interface["line_separator"]
+ interface["indent"]
+ interface["imports"].pop(0)
)
while interface["imports"]:
next_import = interface["imports"].pop(0)
next_statement = f"{interface['statement']}, {next_import}"
current_line_length = len(next_statement.split(interface["line_separator"])[-1])
if interface["imports"] or interface["include_trailing_comma"]:
# We need to account for a comma after this import.
current_line_length += 1
if not interface["imports"] and need_trailing_char:
# We need to account for a closing ) we're going to add.
current_line_length += 1
if current_line_length > interface["line_length"]:
next_statement = (
f"{interface['statement']},{interface['line_separator']}"
f"{interface['indent']}{next_import}"
)
interface["statement"] = next_statement
if interface["include_trailing_comma"]:
interface["statement"] += ","
return str(interface["statement"])
@_wrap_mode
def vertical_grid(**interface: Any) -> str:
return _vertical_grid_common(need_trailing_char=True, **interface) + ")"
@_wrap_mode
def vertical_grid_grouped(**interface: Any) -> str:
return (
_vertical_grid_common(need_trailing_char=False, **interface)
+ str(interface["line_separator"])
+ ")"
)
@_wrap_mode
def vertical_grid_grouped_no_comma(**interface: Any) -> str:
# This is a deprecated alias for vertical_grid_grouped above. This function
# needs to exist for backwards compatibility but should never get called.
raise NotImplementedError
@_wrap_mode
def noqa(**interface: Any) -> str:
_imports = ", ".join(interface["imports"])
retval = f"{interface['statement']}{_imports}"
comment_str = " ".join(interface["comments"])
if interface["comments"]:
if (
len(retval) + len(interface["comment_prefix"]) + 1 + len(comment_str)
<= interface["line_length"]
):
return f"{retval}{interface['comment_prefix']} {comment_str}"
if "NOQA" in interface["comments"]:
return f"{retval}{interface['comment_prefix']} {comment_str}"
return f"{retval}{interface['comment_prefix']} NOQA {comment_str}"
if len(retval) <= interface["line_length"]:
return retval
return f"{retval}{interface['comment_prefix']} NOQA"
@_wrap_mode
def vertical_hanging_indent_bracket(**interface: Any) -> str:
if not interface["imports"]:
return ""
statement = vertical_hanging_indent(**interface)
return f'{statement[:-1]}{interface["indent"]})'
@_wrap_mode
def vertical_prefix_from_module_import(**interface: Any) -> str:
if not interface["imports"]:
return ""
prefix_statement = interface["statement"]
output_statement = prefix_statement + interface["imports"].pop(0)
comments = interface["comments"]
statement = output_statement
statement_with_comments = ""
for next_import in interface["imports"]:
statement = statement + ", " + next_import
statement_with_comments = isort.comments.add_to_line(
comments,
statement,
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
if (
len(statement_with_comments.split(interface["line_separator"])[-1]) + 1
> interface["line_length"]
):
statement = (
isort.comments.add_to_line(
comments,
output_statement,
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ f"{interface['line_separator']}{prefix_statement}{next_import}"
)
comments = []
output_statement = statement
if comments and statement_with_comments:
output_statement = statement_with_comments
return str(output_statement)
@_wrap_mode
def hanging_indent_with_parentheses(**interface: Any) -> str:
if not interface["imports"]:
return ""
line_length_limit = interface["line_length"] - 1
interface["statement"] += "("
next_import = interface["imports"].pop(0)
next_statement = interface["statement"] + next_import
# Check for first import
if len(next_statement) > line_length_limit:
next_statement = (
isort.comments.add_to_line(
interface["comments"],
interface["statement"],
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ f"{interface['line_separator']}{interface['indent']}{next_import}"
)
interface["comments"] = []
interface["statement"] = next_statement
while interface["imports"]:
next_import = interface["imports"].pop(0)
if (
not interface["line_separator"] in interface["statement"]
and "#" in interface["statement"]
): # pragma: no cover # TODO: fix, this is because of test run inconsistency.
line, comments = interface["statement"].split("#", 1)
next_statement = (
f"{line.rstrip()}, {next_import}{interface['comment_prefix']}{comments}"
)
else:
next_statement = isort.comments.add_to_line(
interface["comments"],
interface["statement"] + ", " + next_import,
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
current_line = next_statement.split(interface["line_separator"])[-1]
if len(current_line) > line_length_limit:
next_statement = (
isort.comments.add_to_line(
interface["comments"],
interface["statement"] + ",",
removed=interface["remove_comments"],
comment_prefix=interface["comment_prefix"],
)
+ f"{interface['line_separator']}{interface['indent']}{next_import}"
)
interface["comments"] = []
interface["statement"] = next_statement
return f"{interface['statement']}{',' if interface['include_trailing_comma'] else ''})"
@_wrap_mode
def backslash_grid(**interface: Any) -> str:
interface["indent"] = interface["white_space"][:-1]
return hanging_indent(**interface)
WrapModes = enum.Enum( # type: ignore
"WrapModes", {wrap_mode: index for index, wrap_mode in enumerate(_wrap_modes.keys())}
)
Zerion Mini Shell 1.0