diff --git a/src/syrupy/terminal.py b/src/syrupy/terminal.py index dec15327..f59d6963 100644 --- a/src/syrupy/terminal.py +++ b/src/syrupy/terminal.py @@ -13,6 +13,24 @@ def _is_color_disabled() -> bool: return any(map(get_env_value, DISABLE_COLOR_ENV_VARS)) +def _attr(color: Any) -> str: + if _is_color_disabled(): + return "" + return colored.attr(color) + + +def _fg(color: Any) -> str: + if _is_color_disabled(): + return "" + return colored.fg(color) + + +def _bg(color: Any) -> str: + if _is_color_disabled(): + return "" + return colored.bg(color) + + def _stylize(text: Union[str, int], *args: Any) -> str: if _is_color_disabled(): return str(text) @@ -20,23 +38,23 @@ def _stylize(text: Union[str, int], *args: Any) -> str: def reset(text: Union[str, int]) -> str: - return _stylize(text, colored.attr("reset")) + return _stylize(text, _attr("reset")) def red(text: Union[str, int]) -> str: - return _stylize(text, colored.fg("red")) + return _stylize(text, _fg("red")) def yellow(text: Union[str, int]) -> str: - return _stylize(text, colored.fg("yellow")) + return _stylize(text, _fg("yellow")) def green(text: Union[str, int]) -> str: - return _stylize(text, colored.fg("green")) + return _stylize(text, _fg("green")) def bold(text: Union[str, int]) -> str: - return _stylize(text, colored.attr("bold")) + return _stylize(text, _attr("bold")) def error_style(text: Union[str, int]) -> str: @@ -52,20 +70,20 @@ def success_style(text: Union[str, int]) -> str: def snapshot_style(text: Union[str, int]) -> str: - return _stylize(text, colored.bg(225) + colored.fg(90)) + return _stylize(text, _bg(225) + _fg(90)) def snapshot_diff_style(text: Union[str, int]) -> str: - return _stylize(text, colored.bg(90) + colored.fg(225)) + return _stylize(text, _bg(90) + _fg(225)) def received_style(text: Union[str, int]) -> str: - return _stylize(text, colored.bg(195) + colored.fg(23)) + return _stylize(text, _bg(195) + _fg(23)) def received_diff_style(text: Union[str, int]) -> str: - return _stylize(text, colored.bg(23) + colored.fg(195)) + return _stylize(text, _bg(23) + _fg(195)) def context_style(text: Union[str, int]) -> str: - return _stylize(text, colored.attr("dim")) + return _stylize(text, _attr("dim")) diff --git a/tests/syrupy/test_terminal.py b/tests/syrupy/test_terminal.py new file mode 100644 index 00000000..cf9df9fb --- /dev/null +++ b/tests/syrupy/test_terminal.py @@ -0,0 +1,58 @@ +from unittest.mock import ( + NonCallableMock, + patch, +) + +import pytest + +from syrupy.constants import DISABLE_COLOR_ENV_VAR +from syrupy.terminal import ( + bold, + context_style, + error_style, + green, + received_diff_style, + received_style, + red, + reset, + snapshot_diff_style, + snapshot_style, + success_style, + warning_style, + yellow, +) + + +def test_colors_off_does_not_call_colored(): + """ + Test that disabling colors prevents instantiating colored object. + Enables workarounds for when instantiating the colored object causes crashes, + see issue #633 + """ + + with patch( + "syrupy.terminal.colored.colored.__init__", new_callable=NonCallableMock + ): + with patch.dict("os.environ", {DISABLE_COLOR_ENV_VAR: "true"}): + for method in ( + reset, + red, + yellow, + green, + bold, + error_style, + warning_style, + success_style, + snapshot_style, + snapshot_diff_style, + received_style, + received_diff_style, + context_style, + ): + _ = method("foo") + + # Prevent test from accidentally passing by patching wrong object + with pytest.raises(TypeError) as excinfo: + _ = red("foo") + + assert "NonCallableMock" in str(excinfo.value)