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

add format-errors and format-success options #1750

Merged
merged 1 commit into from Jun 18, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/configuration/options.md
Expand Up @@ -1312,6 +1312,34 @@ Tells isort to format the given files according to an extensions formatting rule

- --ext-format

## Format Errors

Define the format used to print errors.

**NOTE** Variables are `error` and `message`.
The `error` variable prints `ERROR` with color depending on the --color option.

**Type:** String
**Default:** `{error}: {message}`
**Python & Config File Name:** format_errors
**CLI Flags:**

- --format-errors

## Format Success

Define the format used to print successes.

**NOTE** Variables are `success` and `message`.
The `success` variable prints `SUCCESS` with color depending on the --color option.

**Type:** String
**Default:** `{success}: {message}`
**Python & Config File Name:** format_success
**CLI Flags:**

- --format-success

## Deprecated Flags

==SUPPRESS==
Expand Down
4 changes: 3 additions & 1 deletion isort/api.py
Expand Up @@ -242,7 +242,9 @@ def check_stream(
file_path=file_path,
disregard_skip=disregard_skip,
)
printer = create_terminal_printer(color=config.color_output)
printer = create_terminal_printer(
color=config.color_output, error=config.format_error, success=config.format_success
)
if not changed:
if config.verbose and not config.only_modified:
printer.success(f"{file_path or ''} Everything Looks Good!")
Expand Down
20 changes: 13 additions & 7 deletions isort/format.py
Expand Up @@ -95,22 +95,24 @@ class BasicPrinter:
ERROR = "ERROR"
SUCCESS = "SUCCESS"

def __init__(self, output: Optional[TextIO] = None):
def __init__(self, error: str, success: str, output: Optional[TextIO] = None):
self.output = output or sys.stdout
self.success_message = success
self.error_message = error

def success(self, message: str) -> None:
print(f"{self.SUCCESS}: {message}", file=self.output)
print(self.success_message.format(success=self.SUCCESS, message=message), file=self.output)

def error(self, message: str) -> None:
print(f"{self.ERROR}: {message}", file=sys.stderr)
print(self.error_message.format(error=self.ERROR, message=message), file=sys.stderr)

def diff_line(self, line: str) -> None:
self.output.write(line)


class ColoramaPrinter(BasicPrinter):
def __init__(self, output: Optional[TextIO] = None):
super().__init__(output=output)
def __init__(self, error: str, success: str, output: Optional[TextIO]):
super().__init__(error, success, output=output)

# Note: this constants are instance variables instead ofs class variables
# because they refer to colorama which might not be installed.
Expand All @@ -134,7 +136,9 @@ def diff_line(self, line: str) -> None:
self.output.write(self.style_text(line, style))


def create_terminal_printer(color: bool, output: Optional[TextIO] = None):
def create_terminal_printer(
color: bool, output: Optional[TextIO] = None, error: str = "", success: str = ""
):
if color and colorama_unavailable:
no_colorama_message = (
"\n"
Expand All @@ -147,4 +151,6 @@ def create_terminal_printer(color: bool, output: Optional[TextIO] = None):
print(no_colorama_message, file=sys.stderr)
sys.exit(1)

return ColoramaPrinter(output) if color else BasicPrinter(output)
return (
ColoramaPrinter(error, success, output) if color else BasicPrinter(error, success, output)
)
26 changes: 22 additions & 4 deletions isort/main.py
Expand Up @@ -127,7 +127,9 @@ def _print_hard_fail(
"This should NEVER happen.\n"
"If encountered, please open an issue: https://github.com/PyCQA/isort/issues/new"
)
printer = create_terminal_printer(color=config.color_output)
printer = create_terminal_printer(
color=config.color_output, error=config.format_error, success=config.format_success
)
printer.error(message)


Expand Down Expand Up @@ -297,6 +299,16 @@ def _build_arg_parser() -> argparse.ArgumentParser:
action="store_true",
help="Tells isort to apply changes interactively.",
)
general_group.add_argument(
"--format-error",
dest="format_error",
help="Override the format used to print errors.",
)
general_group.add_argument(
"--format-success",
dest="format_success",
help="Override the format used to print success.",
)

target_group.add_argument(
"files", nargs="*", help="One or more Python source files that need their imports sorted."
Expand Down Expand Up @@ -1094,13 +1106,17 @@ def main(argv: Optional[Sequence[str]] = None, stdin: Optional[TextIOWrapper] =
raise_on_skip=False,
)
elif "/" in file_names and not allow_root:
printer = create_terminal_printer(color=config.color_output)
printer = create_terminal_printer(
color=config.color_output, error=config.format_error, success=config.format_success
)
printer.error("it is dangerous to operate recursively on '/'")
printer.error("use --allow-root to override this failsafe")
sys.exit(1)
else:
if stream_filename:
printer = create_terminal_printer(color=config.color_output)
printer = create_terminal_printer(
color=config.color_output, error=config.format_error, success=config.format_success
)
printer.error("Filename override is intended only for stream (-) sorting.")
sys.exit(1)
skipped: List[str] = []
Expand Down Expand Up @@ -1222,7 +1238,9 @@ def main(argv: Optional[Sequence[str]] = None, stdin: Optional[TextIOWrapper] =
sys.exit(1)

if no_valid_encodings:
printer = create_terminal_printer(color=config.color_output)
printer = create_terminal_printer(
color=config.color_output, error=config.format_error, success=config.format_success
)
printer.error("No valid encodings.")
sys.exit(1)

Expand Down
2 changes: 2 additions & 0 deletions isort/settings.py
Expand Up @@ -217,6 +217,8 @@ class _Config:
star_first: bool = False
import_dependencies = Dict[str, str]
git_ignore: Dict[Path, Set[Path]] = field(default_factory=dict)
format_error: str = "{error}: {message}"
format_success: str = "{success}: {message}"

def __post_init__(self):
py_version = self.py_version
Expand Down
18 changes: 15 additions & 3 deletions tests/unit/test_format.py
Expand Up @@ -21,14 +21,26 @@ def test_ask_whether_to_apply_changes_to_file():


def test_basic_printer(capsys):
printer = isort.format.create_terminal_printer(color=False)
printer = isort.format.create_terminal_printer(
color=False, success="{success}: {message}", error="{error}: {message}"
)
printer.success("All good!")
out, _ = capsys.readouterr()
assert out == "SUCCESS: All good!\n"
printer.error("Some error")
_, err = capsys.readouterr()
assert err == "ERROR: Some error\n"

printer = isort.format.create_terminal_printer(
color=False, success="success: {message}: {success}", error="error: {message}: {error}"
)
printer.success("All good!")
out, _ = capsys.readouterr()
assert out == "success: All good!: SUCCESS\n"
printer.error("Some error")
_, err = capsys.readouterr()
assert err == "error: Some error: ERROR\n"


def test_basic_printer_diff(capsys):
printer = isort.format.create_terminal_printer(color=False)
Expand All @@ -40,7 +52,7 @@ def test_basic_printer_diff(capsys):


def test_colored_printer_success(capsys):
printer = isort.format.create_terminal_printer(color=True)
printer = isort.format.create_terminal_printer(color=True, success="{success}: {message}")
printer.success("All good!")
out, _ = capsys.readouterr()
assert "SUCCESS" in out
Expand All @@ -49,7 +61,7 @@ def test_colored_printer_success(capsys):


def test_colored_printer_error(capsys):
printer = isort.format.create_terminal_printer(color=True)
printer = isort.format.create_terminal_printer(color=True, error="{error}: {message}")
printer.error("Some error")
_, err = capsys.readouterr()
assert "ERROR" in err
Expand Down