From be7ba3e36f3abca7a7b7515b946ad4088d020f5d Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 11 Dec 2024 21:01:46 +0200 Subject: [PATCH 01/10] Add test class helper to force no terminal colour --- Lib/test/support/__init__.py | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 42e7b876594fa7..173b270f06a170 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -60,6 +60,7 @@ "skip_on_s390x", "without_optimizer", "force_not_colorized", + "force_not_colorized_test_class", "BrokenIter", "in_systemd_nspawn_sync_suppressed", "run_no_yield_async_fn", "run_yielding_async_fn", "async_yield", @@ -2856,6 +2857,44 @@ def wrapper(*args, **kwargs): return wrapper + +def force_not_colorized_test_class(cls): + """Force the terminal not to be colorized.""" + original_setup = cls.setUp + original_teardown = cls.tearDown + + @functools.wraps(cls.setUp) + def setUp_wrapper(self, *args, **kwargs): + import _colorize + + self._original_fn = _colorize.can_colorize + self._variables: dict[str, str | None] = { + "PYTHON_COLORS": None, + "FORCE_COLOR": None, + "NO_COLOR": None, + } + for key in self._variables: + self._variables[key] = os.environ.pop(key, None) + os.environ["NO_COLOR"] = "1" + _colorize.can_colorize = lambda: False + return original_setup(self, *args, **kwargs) + + @functools.wraps(cls.tearDown) + def tearDown_wrapper(self, *args, **kwargs): + import _colorize + + _colorize.can_colorize = self._original_fn + del os.environ["NO_COLOR"] + for key, value in self._variables.items(): + if value is not None: + os.environ[key] = value + return original_teardown(self, *args, **kwargs) + + cls.setUp = setUp_wrapper + cls.tearDown = tearDown_wrapper + return cls + + def initialized_with_pyrepl(): """Detect whether PyREPL was used during Python initialization.""" # If the main module has a __file__ attribute it's a Python module, which means PyREPL. From 08a260a1f01ee5ca0fa40e43dfb212f50a7f84f7 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 11 Dec 2024 23:33:01 +0200 Subject: [PATCH 02/10] Refactor --- Lib/test/support/__init__.py | 67 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 173b270f06a170..db29f0428a19ba 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -17,6 +17,7 @@ import types import unittest import warnings +from collections.abc import Callable __all__ = [ @@ -2833,31 +2834,45 @@ def is_slot_wrapper(name, value): yield name, True +def _disable_terminal_color() -> Callable[[], bool]: + import _colorize + + original_fn = _colorize.can_colorize + variables: dict[str, str | None] = { + "PYTHON_COLORS": None, + "FORCE_COLOR": None, + "NO_COLOR": None, + } + for key in variables: + variables[key] = os.environ.pop(key, None) + os.environ["NO_COLOR"] = "1" + _colorize.can_colorize = lambda: False + return original_fn, variables + + +def _re_enable_terminal_color( + original_fn: Callable[[], bool], variables: dict[str, str | None] +): + import _colorize + + _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 + + def force_not_colorized(func): """Force the terminal not to be colorized.""" @functools.wraps(func) def wrapper(*args, **kwargs): - import _colorize - 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 + original_fn, variables = _disable_terminal_color() 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 + _re_enable_terminal_color(original_fn, variables) return wrapper - - def force_not_colorized_test_class(cls): """Force the terminal not to be colorized.""" original_setup = cls.setUp @@ -2865,29 +2880,13 @@ def force_not_colorized_test_class(cls): @functools.wraps(cls.setUp) def setUp_wrapper(self, *args, **kwargs): - import _colorize + self._original_fn, self._variables = _disable_terminal_color() - self._original_fn = _colorize.can_colorize - self._variables: dict[str, str | None] = { - "PYTHON_COLORS": None, - "FORCE_COLOR": None, - "NO_COLOR": None, - } - for key in self._variables: - self._variables[key] = os.environ.pop(key, None) - os.environ["NO_COLOR"] = "1" - _colorize.can_colorize = lambda: False return original_setup(self, *args, **kwargs) @functools.wraps(cls.tearDown) def tearDown_wrapper(self, *args, **kwargs): - import _colorize - - _colorize.can_colorize = self._original_fn - del os.environ["NO_COLOR"] - for key, value in self._variables.items(): - if value is not None: - os.environ[key] = value + _re_enable_terminal_color(self._original_fn, self._variables) return original_teardown(self, *args, **kwargs) cls.setUp = setUp_wrapper From 591c2f57582e2fcd07f5fee0142829968061f4b1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:41:10 +0200 Subject: [PATCH 03/10] Disable colour for some tests --- Lib/test/test_code_module.py | 4 ++-- Lib/test/test_traceback.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 37c7bc772ed8c7..11dce808c9415e 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -5,8 +5,7 @@ from textwrap import dedent from contextlib import ExitStack from unittest import mock -from test.support import import_helper - +from test.support import force_not_colorized_test_class, import_helper code = import_helper.import_module('code') @@ -30,6 +29,7 @@ def mock_sys(self): del self.sysmod.ps2 +@force_not_colorized_test_class class TestInteractiveConsole(unittest.TestCase, MockSys): maxDiff = None diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 31f0a61d6a9d59..abdfc4638f2e9c 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -21,7 +21,7 @@ from test.support.os_helper import TESTFN, unlink from test.support.script_helper import assert_python_ok, assert_python_failure 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 textwrap @@ -1712,6 +1712,7 @@ def f(): @requires_debug_ranges() +@force_not_colorized_test_class class PurePythonTracebackErrorCaretTests( PurePythonExceptionFormattingMixin, TracebackErrorLocationCaretTestBase, @@ -1725,6 +1726,7 @@ class PurePythonTracebackErrorCaretTests( @cpython_only @requires_debug_ranges() +@force_not_colorized_test_class class CPythonTracebackErrorCaretTests( CAPIExceptionFormattingMixin, TracebackErrorLocationCaretTestBase, @@ -1736,6 +1738,7 @@ class CPythonTracebackErrorCaretTests( @cpython_only @requires_debug_ranges() +@force_not_colorized_test_class class CPythonTracebackLegacyErrorCaretTests( CAPIExceptionFormattingLegacyMixin, TracebackErrorLocationCaretTestBase, @@ -2149,10 +2152,12 @@ def test_print_exception_bad_type_python(self): boundaries = re.compile( '(%s|%s)' % (re.escape(cause_message), re.escape(context_message))) +@force_not_colorized_test_class class TestTracebackFormat(unittest.TestCase, TracebackFormatMixin): pass @cpython_only +@force_not_colorized_test_class class TestFallbackTracebackFormat(unittest.TestCase, TracebackFormatMixin): DEBUG_RANGES = False def setUp(self) -> None: @@ -2940,6 +2945,7 @@ def f(): self.assertEqual(report, expected) +@force_not_colorized_test_class class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # # This checks reporting through the 'traceback' module, with both @@ -2956,6 +2962,7 @@ def get_report(self, e): return s +@force_not_colorized_test_class class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # # This checks built-in reporting by the interpreter. From d1b6a9ae01a1d5318338c41c8c5caea6a5eb2bff Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:17:14 +0200 Subject: [PATCH 04/10] Detype --- Lib/test/support/__init__.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index db29f0428a19ba..a277d95decaa1e 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2834,11 +2834,11 @@ def is_slot_wrapper(name, value): yield name, True -def _disable_terminal_color() -> Callable[[], bool]: +def _disable_terminal_color(): import _colorize original_fn = _colorize.can_colorize - variables: dict[str, str | None] = { + variables = { "PYTHON_COLORS": None, "FORCE_COLOR": None, "NO_COLOR": None, @@ -2850,9 +2850,7 @@ def _disable_terminal_color() -> Callable[[], bool]: return original_fn, variables -def _re_enable_terminal_color( - original_fn: Callable[[], bool], variables: dict[str, str | None] -): +def _re_enable_terminal_color(original_fn, variables): import _colorize _colorize.can_colorize = original_fn From 8eec75a56ec76ea2fe956571e5a24b14e779a4e1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:44:27 +0200 Subject: [PATCH 05/10] Separate submodule import from other imports --- Lib/test/test_code_module.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 11dce808c9415e..20b960ce8d1e02 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -5,7 +5,8 @@ from textwrap import dedent from contextlib import ExitStack from unittest import mock -from test.support import force_not_colorized_test_class, import_helper +from test.support import force_not_colorized_test_class +from test.support import import_helper code = import_helper.import_module('code') From 966479ad1d13da624af577f07b4be26ebe936158 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:14:31 +0200 Subject: [PATCH 06/10] Detype Co-authored-by: Erlend E. Aasland --- Lib/test/support/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index a277d95decaa1e..ba0b8450e7bc02 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -17,7 +17,6 @@ import types import unittest import warnings -from collections.abc import Callable __all__ = [ From e9aa442e13aa5fc13219ce963380c3866911ae06 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:45:44 +0200 Subject: [PATCH 07/10] Use setUpClass/tearDownClass instead of setUp/tearDown --- Lib/test/support/__init__.py | 40 +++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index ba0b8450e7bc02..6092d8880e110e 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2870,24 +2870,30 @@ def wrapper(*args, **kwargs): _re_enable_terminal_color(original_fn, variables) return wrapper -def force_not_colorized_test_class(cls): - """Force the terminal not to be colorized.""" - original_setup = cls.setUp - original_teardown = cls.tearDown - - @functools.wraps(cls.setUp) - def setUp_wrapper(self, *args, **kwargs): - self._original_fn, self._variables = _disable_terminal_color() - return original_setup(self, *args, **kwargs) - - @functools.wraps(cls.tearDown) - def tearDown_wrapper(self, *args, **kwargs): - _re_enable_terminal_color(self._original_fn, self._variables) - return original_teardown(self, *args, **kwargs) - - cls.setUp = setUp_wrapper - cls.tearDown = tearDown_wrapper +def force_not_colorized_test_class(cls): + """Force the terminal not to be colorized for the entire test class.""" + original_setUpClass = cls.setUpClass + original_tearDownClass = cls.tearDownClass + + @classmethod + @functools.wraps(cls.setUpClass) + def new_setUpClass(cls): + original_fn, variables = _disable_terminal_color() + cls._original_fn = original_fn + cls._variables = variables + if original_setUpClass: + original_setUpClass() + + @classmethod + @functools.wraps(cls.tearDownClass) + def new_tearDownClass(cls): + if original_tearDownClass: + original_tearDownClass() + _re_enable_terminal_color(cls._original_fn, cls._variables) + + cls.setUpClass = new_setUpClass + cls.tearDownClass = new_tearDownClass return cls From 72260f85b52a5e6c6e6ed573771dace2640785fa Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:42:35 +0200 Subject: [PATCH 08/10] Use EnvironmentVarGuard and swap_attrs in force_not_colorized and force_not_colorized_test_class --- Lib/test/support/__init__.py | 65 +++++++++++++----------------------- 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 6092d8880e110e..4c917a8784176d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2833,67 +2833,48 @@ def is_slot_wrapper(name, value): yield name, True -def _disable_terminal_color(): - import _colorize - - original_fn = _colorize.can_colorize - variables = { - "PYTHON_COLORS": None, - "FORCE_COLOR": None, - "NO_COLOR": None, - } - for key in variables: - variables[key] = os.environ.pop(key, None) - os.environ["NO_COLOR"] = "1" - _colorize.can_colorize = lambda: False - return original_fn, variables - - -def _re_enable_terminal_color(original_fn, variables): - import _colorize - - _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 - - def force_not_colorized(func): """Force the terminal not to be colorized.""" @functools.wraps(func) def wrapper(*args, **kwargs): - try: - original_fn, variables = _disable_terminal_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") + return func(*args, **kwargs) - finally: - _re_enable_terminal_color(original_fn, variables) + 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 - original_tearDownClass = cls.tearDownClass @classmethod @functools.wraps(cls.setUpClass) def new_setUpClass(cls): - original_fn, variables = _disable_terminal_color() - cls._original_fn = original_fn - cls._variables = variables + import _colorize + from .os_helper import EnvironmentVarGuard + + cls.enterClassContext( + swap_attr(_colorize, "can_colorize", lambda: False) + ) + env = cls.enterClassContext(EnvironmentVarGuard()) + for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}: + env.unset(var) + env.set("NO_COLOR", "1") + if original_setUpClass: original_setUpClass() - @classmethod - @functools.wraps(cls.tearDownClass) - def new_tearDownClass(cls): - if original_tearDownClass: - original_tearDownClass() - _re_enable_terminal_color(cls._original_fn, cls._variables) - cls.setUpClass = new_setUpClass - cls.tearDownClass = new_tearDownClass return cls From 6daa3c33bb4171693d522e4880c305b87a400b23 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:53:42 +0200 Subject: [PATCH 09/10] Fix tests when running with FORCE_COLOR=1 --- Lib/test/test_exceptions.py | 1 + Lib/test/test_unittest/test_result.py | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 6ccfa9575f8569..206e22e791e02a 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2274,6 +2274,7 @@ def test_range_of_offsets(self): self.assertIn(expected, err.getvalue()) the_exception = exc + @force_not_colorized def test_subclass(self): class MySyntaxError(SyntaxError): pass diff --git a/Lib/test/test_unittest/test_result.py b/Lib/test/test_unittest/test_result.py index 746b9fa2677717..ad6f52d7e0260e 100644 --- a/Lib/test/test_unittest/test_result.py +++ b/Lib/test/test_unittest/test_result.py @@ -1,13 +1,15 @@ import io import sys import textwrap - -from test.support import warnings_helper, captured_stdout - import traceback import unittest from unittest.util import strclass -from test.support import force_not_colorized +from test.support import warnings_helper +from test.support import ( + captured_stdout, + force_not_colorized, + force_not_colorized_test_class, +) from test.test_unittest.support import BufferedWriter @@ -772,6 +774,7 @@ def testFoo(self): runner.run(Test('testFoo')) +@force_not_colorized_test_class class TestOutputBuffering(unittest.TestCase): def setUp(self): From 0554e911e3078dbb389f20f52059bf74e79163fd Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:46:00 +0200 Subject: [PATCH 10/10] Refactor --- Lib/test/support/__init__.py | 43 +++++++++++++++--------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 4c917a8784176d..ee9520a8838625 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2833,23 +2833,27 @@ def is_slot_wrapper(name, value): 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): """Force the terminal not to be colorized.""" @functools.wraps(func) def wrapper(*args, **kwargs): - 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") - + with no_color(): return func(*args, **kwargs) - return wrapper @@ -2860,19 +2864,8 @@ def force_not_colorized_test_class(cls): @classmethod @functools.wraps(cls.setUpClass) def new_setUpClass(cls): - import _colorize - from .os_helper import EnvironmentVarGuard - - cls.enterClassContext( - swap_attr(_colorize, "can_colorize", lambda: False) - ) - env = cls.enterClassContext(EnvironmentVarGuard()) - for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}: - env.unset(var) - env.set("NO_COLOR", "1") - - if original_setUpClass: - original_setUpClass() + cls.enterClassContext(no_color()) + original_setUpClass() cls.setUpClass = new_setUpClass return cls pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy