https://github.com/python/cpython/commit/05d12eecbde1ace39826320cadf8e673d70... commit: 05d12eecbde1ace39826320cadf8e673d709b229 branch: main author: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> committer: hugovk <1324225+hugovk@users.noreply.github.com> date: 2025-01-21T16:10:08Z summary: gh-127873: Only check `sys.flags.ignore_environment` for `PYTHON*` env vars (#127877) files: A Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst M .github/CODEOWNERS M Lib/_colorize.py M Lib/test/support/__init__.py M Lib/test/test__colorize.py M Lib/test/test_capi/test_misc.py M Lib/test/test_cmd_line_script.py M Lib/test/test_compileall.py M Lib/test/test_eof.py M Lib/test/test_exceptions.py M Lib/test/test_import/__init__.py M Lib/test/test_inspect/test_inspect.py M Lib/test/test_pyrepl/support.py M Lib/test/test_pyrepl/test_pyrepl.py M Lib/test/test_regrtest.py M Lib/test/test_repl.py M Lib/test/test_runpy.py M Lib/test/test_tracemalloc.py M Lib/test/test_unicodedata.py M Lib/test/test_unittest/test_program.py M Lib/test/test_unittest/test_result.py M Lib/test/test_unittest/test_runner.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 76b61e700b5f72..0add48e777866c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -304,3 +304,7 @@ Lib/test/test_configparser.py @jaraco Doc/reference/ @willingc @AA-Turner **/*weakref* @kumaraditya303 + +# Colorize +Lib/_colorize.py @hugovk +Lib/test/test__colorize.py @hugovk diff --git a/Lib/_colorize.py b/Lib/_colorize.py index bab2e599b2c810..5e36e45734a5fb 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -42,15 +42,14 @@ def can_colorize(*, file=None) -> bool: return False if os.environ.get("PYTHON_COLORS") == "1": return True - if "NO_COLOR" in os.environ: - return False + if "NO_COLOR" in os.environ: + return False if not COLORIZE: return False - if not sys.flags.ignore_environment: - if "FORCE_COLOR" in os.environ: - return True - if os.environ.get("TERM") == "dumb": - return False + if "FORCE_COLOR" in os.environ: + return True + if os.environ.get("TERM") == "dumb": + return False if not hasattr(file, "fileno"): return False diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 084b2411e799f4..89f2a6b916bfc2 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -61,6 +61,7 @@ "without_optimizer", "force_not_colorized", "force_not_colorized_test_class", + "make_clean_env", "BrokenIter", "in_systemd_nspawn_sync_suppressed", "run_no_yield_async_fn", "run_yielding_async_fn", "async_yield", @@ -2871,6 +2872,16 @@ def new_setUpClass(cls): return cls +def make_clean_env() -> dict[str, str]: + clean_env = os.environ.copy() + for k in clean_env.copy(): + if k.startswith("PYTHON"): + clean_env.pop(k) + clean_env.pop("FORCE_COLOR", None) + clean_env.pop("NO_COLOR", None) + return clean_env + + 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. diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py index 77e74fa3e23c2c..25519ba7e92e1f 100644 --- a/Lib/test/test__colorize.py +++ b/Lib/test/test__colorize.py @@ -3,7 +3,7 @@ import unittest import unittest.mock import _colorize -from test.support import force_not_colorized +from test.support import force_not_colorized, make_clean_env ORIGINAL_CAN_COLORIZE = _colorize.can_colorize @@ -17,6 +17,14 @@ def tearDownModule(): class TestColorizeFunction(unittest.TestCase): + def setUp(self): + # Remove PYTHON* environment variables to isolate from local user + # settings and simulate running with `-E`. Such variables should be + # added to test methods later to patched os.environ. + patcher = unittest.mock.patch("os.environ", new=make_clean_env()) + self.addCleanup(patcher.stop) + patcher.start() + @force_not_colorized def test_colorized_detection_checks_for_environment_variables(self): flags = unittest.mock.MagicMock(ignore_environment=False) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 31a4a224ec8f88..114e7cdfd0cd9c 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -75,8 +75,11 @@ class InstanceMethod: id = _testcapi.instancemethod(id) testfunction = _testcapi.instancemethod(testfunction) + CURRENT_THREAD_REGEX = r'Current thread.*:\n' if not support.Py_GIL_DISABLED else r'Stack .*:\n' + +@support.force_not_colorized_test_class class CAPITest(unittest.TestCase): def test_instancemethod(self): diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 527d51857fc904..e7f3e46c1868f7 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -88,6 +88,8 @@ def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, importlib.invalidate_caches() return to_return + +@support.force_not_colorized_test_class class CmdLineTest(unittest.TestCase): def _check_output(self, script_name, exit_code, data, expected_file, expected_argv0, diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 3a34c6822bc079..a580a240d9f474 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -766,6 +766,7 @@ def test_d_compile_error(self): rc, out, err = self.assertRunNotOK('-q', '-d', 'dinsdale', self.pkgdir) self.assertRegex(out, b'File "dinsdale') + @support.force_not_colorized def test_d_runtime_error(self): bazfn = script_helper.make_script(self.pkgdir, 'baz', 'raise Exception') self.assertRunOK('-q', '-d', 'dinsdale', self.pkgdir) diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py index e377383450e19d..582e5b6de6e687 100644 --- a/Lib/test/test_eof.py +++ b/Lib/test/test_eof.py @@ -2,7 +2,7 @@ import sys from codecs import BOM_UTF8 -from test import support +from test.support import force_not_colorized from test.support import os_helper from test.support import script_helper from test.support import warnings_helper @@ -44,6 +44,7 @@ def test_EOFS(self): self.assertEqual(cm.exception.text, "ä = '''thîs is ") self.assertEqual(cm.exception.offset, 5) + @force_not_colorized def test_EOFS_with_file(self): expect = ("(<string>, line 1)") with os_helper.temp_dir() as temp_dir: @@ -123,6 +124,7 @@ def test_line_continuation_EOF(self): self.assertEqual(str(cm.exception), expect) @unittest.skipIf(not sys.executable, "sys.executable required") + @force_not_colorized def test_line_continuation_EOF_from_file_bpo2180(self): """Ensure tok_nextc() does not add too many ending newlines.""" with os_helper.temp_dir() as temp_dir: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 206e22e791e02a..2d324827451b54 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1465,6 +1465,7 @@ def gen(): @cpython_only @unittest.skipIf(_testcapi is None, "requires _testcapi") + @force_not_colorized def test_recursion_normalizing_infinite_exception(self): # Issue #30697. Test that a RecursionError is raised when # maximum recursion depth has been exceeded when creating @@ -2180,6 +2181,7 @@ def test_multiline_not_highlighted(self): self.assertEqual(result[-len(expected):], expected) +@support.force_not_colorized_test_class class SyntaxErrorTests(unittest.TestCase): maxDiff = None diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 654b9f5bd7ab50..207b7ae7517450 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -29,9 +29,21 @@ from test.support import os_helper from test.support import ( - STDLIB_DIR, swap_attr, swap_item, cpython_only, is_apple_mobile, is_emscripten, - is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS, - requires_gil_enabled, Py_GIL_DISABLED, no_rerun) + STDLIB_DIR, + swap_attr, + swap_item, + cpython_only, + is_apple_mobile, + is_emscripten, + is_wasi, + run_in_subinterp, + run_in_subinterp_with_config, + Py_TRACE_REFS, + requires_gil_enabled, + Py_GIL_DISABLED, + no_rerun, + force_not_colorized_test_class, +) from test.support.import_helper import ( forget, make_legacy_pyc, unlink, unload, ready_to_import, DirsOnSysPath, CleanImport, import_module) @@ -333,6 +345,7 @@ def _from_subinterp(cls, name, interpid, pipe, script_kwargs): return cls.parse(text.decode()) +@force_not_colorized_test_class class ImportTests(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 6457bc523de460..8e47df21cfef2e 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -886,6 +886,7 @@ def test_getsource_stdlib_decimal(self): self.assertEqual(src.splitlines(True), lines) class TestGetsourceInteractive(unittest.TestCase): + @support.force_not_colorized def test_getclasses_interactive(self): # bpo-44648: simulate a REPL session; # there is no `__file__` in the __main__ module diff --git a/Lib/test/test_pyrepl/support.py b/Lib/test/test_pyrepl/support.py index 672d4896c92283..45e3bf758f17de 100644 --- a/Lib/test/test_pyrepl/support.py +++ b/Lib/test/test_pyrepl/support.py @@ -101,16 +101,6 @@ def handle_all_events( ) -def make_clean_env() -> dict[str, str]: - clean_env = os.environ.copy() - for k in clean_env.copy(): - if k.startswith("PYTHON"): - clean_env.pop(k) - clean_env.pop("FORCE_COLOR", None) - clean_env.pop("NO_COLOR", None) - return clean_env - - class FakeConsole(Console): def __init__(self, events, encoding="utf-8") -> None: self.events = iter(events) diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index f29a7ffbd7cafd..bbe19612437a1d 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -10,7 +10,7 @@ import tempfile from unittest import TestCase, skipUnless, skipIf from unittest.mock import patch -from test.support import force_not_colorized +from test.support import force_not_colorized, make_clean_env from test.support import SHORT_TIMEOUT from test.support.import_helper import import_module from test.support.os_helper import unlink @@ -23,7 +23,6 @@ multiline_input, code_to_events, clean_screen, - make_clean_env, ) from _pyrepl.console import Event from _pyrepl.readline import (ReadlineAlikeReader, ReadlineConfig, diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 5707b355e94337..e9ef830c848aad 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -792,6 +792,7 @@ def test_finds_expected_number_of_tests(self): f'{", ".join(output.splitlines())}') +@support.force_not_colorized_test_class class ProgramsTestCase(BaseTestCase): """ Test various ways to run the Python test suite. Use options close @@ -905,6 +906,7 @@ def test_pcbuild_rt(self): self.run_batch(script, *rt_args, *self.regrtest_args, *self.tests) +@support.force_not_colorized_test_class class ArgsTestCase(BaseTestCase): """ Test arguments of the Python test suite. diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index e764e60560db23..356ff5b198d637 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -70,6 +70,7 @@ def run_on_interactive_mode(source): return output +@support.force_not_colorized_test_class class TestInteractiveInterpreter(unittest.TestCase): @cpython_only @@ -273,6 +274,8 @@ def test_asyncio_repl_is_ok(self): self.assertEqual(exit_code, 0, "".join(output)) + +@support.force_not_colorized_test_class class TestInteractiveModeSyntaxErrors(unittest.TestCase): def test_interactive_syntax_error_correct_line(self): diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index b64383f6546f31..ada78ec8e6b0c7 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -12,8 +12,14 @@ import textwrap import unittest import warnings -from test.support import (infinite_recursion, no_tracing, verbose, - requires_subprocess, requires_resource) +from test.support import ( + force_not_colorized_test_class, + infinite_recursion, + no_tracing, + requires_resource, + requires_subprocess, + verbose, +) from test.support.import_helper import forget, make_legacy_pyc, unload from test.support.os_helper import create_empty_file, temp_dir, FakePath from test.support.script_helper import make_script, make_zip_script @@ -758,6 +764,7 @@ def test_encoding(self): self.assertEqual(result['s'], "non-ASCII: h\xe9") +@force_not_colorized_test_class class TestExit(unittest.TestCase): STATUS_CONTROL_C_EXIT = 0xC000013A EXPECTED_CODE = ( diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index a848363fcd1de9..238ae14b388c76 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -981,6 +981,7 @@ def check_sys_xoptions_invalid(self, nframe): return self.fail(f"unexpected output: {stderr!a}") + @force_not_colorized def test_sys_xoptions_invalid(self): for nframe in INVALID_NFRAME: with self.subTest(nframe=nframe): diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index c7d09a6b460c19..0285f0d51f2365 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -11,8 +11,14 @@ import sys import unicodedata import unittest -from test.support import (open_urlresource, requires_resource, script_helper, - cpython_only, check_disallow_instantiation) +from test.support import ( + open_urlresource, + requires_resource, + script_helper, + cpython_only, + check_disallow_instantiation, + force_not_colorized, +) class UnicodeMethodsTest(unittest.TestCase): @@ -277,6 +283,7 @@ def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) check_disallow_instantiation(self, unicodedata.UCD) + @force_not_colorized def test_failed_import_during_compiling(self): # Issue 4367 # Decoding \N escapes requires the unicodedata module. If it can't be diff --git a/Lib/test/test_unittest/test_program.py b/Lib/test/test_unittest/test_program.py index 58d0cef9708c95..6092ed292d8f60 100644 --- a/Lib/test/test_unittest/test_program.py +++ b/Lib/test/test_unittest/test_program.py @@ -4,10 +4,10 @@ from test import support import unittest import test.test_unittest -from test.support import force_not_colorized from test.test_unittest.test_result import BufferedWriter +@support.force_not_colorized_test_class class Test_TestProgram(unittest.TestCase): def test_discovery_from_dotted_path(self): @@ -121,7 +121,6 @@ def run(self, test): self.assertEqual(['test.test_unittest', 'test.test_unittest2'], program.testNames) - @force_not_colorized def test_NonExit(self): stream = BufferedWriter() program = unittest.main(exit=False, @@ -137,7 +136,6 @@ def test_NonExit(self): 'expected failures=1, unexpected successes=1)\n') self.assertEndsWith(out, expected) - @force_not_colorized def test_Exit(self): stream = BufferedWriter() with self.assertRaises(SystemExit) as cm: @@ -155,7 +153,6 @@ def test_Exit(self): 'expected failures=1, unexpected successes=1)\n') self.assertEndsWith(out, expected) - @force_not_colorized def test_ExitAsDefault(self): stream = BufferedWriter() with self.assertRaises(SystemExit): @@ -171,7 +168,6 @@ def test_ExitAsDefault(self): 'expected failures=1, unexpected successes=1)\n') self.assertEndsWith(out, expected) - @force_not_colorized def test_ExitSkippedSuite(self): stream = BufferedWriter() with self.assertRaises(SystemExit) as cm: @@ -184,7 +180,6 @@ def test_ExitSkippedSuite(self): expected = '\n\nOK (skipped=1)\n' self.assertEndsWith(out, expected) - @force_not_colorized def test_ExitEmptySuite(self): stream = BufferedWriter() with self.assertRaises(SystemExit) as cm: diff --git a/Lib/test/test_unittest/test_result.py b/Lib/test/test_unittest/test_result.py index 327b246452bedf..9ac4c52449c2ff 100644 --- a/Lib/test/test_unittest/test_result.py +++ b/Lib/test/test_unittest/test_result.py @@ -5,11 +5,7 @@ import unittest from unittest.util import strclass from test.support import warnings_helper -from test.support import ( - captured_stdout, - force_not_colorized, - force_not_colorized_test_class, -) +from test.support import captured_stdout, force_not_colorized_test_class from test.test_unittest.support import BufferedWriter @@ -37,6 +33,7 @@ def bad_cleanup2(): raise ValueError('bad cleanup2') +@force_not_colorized_test_class class Test_TestResult(unittest.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -208,7 +205,6 @@ def test_1(self): self.assertIs(test_case, test) self.assertIsInstance(formatted_exc, str) - @force_not_colorized def test_addFailure_filter_traceback_frames(self): class Foo(unittest.TestCase): def test_1(self): @@ -235,7 +231,6 @@ def get_exc_info(): self.assertEqual(len(dropped), 1) self.assertIn("raise self.failureException(msg)", dropped[0]) - @force_not_colorized def test_addFailure_filter_traceback_frames_context(self): class Foo(unittest.TestCase): def test_1(self): @@ -265,7 +260,6 @@ def get_exc_info(): self.assertEqual(len(dropped), 1) self.assertIn("raise self.failureException(msg)", dropped[0]) - @force_not_colorized def test_addFailure_filter_traceback_frames_chained_exception_self_loop(self): class Foo(unittest.TestCase): def test_1(self): @@ -291,7 +285,6 @@ def get_exc_info(): formatted_exc = result.failures[0][1] self.assertEqual(formatted_exc.count("Exception: Loop\n"), 1) - @force_not_colorized def test_addFailure_filter_traceback_frames_chained_exception_cycle(self): class Foo(unittest.TestCase): def test_1(self): @@ -453,7 +446,6 @@ def testFailFast(self): result.addUnexpectedSuccess(None) self.assertTrue(result.shouldStop) - @force_not_colorized def testFailFastSetByRunner(self): stream = BufferedWriter() runner = unittest.TextTestRunner(stream=stream, failfast=True) @@ -465,6 +457,7 @@ def test(result): self.assertEndsWith(stream.getvalue(), '\n\nOK\n') +@force_not_colorized_test_class class Test_TextTestResult(unittest.TestCase): maxDiff = None @@ -627,7 +620,6 @@ def _run_test(self, test_name, verbosity, tearDownError=None): test.run(result) return stream.getvalue() - @force_not_colorized def testDotsOutput(self): self.assertEqual(self._run_test('testSuccess', 1), '.') self.assertEqual(self._run_test('testSkip', 1), 's') @@ -636,7 +628,6 @@ def testDotsOutput(self): self.assertEqual(self._run_test('testExpectedFailure', 1), 'x') self.assertEqual(self._run_test('testUnexpectedSuccess', 1), 'u') - @force_not_colorized def testLongOutput(self): classname = f'{__name__}.{self.Test.__qualname__}' self.assertEqual(self._run_test('testSuccess', 2), @@ -652,21 +643,17 @@ def testLongOutput(self): self.assertEqual(self._run_test('testUnexpectedSuccess', 2), f'testUnexpectedSuccess ({classname}.testUnexpectedSuccess) ... unexpected success\n') - @force_not_colorized def testDotsOutputSubTestSuccess(self): self.assertEqual(self._run_test('testSubTestSuccess', 1), '.') - @force_not_colorized def testLongOutputSubTestSuccess(self): classname = f'{__name__}.{self.Test.__qualname__}' self.assertEqual(self._run_test('testSubTestSuccess', 2), f'testSubTestSuccess ({classname}.testSubTestSuccess) ... ok\n') - @force_not_colorized def testDotsOutputSubTestMixed(self): self.assertEqual(self._run_test('testSubTestMixed', 1), 'sFE') - @force_not_colorized def testLongOutputSubTestMixed(self): classname = f'{__name__}.{self.Test.__qualname__}' self.assertEqual(self._run_test('testSubTestMixed', 2), @@ -675,7 +662,6 @@ def testLongOutputSubTestMixed(self): f' testSubTestMixed ({classname}.testSubTestMixed) [fail] (c=3) ... FAIL\n' f' testSubTestMixed ({classname}.testSubTestMixed) [error] (d=4) ... ERROR\n') - @force_not_colorized def testDotsOutputTearDownFail(self): out = self._run_test('testSuccess', 1, AssertionError('fail')) self.assertEqual(out, 'F') @@ -686,7 +672,6 @@ def testDotsOutputTearDownFail(self): out = self._run_test('testSkip', 1, AssertionError('fail')) self.assertEqual(out, 'sF') - @force_not_colorized def testLongOutputTearDownFail(self): classname = f'{__name__}.{self.Test.__qualname__}' out = self._run_test('testSuccess', 2, AssertionError('fail')) diff --git a/Lib/test/test_unittest/test_runner.py b/Lib/test/test_unittest/test_runner.py index 1131cd73128866..4d3cfd60b8d9c3 100644 --- a/Lib/test/test_unittest/test_runner.py +++ b/Lib/test/test_unittest/test_runner.py @@ -4,7 +4,6 @@ import pickle import subprocess from test import support -from test.support import force_not_colorized import unittest from unittest.case import _Outcome @@ -107,7 +106,7 @@ def cleanup2(*args, **kwargs): self.assertTrue(test.doCleanups()) self.assertEqual(cleanups, [(2, (), {}), (1, (1, 2, 3), dict(four='hello', five='goodbye'))]) - @force_not_colorized + @support.force_not_colorized def testCleanUpWithErrors(self): class TestableTest(unittest.TestCase): def testNothing(self): @@ -251,6 +250,7 @@ def testNothing(self): self.assertEqual(test._cleanups, []) +@support.force_not_colorized_test_class class TestClassCleanup(unittest.TestCase): def test_addClassCleanUp(self): class TestableTest(unittest.TestCase): @@ -418,7 +418,6 @@ def cleanup2(): self.assertIsInstance(e2[1], CustomError) self.assertEqual(str(e2[1]), 'cleanup1') - @force_not_colorized def test_with_errors_addCleanUp(self): ordering = [] class TestableTest(unittest.TestCase): @@ -442,7 +441,6 @@ def tearDownClass(cls): ['setUpClass', 'setUp', 'cleanup_exc', 'tearDownClass', 'cleanup_good']) - @force_not_colorized def test_run_with_errors_addClassCleanUp(self): ordering = [] class TestableTest(unittest.TestCase): @@ -466,7 +464,6 @@ def tearDownClass(cls): ['setUpClass', 'setUp', 'test', 'cleanup_good', 'tearDownClass', 'cleanup_exc']) - @force_not_colorized def test_with_errors_in_addClassCleanup_and_setUps(self): ordering = [] class_blow_up = False @@ -519,7 +516,6 @@ def tearDownClass(cls): ['setUpClass', 'setUp', 'tearDownClass', 'cleanup_exc']) - @force_not_colorized def test_with_errors_in_tearDownClass(self): ordering = [] class TestableTest(unittest.TestCase): @@ -596,7 +592,6 @@ def test(self): 'inner setup', 'inner test', 'inner cleanup', 'end outer test', 'outer cleanup']) - @force_not_colorized def test_run_empty_suite_error_message(self): class EmptyTest(unittest.TestCase): pass @@ -608,6 +603,7 @@ class EmptyTest(unittest.TestCase): self.assertIn("\nNO TESTS RAN\n", runner.stream.getvalue()) +@support.force_not_colorized_test_class class TestModuleCleanUp(unittest.TestCase): def test_add_and_do_ModuleCleanup(self): module_cleanups = [] @@ -670,7 +666,6 @@ class Module(object): self.assertEqual(cleanups, [((1, 2), {'function': 'hello'})]) - @force_not_colorized def test_run_module_cleanUp(self): blowUp = True ordering = [] @@ -810,7 +805,6 @@ def tearDownClass(cls): 'tearDownClass', 'cleanup_good']) self.assertEqual(unittest.case._module_cleanups, []) - @force_not_colorized def test_run_module_cleanUp_when_teardown_exception(self): ordering = [] class Module(object): @@ -972,7 +966,6 @@ def testNothing(self): self.assertEqual(cleanups, [((1, 2), {'function': 3, 'self': 4})]) - @force_not_colorized def test_with_errors_in_addClassCleanup(self): ordering = [] @@ -1006,7 +999,6 @@ def tearDownClass(cls): ['setUpModule', 'setUpClass', 'test', 'tearDownClass', 'cleanup_exc', 'tearDownModule', 'cleanup_good']) - @force_not_colorized def test_with_errors_in_addCleanup(self): ordering = [] class Module(object): @@ -1037,7 +1029,6 @@ def tearDown(self): ['setUpModule', 'setUp', 'test', 'tearDown', 'cleanup_exc', 'tearDownModule', 'cleanup_good']) - @force_not_colorized def test_with_errors_in_addModuleCleanup_and_setUps(self): ordering = [] module_blow_up = False @@ -1330,7 +1321,7 @@ def MockResultClass(*args): expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY) self.assertEqual(runner._makeResult(), expectedresult) - @force_not_colorized + @support.force_not_colorized @support.requires_subprocess() def test_warnings(self): """ diff --git a/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst b/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst new file mode 100644 index 00000000000000..d7575c7efb6e88 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst @@ -0,0 +1,3 @@ +When ``-E`` is set, only ignore ``PYTHON_COLORS`` and not +``FORCE_COLOR``/``NO_COLOR``/``TERM`` when colourising output. +Patch by Hugo van Kemenade.