setattr(NoColors, attr, "")
-def get_colors(colorize: bool = False) -> ANSIColors:
- if colorize or can_colorize():
+def get_colors(colorize: bool = False, *, file=None) -> ANSIColors:
+ if colorize or can_colorize(file=file):
return ANSIColors()
else:
return NoColors
-def can_colorize() -> bool:
+def can_colorize(*, file=None) -> bool:
+ if file is None:
+ file = sys.stdout
+
if not sys.flags.ignore_environment:
if os.environ.get("PYTHON_COLORS") == "0":
return False
if os.environ.get("TERM") == "dumb":
return False
- if not hasattr(sys.stderr, "fileno"):
+ if not hasattr(file, "fileno"):
return False
if sys.platform == "win32":
return False
try:
- return os.isatty(sys.stderr.fileno())
+ return os.isatty(file.fileno())
except io.UnsupportedOperation:
- return sys.stderr.isatty()
+ return file.isatty()
save_displayhook = sys.displayhook
sys.displayhook = sys.__displayhook__
saved_can_colorize = _colorize.can_colorize
- _colorize.can_colorize = lambda: False
+ _colorize.can_colorize = lambda *args, **kwargs: False
color_variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None}
for key in color_variables:
color_variables[key] = os.environ.pop(key, None)
def _runtest_env_changed_exc(result: TestResult, runtests: RunTests,
display_failure: bool = True) -> None:
# Handle exceptions, detect environment changes.
- ansi = get_colors()
- red, reset, yellow = ansi.RED, ansi.RESET, ansi.YELLOW
+ stdout = get_colors(file=sys.stdout)
+ stderr = get_colors(file=sys.stderr)
# Reset the environment_altered flag to detect if a test altered
# the environment
_load_run_test(result, runtests)
except support.ResourceDenied as exc:
if not quiet and not pgo:
- print(f"{yellow}{test_name} skipped -- {exc}{reset}", flush=True)
+ print(
+ f"{stdout.YELLOW}{test_name} skipped -- {exc}{stdout.RESET}",
+ flush=True,
+ )
result.state = State.RESOURCE_DENIED
return
except unittest.SkipTest as exc:
if not quiet and not pgo:
- print(f"{yellow}{test_name} skipped -- {exc}{reset}", flush=True)
+ print(
+ f"{stdout.YELLOW}{test_name} skipped -- {exc}{stdout.RESET}",
+ flush=True,
+ )
result.state = State.SKIPPED
return
except support.TestFailedWithDetails as exc:
- msg = f"{red}test {test_name} failed{reset}"
+ msg = f"{stderr.RED}test {test_name} failed{stderr.RESET}"
if display_failure:
- msg = f"{red}{msg} -- {exc}{reset}"
+ msg = f"{stderr.RED}{msg} -- {exc}{stderr.RESET}"
print(msg, file=sys.stderr, flush=True)
result.state = State.FAILED
result.errors = exc.errors
result.stats = exc.stats
return
except support.TestFailed as exc:
- msg = f"{red}test {test_name} failed{reset}"
+ msg = f"{stderr.RED}test {test_name} failed{stderr.RESET}"
if display_failure:
- msg = f"{red}{msg} -- {exc}{reset}"
+ msg = f"{stderr.RED}{msg} -- {exc}{stderr.RESET}"
print(msg, file=sys.stderr, flush=True)
result.state = State.FAILED
result.stats = exc.stats
except:
if not pgo:
msg = traceback.format_exc()
- print(f"{red}test {test_name} crashed -- {msg}{reset}",
- file=sys.stderr, flush=True)
+ print(
+ f"{stderr.RED}test {test_name} crashed -- {msg}{stderr.RESET}",
+ file=sys.stderr,
+ flush=True,
+ )
result.state = State.UNCAUGHT_EXC
return
If runtests.use_junit, xml_data is a list containing each generated
testsuite element.
"""
- ansi = get_colors()
+ ansi = get_colors(file=sys.stderr)
red, reset, yellow = ansi.BOLD_RED, ansi.RESET, ansi.YELLOW
start_time = time.perf_counter()
from .os_helper import EnvironmentVarGuard
with (
- swap_attr(_colorize, "can_colorize", lambda: False),
+ swap_attr(_colorize, "can_colorize", lambda file=None: False),
EnvironmentVarGuard() as env,
):
for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}:
def _print_exception_bltin(exc, /):
file = sys.stderr if sys.stderr is not None else sys.__stderr__
- colorize = _colorize.can_colorize()
+ colorize = _colorize.can_colorize(file=file)
return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize)
capture_locals=self.tb_locals, compact=True)
from _colorize import can_colorize
- msgLines = list(tb_e.format(colorize=can_colorize()))
+ colorize = hasattr(self, "stream") and can_colorize(file=self.stream)
+ msgLines = list(tb_e.format(colorize=colorize))
if self.buffer:
output = sys.stdout.getvalue()
self.showAll = verbosity > 1
self.dots = verbosity == 1
self.descriptions = descriptions
- self._ansi = get_colors()
+ self._ansi = get_colors(file=stream)
self._newline = True
self.durations = durations
expected_fails, unexpected_successes, skipped = results
infos = []
- ansi = get_colors()
+ ansi = get_colors(file=self.stream)
bold_red = ansi.BOLD_RED
green = ansi.GREEN
red = ansi.RED
--- /dev/null
+Default to stdout isatty for color detection instead of stderr. Patch by
+Hugo van Kemenade.