diff --git a/Lib/_colorize.py b/Lib/_colorize.py index 709081e25ec59b..daecf5b16c1965 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -24,14 +24,17 @@ class ANSIColors: 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 @@ -47,7 +50,7 @@ def can_colorize() -> bool: 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": @@ -60,6 +63,6 @@ def can_colorize() -> bool: return False try: - return os.isatty(sys.stderr.fileno()) + return os.isatty(file.fileno()) except io.UnsupportedOperation: - return sys.stderr.isatty() + return file.isatty() diff --git a/Lib/doctest.py b/Lib/doctest.py index c531e3ca6a3d5e..dd4d62a210a902 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1558,7 +1558,7 @@ def out(s): 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) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 1e711ef32bc796..e6a8ef1ddcc14d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2700,7 +2700,7 @@ def no_color(): 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"}: diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py index 1871775fa205a2..77e74fa3e23c2c 100644 --- a/Lib/test/test__colorize.py +++ b/Lib/test/test__colorize.py @@ -9,7 +9,7 @@ def setUpModule(): - _colorize.can_colorize = lambda: False + _colorize.can_colorize = lambda *args, **kwargs: False def tearDownModule(): @@ -21,6 +21,7 @@ class TestColorizeFunction(unittest.TestCase): def test_colorized_detection_checks_for_environment_variables(self): flags = unittest.mock.MagicMock(ignore_environment=False) with (unittest.mock.patch("os.isatty") as isatty_mock, + unittest.mock.patch("sys.stdout") as stdout_mock, unittest.mock.patch("sys.stderr") as stderr_mock, unittest.mock.patch("sys.flags", flags), unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE), @@ -29,6 +30,8 @@ def test_colorized_detection_checks_for_environment_variables(self): contextlib.nullcontext()) as vt_mock): isatty_mock.return_value = True + stdout_mock.fileno.return_value = 1 + stdout_mock.isatty.return_value = True stderr_mock.fileno.return_value = 2 stderr_mock.isatty.return_value = True with unittest.mock.patch("os.environ", {'TERM': 'dumb'}): @@ -61,6 +64,7 @@ def test_colorized_detection_checks_for_environment_variables(self): self.assertEqual(_colorize.can_colorize(), True) isatty_mock.return_value = False + stdout_mock.isatty.return_value = False stderr_mock.isatty.return_value = False self.assertEqual(_colorize.can_colorize(), False) diff --git a/Lib/traceback.py b/Lib/traceback.py index f73149271b9bc9..947c3e82b8c004 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -135,7 +135,7 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \ 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) diff --git a/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst b/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst new file mode 100644 index 00000000000000..9a241e37c20a44 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst @@ -0,0 +1,2 @@ +Default to stdout isatty for color detection instead of stderr. Patch by +Hugo van Kemenade.