https://github.com/python/cpython/commit/a0cbdd84afd7526a2cb31bfc606170cca492e32e
commit: a0cbdd84afd7526a2cb31bfc606170cca492e32e
branch: 3.13
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2025-11-19T14:28:31Z
summary:

[3.13] gh-141570: can_colorize: Expect fileno() to raise OSError, as documented 
(#141716) (#141748)

gh-141570: can_colorize: Expect fileno() to raise OSError, as documented 
(#141716)

In Fedora, we've been given a slightly incomplete reproducer for a problematic
Python 3.14 color-related change in argparse that leads to an exception when
Python is used from mod_wsgi: https://bugzilla.redhat.com/2414940

mod_wsgi replaces sys.stdout with a custom object that raises OSError on 
.fileno():

https://github.com/GrahamDumpleton/mod_wsgi/blob/8460dbfcd5c7108892b3cde9fab7cbc1caa27886/src/server/wsgi_logger.c#L434-L440

This should be supported, as the documentation of fileno explicitly says:

> An OSError is raised if the IO object does not use a file descriptor.

https://docs.python.org/3.14/library/io.html#io.IOBase.fileno

The previously expected exception inherits from OSError,
so it is still expected.

Fixes https://github.com/python/cpython/issues/141570



(cherry picked from commit 96f496a949b05054d0d043c3085f00cec2f83bf5)

Co-authored-by: Miro HronĨok <[email protected]>
Co-authored-by: Cody Maloney <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-11-18-14-39-31.gh-issue-141570.q3n984.rst
M Lib/_colorize.py
M Lib/test/test__colorize.py

diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index 0688ea00aa5bff..8263d2df6ecd99 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -1,5 +1,4 @@
 from __future__ import annotations
-import io
 import os
 import sys
 
@@ -116,5 +115,5 @@ def _safe_getenv(k: str, fallback: str | None = None) -> 
str | None:
 
     try:
         return os.isatty(file.fileno())
-    except io.UnsupportedOperation:
+    except OSError:
         return hasattr(file, "isatty") and file.isatty()
diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py
index b2f0bb1386fe5b..5c3743677534d4 100644
--- a/Lib/test/test__colorize.py
+++ b/Lib/test/test__colorize.py
@@ -129,6 +129,17 @@ def test_colorized_detection_checks_for_file(self):
                 file.isatty.return_value = False
                 self.assertEqual(_colorize.can_colorize(file=file), False)
 
+            # The documentation for file.fileno says:
+            # > An OSError is raised if the IO object does not use a file 
descriptor.
+            # gh-141570: Check OSError is caught and handled
+            with unittest.mock.patch("os.isatty", 
side_effect=ZeroDivisionError):
+                file = unittest.mock.MagicMock()
+                file.fileno.side_effect = OSError
+                file.isatty.return_value = True
+                self.assertEqual(_colorize.can_colorize(file=file), True)
+                file.isatty.return_value = False
+                self.assertEqual(_colorize.can_colorize(file=file), False)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Library/2025-11-18-14-39-31.gh-issue-141570.q3n984.rst 
b/Misc/NEWS.d/next/Library/2025-11-18-14-39-31.gh-issue-141570.q3n984.rst
new file mode 100644
index 00000000000000..8f4641ce4cf8c2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-18-14-39-31.gh-issue-141570.q3n984.rst
@@ -0,0 +1,2 @@
+Support :term:`file-like object` raising :exc:`OSError` from 
:meth:`~io.IOBase.fileno` in color
+detection (``_colorize.can_colorize()``). This can occur when ``sys.stdout`` 
is redirected.

_______________________________________________
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