Skip to content

Commit b664cd4

Browse files
committed
Add test class helper to force no terminal colour
1 parent 71df920 commit b664cd4

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

Lib/test/support/__init__.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"skip_on_s390x",
6161
"without_optimizer",
6262
"force_not_colorized",
63+
"force_not_colorized_test_class",
6364
"BrokenIter",
6465
"in_systemd_nspawn_sync_suppressed",
6566
]
@@ -2855,6 +2856,44 @@ def wrapper(*args, **kwargs):
28552856
return wrapper
28562857

28572858

2859+
2860+
def force_not_colorized_test_class(cls):
2861+
"""Force the terminal not to be colorized."""
2862+
original_setup = cls.setUp
2863+
original_teardown = cls.tearDown
2864+
2865+
@functools.wraps(cls.setUp)
2866+
def setUp_wrapper(self, *args, **kwargs):
2867+
import _colorize
2868+
2869+
self._original_fn = _colorize.can_colorize
2870+
self._variables: dict[str, str | None] = {
2871+
"PYTHON_COLORS": None,
2872+
"FORCE_COLOR": None,
2873+
"NO_COLOR": None,
2874+
}
2875+
for key in self._variables:
2876+
self._variables[key] = os.environ.pop(key, None)
2877+
os.environ["NO_COLOR"] = "1"
2878+
_colorize.can_colorize = lambda: False
2879+
return original_setup(self, *args, **kwargs)
2880+
2881+
@functools.wraps(cls.tearDown)
2882+
def tearDown_wrapper(self, *args, **kwargs):
2883+
import _colorize
2884+
2885+
_colorize.can_colorize = self._original_fn
2886+
del os.environ["NO_COLOR"]
2887+
for key, value in self._variables.items():
2888+
if value is not None:
2889+
os.environ[key] = value
2890+
return original_teardown(self, *args, **kwargs)
2891+
2892+
cls.setUp = setUp_wrapper
2893+
cls.tearDown = tearDown_wrapper
2894+
return cls
2895+
2896+
28582897
def initialized_with_pyrepl():
28592898
"""Detect whether PyREPL was used during Python initialization."""
28602899
# If the main module has a __file__ attribute it's a Python module, which means PyREPL.

Lib/test/test_traceback.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from test.support.os_helper import TESTFN, unlink
2222
from test.support.script_helper import assert_python_ok, assert_python_failure
2323
from test.support.import_helper import forget
24-
from test.support import force_not_colorized
24+
from test.support import force_not_colorized, force_not_colorized_test_class
2525

2626
import json
2727
import textwrap
@@ -1712,6 +1712,7 @@ def f():
17121712

17131713

17141714
@requires_debug_ranges()
1715+
@force_not_colorized_test_class
17151716
class PurePythonTracebackErrorCaretTests(
17161717
PurePythonExceptionFormattingMixin,
17171718
TracebackErrorLocationCaretTestBase,
@@ -1725,6 +1726,7 @@ class PurePythonTracebackErrorCaretTests(
17251726

17261727
@cpython_only
17271728
@requires_debug_ranges()
1729+
@force_not_colorized_test_class
17281730
class CPythonTracebackErrorCaretTests(
17291731
CAPIExceptionFormattingMixin,
17301732
TracebackErrorLocationCaretTestBase,
@@ -1736,6 +1738,7 @@ class CPythonTracebackErrorCaretTests(
17361738

17371739
@cpython_only
17381740
@requires_debug_ranges()
1741+
@force_not_colorized_test_class
17391742
class CPythonTracebackLegacyErrorCaretTests(
17401743
CAPIExceptionFormattingLegacyMixin,
17411744
TracebackErrorLocationCaretTestBase,
@@ -2149,10 +2152,12 @@ def test_print_exception_bad_type_python(self):
21492152
boundaries = re.compile(
21502153
'(%s|%s)' % (re.escape(cause_message), re.escape(context_message)))
21512154

2155+
@force_not_colorized_test_class
21522156
class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin):
21532157
pass
21542158

21552159
@cpython_only
2160+
@force_not_colorized_test_class
21562161
class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin):
21572162
DEBUG_RANGES = False
21582163
def setUp(self) -> None:
@@ -2940,6 +2945,7 @@ def f():
29402945
self.assertEqual(report, expected)
29412946

29422947

2948+
@force_not_colorized_test_class
29432949
class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
29442950
#
29452951
# This checks reporting through the 'traceback' module, with both
@@ -2956,6 +2962,7 @@ def get_report(self, e):
29562962
return s
29572963

29582964

2965+
@force_not_colorized_test_class
29592966
class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
29602967
#
29612968
# This checks built-in reporting by the interpreter.

Lib/test/test_unittest/test_result.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import io
22
import sys
33
import textwrap
4-
5-
from test.support import warnings_helper, captured_stdout
6-
74
import traceback
85
import unittest
9-
from unittest.util import strclass
10-
from test.support import force_not_colorized
6+
from test.support import (
7+
captured_stdout,
8+
force_not_colorized,
9+
force_not_colorized_test_class,
10+
warnings_helper,
11+
)
1112
from test.test_unittest.support import BufferedWriter
13+
from unittest.util import strclass
1214

1315

1416
class MockTraceback(object):
@@ -772,6 +774,7 @@ def testFoo(self):
772774
runner.run(Test('testFoo'))
773775

774776

777+
@force_not_colorized_test_class
775778
class TestOutputBuffering(unittest.TestCase):
776779

777780
def setUp(self):

0 commit comments

Comments
 (0)