mirror of
https://github.com/python/cpython.git
synced 2025-08-02 16:13:13 +00:00
[3.13] gh-128595: Add test class helper to force no terminal colour (GH-128687) (#128778)
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
This commit is contained in:
parent
05bd6cbe61
commit
afcf238ed4
4 changed files with 44 additions and 21 deletions
|
@ -60,6 +60,7 @@ __all__ = [
|
||||||
"skip_on_s390x",
|
"skip_on_s390x",
|
||||||
"without_optimizer",
|
"without_optimizer",
|
||||||
"force_not_colorized",
|
"force_not_colorized",
|
||||||
|
"force_not_colorized_test_class",
|
||||||
"BrokenIter",
|
"BrokenIter",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2693,30 +2694,44 @@ def iter_slot_wrappers(cls):
|
||||||
yield name, True
|
yield name, True
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def no_color():
|
||||||
|
import _colorize
|
||||||
|
from .os_helper import EnvironmentVarGuard
|
||||||
|
|
||||||
|
with (
|
||||||
|
swap_attr(_colorize, "can_colorize", lambda: False),
|
||||||
|
EnvironmentVarGuard() as env,
|
||||||
|
):
|
||||||
|
for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}:
|
||||||
|
env.unset(var)
|
||||||
|
env.set("NO_COLOR", "1")
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
def force_not_colorized(func):
|
def force_not_colorized(func):
|
||||||
"""Force the terminal not to be colorized."""
|
"""Force the terminal not to be colorized."""
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
import _colorize
|
with no_color():
|
||||||
original_fn = _colorize.can_colorize
|
|
||||||
variables: dict[str, str | None] = {
|
|
||||||
"PYTHON_COLORS": None, "FORCE_COLOR": None, "NO_COLOR": None
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
for key in variables:
|
|
||||||
variables[key] = os.environ.pop(key, None)
|
|
||||||
os.environ["NO_COLOR"] = "1"
|
|
||||||
_colorize.can_colorize = lambda: False
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
finally:
|
|
||||||
_colorize.can_colorize = original_fn
|
|
||||||
del os.environ["NO_COLOR"]
|
|
||||||
for key, value in variables.items():
|
|
||||||
if value is not None:
|
|
||||||
os.environ[key] = value
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def force_not_colorized_test_class(cls):
|
||||||
|
"""Force the terminal not to be colorized for the entire test class."""
|
||||||
|
original_setUpClass = cls.setUpClass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@functools.wraps(cls.setUpClass)
|
||||||
|
def new_setUpClass(cls):
|
||||||
|
cls.enterClassContext(no_color())
|
||||||
|
original_setUpClass()
|
||||||
|
|
||||||
|
cls.setUpClass = new_setUpClass
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
def initialized_with_pyrepl():
|
def initialized_with_pyrepl():
|
||||||
"""Detect whether PyREPL was used during Python initialization."""
|
"""Detect whether PyREPL was used during Python initialization."""
|
||||||
# If the main module has a __file__ attribute it's a Python module, which means PyREPL.
|
# If the main module has a __file__ attribute it's a Python module, which means PyREPL.
|
||||||
|
|
|
@ -5,9 +5,9 @@ import unittest
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from contextlib import ExitStack
|
from contextlib import ExitStack
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
from test.support import force_not_colorized_test_class
|
||||||
from test.support import import_helper
|
from test.support import import_helper
|
||||||
|
|
||||||
|
|
||||||
code = import_helper.import_module('code')
|
code = import_helper.import_module('code')
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ class MockSys:
|
||||||
del self.sysmod.ps2
|
del self.sysmod.ps2
|
||||||
|
|
||||||
|
|
||||||
|
@force_not_colorized_test_class
|
||||||
class TestInteractiveConsole(unittest.TestCase, MockSys):
|
class TestInteractiveConsole(unittest.TestCase, MockSys):
|
||||||
maxDiff = None
|
maxDiff = None
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ from test.support import (Error, captured_output, cpython_only, ALWAYS_EQ,
|
||||||
from test.support.os_helper import TESTFN, unlink
|
from test.support.os_helper import TESTFN, unlink
|
||||||
from test.support.script_helper import assert_python_ok, assert_python_failure
|
from test.support.script_helper import assert_python_ok, assert_python_failure
|
||||||
from test.support.import_helper import forget
|
from test.support.import_helper import forget
|
||||||
from test.support import force_not_colorized
|
from test.support import force_not_colorized, force_not_colorized_test_class
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import textwrap
|
import textwrap
|
||||||
|
@ -1709,6 +1709,7 @@ class TracebackErrorLocationCaretTestBase:
|
||||||
|
|
||||||
|
|
||||||
@requires_debug_ranges()
|
@requires_debug_ranges()
|
||||||
|
@force_not_colorized_test_class
|
||||||
class PurePythonTracebackErrorCaretTests(
|
class PurePythonTracebackErrorCaretTests(
|
||||||
PurePythonExceptionFormattingMixin,
|
PurePythonExceptionFormattingMixin,
|
||||||
TracebackErrorLocationCaretTestBase,
|
TracebackErrorLocationCaretTestBase,
|
||||||
|
@ -1722,6 +1723,7 @@ class PurePythonTracebackErrorCaretTests(
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
@requires_debug_ranges()
|
@requires_debug_ranges()
|
||||||
|
@force_not_colorized_test_class
|
||||||
class CPythonTracebackErrorCaretTests(
|
class CPythonTracebackErrorCaretTests(
|
||||||
CAPIExceptionFormattingMixin,
|
CAPIExceptionFormattingMixin,
|
||||||
TracebackErrorLocationCaretTestBase,
|
TracebackErrorLocationCaretTestBase,
|
||||||
|
@ -1733,6 +1735,7 @@ class CPythonTracebackErrorCaretTests(
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
@requires_debug_ranges()
|
@requires_debug_ranges()
|
||||||
|
@force_not_colorized_test_class
|
||||||
class CPythonTracebackLegacyErrorCaretTests(
|
class CPythonTracebackLegacyErrorCaretTests(
|
||||||
CAPIExceptionFormattingLegacyMixin,
|
CAPIExceptionFormattingLegacyMixin,
|
||||||
TracebackErrorLocationCaretTestBase,
|
TracebackErrorLocationCaretTestBase,
|
||||||
|
@ -2144,10 +2147,12 @@ context_message = (
|
||||||
boundaries = re.compile(
|
boundaries = re.compile(
|
||||||
'(%s|%s)' % (re.escape(cause_message), re.escape(context_message)))
|
'(%s|%s)' % (re.escape(cause_message), re.escape(context_message)))
|
||||||
|
|
||||||
|
@force_not_colorized_test_class
|
||||||
class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
|
@force_not_colorized_test_class
|
||||||
class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin):
|
||||||
DEBUG_RANGES = False
|
DEBUG_RANGES = False
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
|
@ -2935,6 +2940,7 @@ class BaseExceptionReportingTests:
|
||||||
self.assertEqual(report, expected)
|
self.assertEqual(report, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@force_not_colorized_test_class
|
||||||
class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
|
class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
|
||||||
#
|
#
|
||||||
# This checks reporting through the 'traceback' module, with both
|
# This checks reporting through the 'traceback' module, with both
|
||||||
|
@ -2951,6 +2957,7 @@ class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
@force_not_colorized_test_class
|
||||||
class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
|
class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
|
||||||
#
|
#
|
||||||
# This checks built-in reporting by the interpreter.
|
# This checks built-in reporting by the interpreter.
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import io
|
import io
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from test.support import warnings_helper, captured_stdout
|
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.util import strclass
|
from unittest.util import strclass
|
||||||
|
from test.support import warnings_helper
|
||||||
|
from test.support import captured_stdout, force_not_colorized_test_class
|
||||||
from test.test_unittest.support import BufferedWriter
|
from test.test_unittest.support import BufferedWriter
|
||||||
|
|
||||||
|
|
||||||
|
@ -758,6 +757,7 @@ class Test_OldTestResult(unittest.TestCase):
|
||||||
runner.run(Test('testFoo'))
|
runner.run(Test('testFoo'))
|
||||||
|
|
||||||
|
|
||||||
|
@force_not_colorized_test_class
|
||||||
class TestOutputBuffering(unittest.TestCase):
|
class TestOutputBuffering(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue