Skip to content

Commit 799495c

Browse files
committed
Adds ability to configure stderr output color
1 parent ab51e14 commit 799495c

File tree

5 files changed

+21
-1
lines changed

5 files changed

+21
-1
lines changed

docs/changelog/3426.misc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Adds ability to configure the stderr color for output received from external
2+
commands.

src/tox/config/cli/parser.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from pathlib import Path
1212
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple, Type, TypeVar, cast
1313

14+
from colorama import Fore
15+
1416
from tox.config.loader.str_convert import StrConvert
1517
from tox.plugin import NAME
1618
from tox.util.ci import is_ci
@@ -366,6 +368,12 @@ def add_color_flags(parser: ArgumentParser) -> None:
366368
choices=["yes", "no"],
367369
help="should output be enriched with colors, default is yes unless TERM=dumb or NO_COLOR is defined.",
368370
)
371+
parser.add_argument(
372+
"--stderr-color",
373+
default="RED",
374+
choices=["0", *Fore.__dict__.keys()],
375+
help="color for stderr output, use 0 to disable coloring.",
376+
)
369377

370378

371379
def add_exit_and_dump_after(parser: ArgumentParser) -> None:

src/tox/execute/api.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ def call(
122122
env: ToxEnv,
123123
) -> Iterator[ExecuteStatus]:
124124
start = time.monotonic()
125+
stderr_color = Fore.RED
126+
try:
127+
cfg_color = env.conf._conf.options.stderr_color # noqa: SLF001
128+
stderr_color = None if cfg_color == "0" else Fore.__dict__[cfg_color]
129+
except (AttributeError, KeyError, TypeError): # many tests have a mocked 'env'
130+
pass
125131
try:
126132
# collector is what forwards the content from the file streams to the standard streams
127133
out, err = out_err[0].buffer, out_err[1].buffer
128134
out_sync = SyncWrite(out.name, out if show else None)
129-
err_sync = SyncWrite(err.name, err if show else None, Fore.RED if self._colored else None)
135+
err_sync = SyncWrite(err.name, err if show else None, stderr_color)
130136
with out_sync, err_sync:
131137
instance = self.build_instance(request, self._option_class(env), out_sync, err_sync)
132138
with instance as status:

tests/config/cli/test_cli_env_var.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def test_verbose_no_test() -> None:
3131
"verbose": 4,
3232
"quiet": 0,
3333
"colored": "no",
34+
"stderr_color": "RED",
3435
"work_dir": None,
3536
"root_dir": None,
3637
"config_file": None,
@@ -90,6 +91,7 @@ def test_env_var_exhaustive_parallel_values(
9091
assert vars(options.parsed) == {
9192
"always_copy": False,
9293
"colored": "no",
94+
"stderr_color": "RED",
9395
"command": "legacy",
9496
"default_runner": "virtualenv",
9597
"develop": False,

tests/config/cli/test_cli_ini.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
def default_options() -> dict[str, Any]:
3030
return {
3131
"colored": "no",
32+
"stderr_color": "RED",
3233
"command": "r",
3334
"default_runner": "virtualenv",
3435
"develop": False,
@@ -200,6 +201,7 @@ def test_ini_exhaustive_parallel_values(core_handlers: dict[str, Callable[[State
200201
options = get_options("p")
201202
assert vars(options.parsed) == {
202203
"colored": "yes",
204+
"stderr_color": "RED",
203205
"command": "p",
204206
"default_runner": "virtualenv",
205207
"develop": False,

0 commit comments

Comments
 (0)