From e7a5af5db5dc20f5c96cad8e695ff72594f69538 Mon Sep 17 00:00:00 2001 From: dzcode <9089037+dzcode@users.noreply.github.com> Date: Mon, 2 May 2022 17:03:46 -0600 Subject: [PATCH 1/2] Pass 'color' explicitly in error echoing --- src/click/exceptions.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/click/exceptions.py b/src/click/exceptions.py index 9e20b3eb5..74109b8ae 100644 --- a/src/click/exceptions.py +++ b/src/click/exceptions.py @@ -5,6 +5,7 @@ from ._compat import get_text_stderr from .utils import echo +from click.globals import resolve_color_default if t.TYPE_CHECKING: from .core import Context @@ -28,6 +29,9 @@ class ClickException(Exception): def __init__(self, message: str) -> None: super().__init__(message) + # The context will be removed by the time we print the message, so cache + # the color settings here to be used later on (in `show`) + self.show_color = resolve_color_default() self.message = message def format_message(self) -> str: @@ -40,7 +44,11 @@ def show(self, file: t.Optional[t.IO] = None) -> None: if file is None: file = get_text_stderr() - echo(_("Error: {message}").format(message=self.format_message()), file=file) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=self.show_color, + ) class UsageError(ClickException): From 512749d1653f2f2633ba8c5d03059f7348caa1fe Mon Sep 17 00:00:00 2001 From: dzcode <9089037+dzcode@users.noreply.github.com> Date: Mon, 2 May 2022 17:08:09 -0600 Subject: [PATCH 2/2] Add tests for color --- tests/test_testing.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_testing.py b/tests/test_testing.py index 9f294b3a1..678b28c9e 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -6,6 +6,7 @@ import click from click._compat import WIN +from click.exceptions import ClickException from click.testing import CliRunner @@ -201,6 +202,27 @@ def cli(): assert not result.exception +@pytest.mark.skipif(WIN, reason="Test does not make sense on Windows.") +def test_with_color_errors(): + class CLIError(ClickException): + def format_message(self) -> str: + return click.style(self.message, fg="red") + + @click.command() + def cli(): + raise CLIError("Red error") + + runner = CliRunner() + + result = runner.invoke(cli) + assert result.output == "Error: Red error\n" + assert result.exception + + result = runner.invoke(cli, color=True) + assert result.output == f"Error: {click.style('Red error', fg='red')}\n" + assert result.exception + + def test_with_color_but_pause_not_blocking(): @click.command() def cli():