https://github.com/python/cpython/commit/383af395af828f40d9543ee0a8fdc5cc011d43db
commit: 383af395af828f40d9543ee0a8fdc5cc011d43db
branch: 3.13
author: Hugo van Kemenade <[email protected]>
committer: hugovk <[email protected]>
date: 2025-01-21T18:14:24+02:00
summary:

[3.13] gh-128595: Default to stdout isatty for colour detection instead of 
stderr (GH-128498) (#129057)

Co-authored-by: Hugo van Kemenade <[email protected]>
Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
Fix `test__colorize` unexpected keyword argument 'file' on buildbots (#129070)

files:
A Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst
M Lib/_colorize.py
M Lib/doctest.py
M Lib/test/support/__init__.py
M Lib/test/test__colorize.py
M Lib/traceback.py

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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to