diff --git a/docs/configuration/options.md b/docs/configuration/options.md index 440a6c887..e07deb222 100644 --- a/docs/configuration/options.md +++ b/docs/configuration/options.md @@ -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== diff --git a/isort/api.py b/isort/api.py index 642784f85..4d6f5c461 100644 --- a/isort/api.py +++ b/isort/api.py @@ -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!") diff --git a/isort/format.py b/isort/format.py index ba00f8651..1db549137 100644 --- a/isort/format.py +++ b/isort/format.py @@ -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. @@ -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" @@ -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) + ) diff --git a/isort/main.py b/isort/main.py index 6057ef388..f354d82d2 100644 --- a/isort/main.py +++ b/isort/main.py @@ -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) @@ -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." @@ -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] = [] @@ -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) diff --git a/isort/settings.py b/isort/settings.py index c52de99cc..37dd67a07 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -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 diff --git a/tests/unit/test_format.py b/tests/unit/test_format.py index f331578a8..527feaa0b 100644 --- a/tests/unit/test_format.py +++ b/tests/unit/test_format.py @@ -21,7 +21,9 @@ 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" @@ -29,6 +31,16 @@ def test_basic_printer(capsys): _, 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) @@ -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 @@ -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