From 952560403624de3054939b5039eada96a4adccbd Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi-Ugbe Date: Sat, 19 Sep 2020 12:19:57 -0400 Subject: [PATCH 1/5] fix: use env variable to disable terminal color --- dev_requirements.txt | 9 ++------- src/syrupy/terminal.py | 40 +++++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/dev_requirements.txt b/dev_requirements.txt index 42117ca9..49f73b6e 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -9,15 +9,13 @@ attrs==20.2.0 # via flake8-bugbear, pytest, syrupy black==20.8b1 # via syrupy bleach==3.2.1 # via readme-renderer certifi==2020.6.20 # via requests -cffi==1.14.2 # via cryptography chardet==3.0.4 # via requests click==7.1.2 # via black, pip-tools codecov==2.1.9 # via syrupy colorama==0.4.3 # via twine colored==1.4.2 # via syrupy configparser==5.0.0 # via py-githooks -coverage[toml]==5.3 # via codecov, syrupy -cryptography==3.1 # via secretstorage +coverage[toml]==5.3 # via codecov, syrupy deprecated==1.2.10 # via pygithub docutils==0.16 # via readme-renderer flake8-bugbear==20.1.4 # via syrupy @@ -29,7 +27,6 @@ idna==2.10 # via requests iniconfig==1.0.1 # via pytest invoke==1.4.1 # via syrupy isort==5.5.2 # via syrupy -jeepney==0.4.3 # via keyring, secretstorage keyring==21.4.0 # via twine mccabe==0.6.1 # via flake8 more-itertools==8.5.0 # via pytest @@ -43,7 +40,6 @@ pluggy==0.13.1 # via pytest py-githooks==1.1.0 # via syrupy py==1.9.0 # via pytest pycodestyle==2.6.0 # via flake8 -pycparser==2.20 # via cffi pyflakes==2.2.0 # via flake8 pygithub==1.53 # via syrupy pygments==2.7.1 # via readme-renderer @@ -56,9 +52,8 @@ regex==2020.7.14 # via black requests-toolbelt==0.9.1 # via twine requests==2.24.0 # via codecov, pygithub, requests-toolbelt, twine rfc3986==1.4.0 # via twine -secretstorage==3.1.2 # via keyring semver==2.10.2 # via syrupy -six==1.15.0 # via bleach, cryptography, packaging, pip-tools, readme-renderer +six==1.15.0 # via bleach, packaging, pip-tools, readme-renderer toml==0.10.1 # via black, coverage, pytest tqdm==4.49.0 # via twine twine==3.2.0 # via syrupy diff --git a/src/syrupy/terminal.py b/src/syrupy/terminal.py index 5e62888a..d1936afe 100644 --- a/src/syrupy/terminal.py +++ b/src/syrupy/terminal.py @@ -1,26 +1,44 @@ -from typing import Union +import os +from typing import ( + Any, + Union, +) import colored +def _is_color_disabled() -> bool: + disable_color_env_vars = {"ANSI_COLORS_DISABLED", "NO_COLOR"} + for env_var_name in disable_color_env_vars: + if os.environ.get(env_var_name) is not None: + return True + return False + + +def _stylize(text: Union[str, int], *args: Any) -> str: + if _is_color_disabled(): + return str(text) + return colored.stylize(text, *args) + + def reset(text: Union[str, int]) -> str: - return colored.stylize(text, colored.attr("reset")) + return _stylize(text, colored.attr("reset")) def red(text: Union[str, int]) -> str: - return colored.stylize(text, colored.fg("red")) + return _stylize(text, colored.fg("red")) def yellow(text: Union[str, int]) -> str: - return colored.stylize(text, colored.fg("yellow")) + return _stylize(text, colored.fg("yellow")) def green(text: Union[str, int]) -> str: - return colored.stylize(text, colored.fg("green")) + return _stylize(text, colored.fg("green")) def bold(text: Union[str, int]) -> str: - return colored.stylize(text, colored.attr("bold")) + return _stylize(text, colored.attr("bold")) def error_style(text: Union[str, int]) -> str: @@ -36,20 +54,20 @@ def success_style(text: Union[str, int]) -> str: def snapshot_style(text: Union[str, int]) -> str: - return colored.stylize(text, colored.bg(225) + colored.fg(90)) + return _stylize(text, colored.bg(225) + colored.fg(90)) def snapshot_diff_style(text: Union[str, int]) -> str: - return colored.stylize(text, colored.bg(90) + colored.fg(225)) + return _stylize(text, colored.bg(90) + colored.fg(225)) def received_style(text: Union[str, int]) -> str: - return colored.stylize(text, colored.bg(195) + colored.fg(23)) + return _stylize(text, colored.bg(195) + colored.fg(23)) def received_diff_style(text: Union[str, int]) -> str: - return colored.stylize(text, colored.bg(23) + colored.fg(195)) + return _stylize(text, colored.bg(23) + colored.fg(195)) def context_style(text: Union[str, int]) -> str: - return colored.stylize(text, colored.attr("dim")) + return _stylize(text, colored.attr("dim")) From cb8d25190b1a9c68bb668dcca2313e69771d1bd6 Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi-Ugbe Date: Sat, 19 Sep 2020 12:34:06 -0400 Subject: [PATCH 2/5] docs: add no color to option list --- README.md | 11 ++++++----- src/syrupy/__init__.py | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 979f3907..361dd8e8 100644 --- a/README.md +++ b/README.md @@ -74,11 +74,12 @@ def __repr__(self) -> str: These are the cli options exposed to `pytest` by the plugin. -| Option | Description | Default | -| ------------------------------ | ----------------------------------------------------------------------------------- | ------------------------------------------------ | -| `--snapshot-update` | Snapshots will be updated to match assertions and unused snapshots will be deleted. | `False` | -| `--snapshot-warn-unused` | Prints a warning on unused snapshots rather than fail the test suite. | `False` | -| `--snapshot-default-extension` | Use to change the default snapshot extension class. | `syrupy.extensions.amber.AmberSnapshotExtension` | +| Option | Description | Default | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ | +| `--snapshot-update` | Snapshots will be updated to match assertions and unused snapshots will be deleted. | `False` | +| `--snapshot-warn-unused` | Prints a warning on unused snapshots rather than fail the test suite. | `False` | +| `--snapshot-default-extension` | Use to change the default snapshot extension class. | `syrupy.extensions.amber.AmberSnapshotExtension` | +| `--snapshot-no-colors` | Disable test results output highlighting. Equivalent to setting the environment variables `ANSI_COLORS_DISABLED` or `NO_COLOR` | Disabled by default if not in terminal. | ### Assertion Options diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py index 106b70d0..05dd26e3 100644 --- a/src/syrupy/__init__.py +++ b/src/syrupy/__init__.py @@ -1,5 +1,6 @@ import argparse import glob +import sys from gettext import gettext from typing import ( Any, @@ -56,6 +57,13 @@ def pytest_addoption(parser: Any) -> None: dest="default_extension", help="Specify the default snapshot extension", ) + group.addoption( + "--snapshot-no-colors", + action="store_true", + default=not sys.stdout.isatty(), + dest="no_colors", + help="Disable test results output highlighting", + ) def pytest_assertrepr_compare(op: str, left: Any, right: Any) -> Optional[List[str]]: From 965060e72bd241fa1f4110e340c0a182c1886025 Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi-Ugbe Date: Sat, 19 Sep 2020 13:20:06 -0400 Subject: [PATCH 3/5] test: update cases to work with no colors --- conftest.py | 9 +++++++++ src/syrupy/__init__.py | 4 ++++ src/syrupy/constants.py | 3 +++ src/syrupy/terminal.py | 5 +++-- src/syrupy/utils.py | 12 ++++++++++++ .../test_integration_default.ambr | 2 +- tests/test_extension_base.py | 7 +++---- tests/test_integration_custom.py | 6 ++---- tests/test_integration_default.py | 18 ++++++++---------- tests/test_integration_pytest_extension.py | 5 +---- tests/test_integration_single_file.py | 12 +++++------- tests/utils.py | 6 ------ 12 files changed, 51 insertions(+), 38 deletions(-) delete mode 100644 tests/utils.py diff --git a/conftest.py b/conftest.py index 43a0e81e..af3510bd 100644 --- a/conftest.py +++ b/conftest.py @@ -1,4 +1,13 @@ import typing +import pytest + +from syrupy.utils import env_context + typing.TYPE_CHECKING = True pytest_plugins = "pytester" + + +@pytest.fixture +def osenv(): + return env_context diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py index 05dd26e3..dfcdfc14 100644 --- a/src/syrupy/__init__.py +++ b/src/syrupy/__init__.py @@ -1,5 +1,6 @@ import argparse import glob +import os import sys from gettext import gettext from typing import ( @@ -11,6 +12,7 @@ import pytest from .assertion import SnapshotAssertion +from .constants import DISABLE_COLOR_ENV_VAR from .exceptions import FailedToLoadModuleMember from .extensions import DEFAULT_EXTENSION from .location import TestLocation @@ -102,6 +104,8 @@ def pytest_sessionstart(session: Any) -> None: https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_sessionstart """ config = session.config + if config.option.no_colors: + os.environ[DISABLE_COLOR_ENV_VAR] = "true" config._syrupy = SnapshotSession( warn_unused_snapshots=config.option.warn_unused_snapshots, update_snapshots=config.option.update_snapshots, diff --git a/src/syrupy/constants.py b/src/syrupy/constants.py index 8668001b..5cbe9da4 100644 --- a/src/syrupy/constants.py +++ b/src/syrupy/constants.py @@ -7,3 +7,6 @@ SYMBOL_ELLIPSIS = "..." # U+2026 SYMBOL_NEW_LINE = "␤" # U+2424 SYMBOL_CARRIAGE = "␍" # U+240D + +DISABLE_COLOR_ENV_VAR = "ANSI_COLORS_DISABLED" +DISABLE_COLOR_ENV_VARS = {DISABLE_COLOR_ENV_VAR, "NO_COLOR"} diff --git a/src/syrupy/terminal.py b/src/syrupy/terminal.py index d1936afe..9c784152 100644 --- a/src/syrupy/terminal.py +++ b/src/syrupy/terminal.py @@ -6,10 +6,11 @@ import colored +from .constants import DISABLE_COLOR_ENV_VARS + def _is_color_disabled() -> bool: - disable_color_env_vars = {"ANSI_COLORS_DISABLED", "NO_COLOR"} - for env_var_name in disable_color_env_vars: + for env_var_name in DISABLE_COLOR_ENV_VARS: if os.environ.get(env_var_name) is not None: return True return False diff --git a/src/syrupy/utils.py b/src/syrupy/utils.py index eaeb3374..a766e6f9 100644 --- a/src/syrupy/utils.py +++ b/src/syrupy/utils.py @@ -1,3 +1,5 @@ +import os +from contextlib import contextmanager from gettext import gettext from importlib import import_module from pathlib import Path @@ -46,3 +48,13 @@ def import_module_member(path: str) -> Any: module_name, ) ) + + +@contextmanager +def env_context(**kwargs: str) -> Iterator[None]: + prev_env = {**os.environ} + try: + yield os.environ.update(kwargs) + finally: + os.environ.clear() + os.environ.update(prev_env) diff --git a/tests/__snapshots__/test_integration_default.ambr b/tests/__snapshots__/test_integration_default.ambr index b04fff09..a224ed1e 100644 --- a/tests/__snapshots__/test_integration_default.ambr +++ b/tests/__snapshots__/test_integration_default.ambr @@ -74,7 +74,7 @@ you do not want to see this line or this line this line should show up because it changes\n - this line should show up because it changes color + this line should show up because it changes color and this line does not exist in the first one ''' E AssertionError: assert snapshot == received diff --git a/tests/test_extension_base.py b/tests/test_extension_base.py index 2e543b14..b2a363cc 100644 --- a/tests/test_extension_base.py +++ b/tests/test_extension_base.py @@ -2,8 +2,6 @@ from syrupy.extensions.base import SnapshotReporter -from .utils import clean_output - class SnapshotReporterNoContext(SnapshotReporter): @property @@ -27,5 +25,6 @@ class TestSnapshotReporter: ], ids=lambda _: "", ) - def test_diff_lines(self, a, b, Reporter, snapshot): - assert "\n".join(map(clean_output, Reporter().diff_lines(a, b))) == snapshot + def test_diff_lines(self, a, b, Reporter, snapshot, osenv): + with osenv(NO_COLOR="true"): + assert "\n".join(Reporter().diff_lines(a, b)) == snapshot diff --git a/tests/test_integration_custom.py b/tests/test_integration_custom.py index 243180f6..1837f6bf 100644 --- a/tests/test_integration_custom.py +++ b/tests/test_integration_custom.py @@ -1,7 +1,5 @@ import pytest -from .utils import clean_output - @pytest.fixture def testcases(testdir): @@ -56,8 +54,8 @@ def test_passed_custom(snapshot_custom): def test_warns_on_snapshot_name(testdir, testcases): testdir.makepyfile(test_file=testcases["passed"]) - result = testdir.runpytest("-v", "--snapshot-update") - result_stdout = clean_output(result.stdout.str()) + result = testdir.runpytest("-v", "--snapshot-update", "--snapshot-no-colors") + result_stdout = result.stdout.str() assert "2 snapshots generated" in result_stdout assert "Warning:" in result_stdout assert "Can not relate snapshot name" in result_stdout diff --git a/tests/test_integration_default.py b/tests/test_integration_default.py index 0e4a312f..775cd9a7 100644 --- a/tests/test_integration_default.py +++ b/tests/test_integration_default.py @@ -2,11 +2,9 @@ import pytest -from .utils import clean_output - def get_result_snapshot_summary(result: object) -> str: - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() start_idx = result_stdout.find("\n", result_stdout.find("---- snapshot report")) end_idx = result_stdout.find("====", start_idx) return result_stdout[start_idx:end_idx].strip() @@ -120,7 +118,7 @@ def test_case_2(self, snapshot): test_filepath = Path(testdir.tmpdir, "test_content.py") result = testdir.runpytest(str(test_filepath), "-v", "-k test_case_2") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "1 snapshot passed" in result_stdout assert "snapshot unused" not in result_stdout @@ -144,7 +142,7 @@ def test_case_2(snapshot): test_filepath = Path(testdir.tmpdir, "test_content.py") result = testdir.runpytest(str(test_filepath), "-v", "-k test_case_2") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "1 snapshot passed" in result_stdout assert "snapshot unused" not in result_stdout @@ -161,7 +159,7 @@ def test_case_1(snapshot): testdir.makepyfile(test_content=test_content) result = testdir.runpytest("-v", "--snapshot-update") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "Can not relate snapshot name" not in result_stdout @@ -305,8 +303,8 @@ def test_generated_snapshots(stubs, snapshot): def test_failing_snapshots_diff(stubs, testcases_updated, snapshot): testdir = stubs[1] testdir.makepyfile(test_file="\n\n".join(testcases_updated.values())) - result = testdir.runpytest("-vv") - result_stdout = clean_output(result.stdout.str()) + result = testdir.runpytest("-vv", "--snapshot-no-colors") + result_stdout = result.stdout.str() start_index = result_stdout.find("\n", result_stdout.find("==== FAILURES")) end_index = result_stdout.find("\n", result_stdout.find("---- snapshot report")) assert result_stdout[start_index:end_index] == snapshot @@ -426,7 +424,7 @@ def test_removed_hanging_snapshot_fossil(stubs, snapshot): hanging_filepath = Path(testdir.tmpdir, "__snapshots__/test_hanging.abc") assert hanging_filepath.exists() result = testdir.runpytest("-v", "--snapshot-update") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert str(Path(filepath).relative_to(Path.cwd())) not in result_stdout assert "1 unused snapshot deleted" in result_stdout assert "unknown snapshot" in result_stdout @@ -464,7 +462,7 @@ def test_snapshot_default_extension_option_failure(testdir, testcases, snapshot) "--snapshot-default-extension", "syrupy.extensions.amber.DoesNotExistExtension", ) - result_stderr = clean_output(result.stderr.str()) + result_stderr = result.stderr.str() assert "error: argument --snapshot-default-extension" in result_stderr assert "Member 'DoesNotExistExtension' not found" in result_stderr assert result.ret diff --git a/tests/test_integration_pytest_extension.py b/tests/test_integration_pytest_extension.py index 8ca02362..0d44b0de 100644 --- a/tests/test_integration_pytest_extension.py +++ b/tests/test_integration_pytest_extension.py @@ -1,6 +1,3 @@ -from .utils import clean_output - - def test_ignores_non_function_nodes(testdir): conftest = """ import pytest @@ -23,6 +20,6 @@ def test_example(snapshot): testdir.makepyfile(conftest=conftest) testdir.makepyfile(test_file=testcase) result = testdir.runpytest("test_file.py", "-v", "--snapshot-update") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert result.ret == 0 assert "test_file.py::CUSTOM" in result_stdout diff --git a/tests/test_integration_single_file.py b/tests/test_integration_single_file.py index 9a1363a5..4c9cdf6f 100644 --- a/tests/test_integration_single_file.py +++ b/tests/test_integration_single_file.py @@ -1,7 +1,5 @@ import pytest -from .utils import clean_output - @pytest.fixture def testcases(testdir): @@ -67,7 +65,7 @@ def test_passed_single(snapshot_single): def test_unsaved_snapshots(snapshot, testdir, testcases): testdir.makepyfile(test_file=testcases["passed"]) result = testdir.runpytest("-v") - output = clean_output(result.stdout.str()) + output = result.stdout.str() assert "Snapshot does not exist" in output assert "+ b'passed1'" in output assert result.ret == 1 @@ -76,7 +74,7 @@ def test_unsaved_snapshots(snapshot, testdir, testcases): def test_failed_snapshots(testdir, testcases): testdir.makepyfile(test_file=testcases["failed"]) result = testdir.runpytest("-v", "--snapshot-update") - assert "2 snapshots failed" in clean_output(result.stdout.str()) + assert "2 snapshots failed" in result.stdout.str() assert result.ret == 1 @@ -88,7 +86,7 @@ def stubs(testdir, testcases): def test_generated_snapshots(stubs): result = stubs[0] - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "2 snapshots generated" in result_stdout assert "snapshots unused" not in result_stdout assert result.ret == 0 @@ -98,7 +96,7 @@ def test_unmatched_snapshots(stubs, testcases_updated): testdir = stubs[1] testdir.makepyfile(test_file=testcases_updated["passed"]) result = testdir.runpytest("-v") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "1 snapshot failed" in result_stdout assert "1 snapshot unused" in result_stdout assert result.ret == 1 @@ -108,7 +106,7 @@ def test_updated_snapshots(stubs, testcases_updated): testdir = stubs[1] testdir.makepyfile(test_file=testcases_updated["passed"]) result = testdir.runpytest("-v", "--snapshot-update") - result_stdout = clean_output(result.stdout.str()) + result_stdout = result.stdout.str() assert "1 snapshot updated" in result_stdout assert "1 unused snapshot deleted" in result_stdout assert result.ret == 0 diff --git a/tests/utils.py b/tests/utils.py deleted file mode 100644 index b09fb9a3..00000000 --- a/tests/utils.py +++ /dev/null @@ -1,6 +0,0 @@ -import re - - -def clean_output(output: str) -> str: - """Removes ansi color codes from string""" - return re.sub(r"\x1B[@-_][0-?]*[ -/]*[@-~]", "", str(output).strip()) From 0ee9d407b0b1fcd95b6949dc6b10f2003c162b96 Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi-Ugbe Date: Sat, 19 Sep 2020 13:59:20 -0400 Subject: [PATCH 4/5] fix: ensure term color is repected in assert repr --- src/syrupy/__init__.py | 49 ++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py index dfcdfc14..88850ed1 100644 --- a/src/syrupy/__init__.py +++ b/src/syrupy/__init__.py @@ -1,10 +1,10 @@ import argparse import glob -import os import sys from gettext import gettext from typing import ( Any, + ContextManager, List, Optional, ) @@ -22,7 +22,10 @@ reset, snapshot_style, ) -from .utils import import_module_member +from .utils import ( + env_context, + import_module_member, +) def __default_extension_option(value: str) -> Any: @@ -68,21 +71,32 @@ def pytest_addoption(parser: Any) -> None: ) -def pytest_assertrepr_compare(op: str, left: Any, right: Any) -> Optional[List[str]]: +def __terminal_color(config: Any) -> "ContextManager[None]": + env = {} + if config.option.no_colors: + env[DISABLE_COLOR_ENV_VAR] = "true" + + return env_context(**env) + + +def pytest_assertrepr_compare( + config: Any, op: str, left: Any, right: Any +) -> Optional[List[str]]: """ Return explanation for comparisons in failing assert expressions. https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_assertrepr_compare """ - if isinstance(left, SnapshotAssertion): - assert_msg = reset( - f"{snapshot_style(left.name)} {op} {received_style('received')}" - ) - return [assert_msg] + left.get_assert_diff() - elif isinstance(right, SnapshotAssertion): - assert_msg = reset( - f"{received_style('received')} {op} {snapshot_style(right.name)}" - ) - return [assert_msg] + right.get_assert_diff() + with __terminal_color(config): + if isinstance(left, SnapshotAssertion): + assert_msg = reset( + f"{snapshot_style(left.name)} {op} {received_style('received')}" + ) + return [assert_msg] + left.get_assert_diff() + elif isinstance(right, SnapshotAssertion): + assert_msg = reset( + f"{received_style('received')} {op} {snapshot_style(right.name)}" + ) + return [assert_msg] + right.get_assert_diff() return None @@ -104,8 +118,6 @@ def pytest_sessionstart(session: Any) -> None: https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_sessionstart """ config = session.config - if config.option.no_colors: - os.environ[DISABLE_COLOR_ENV_VAR] = "true" config._syrupy = SnapshotSession( warn_unused_snapshots=config.option.warn_unused_snapshots, update_snapshots=config.option.update_snapshots, @@ -156,9 +168,10 @@ def pytest_terminal_summary( Add syrupy report to pytest. https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_terminal_summary """ - terminalreporter.write_sep("-", gettext("snapshot report summary")) - for line in terminalreporter.config._syrupy.report.lines: - terminalreporter.write_line(line) + with __terminal_color(config): + terminalreporter.write_sep("-", gettext("snapshot report summary")) + for line in terminalreporter.config._syrupy.report.lines: + terminalreporter.write_line(line) @pytest.fixture From 51bcaf6007bfdfd5905300655a11715eec022cef Mon Sep 17 00:00:00 2001 From: Emmanuel Ogbizi-Ugbe Date: Sat, 19 Sep 2020 14:16:34 -0400 Subject: [PATCH 5/5] refactor: support wider range of env values --- src/syrupy/terminal.py | 7 ++----- src/syrupy/utils.py | 8 ++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/syrupy/terminal.py b/src/syrupy/terminal.py index 9c784152..dec15327 100644 --- a/src/syrupy/terminal.py +++ b/src/syrupy/terminal.py @@ -1,4 +1,3 @@ -import os from typing import ( Any, Union, @@ -7,13 +6,11 @@ import colored from .constants import DISABLE_COLOR_ENV_VARS +from .utils import get_env_value def _is_color_disabled() -> bool: - for env_var_name in DISABLE_COLOR_ENV_VARS: - if os.environ.get(env_var_name) is not None: - return True - return False + return any(map(get_env_value, DISABLE_COLOR_ENV_VARS)) def _stylize(text: Union[str, int], *args: Any) -> str: diff --git a/src/syrupy/utils.py b/src/syrupy/utils.py index a766e6f9..86370921 100644 --- a/src/syrupy/utils.py +++ b/src/syrupy/utils.py @@ -1,3 +1,4 @@ +import json import os from contextlib import contextmanager from gettext import gettext @@ -50,6 +51,13 @@ def import_module_member(path: str) -> Any: ) +def get_env_value(env_var_name: str) -> object: + try: + return json.loads(os.environ[env_var_name]) + except (KeyError, TypeError, json.decoder.JSONDecodeError): + return os.environ.get(env_var_name) + + @contextmanager def env_context(**kwargs: str) -> Iterator[None]: prev_env = {**os.environ}