https://github.com/python/cpython/commit/96f496a949b05054d0d043c3085f00cec2f83bf5 commit: 96f496a949b05054d0d043c3085f00cec2f83bf5 branch: main author: Miro HronĨok <[email protected]> committer: vstinner <[email protected]> date: 2025-11-19T15:02:52+01:00 summary:
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 Co-authored-by: Cody Maloney <[email protected]> Co-authored-by: Victor Stinner <[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 57b712bc068d4e..7d573274328826 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -1,4 +1,3 @@ -import io import os import sys @@ -330,7 +329,7 @@ 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 25012466840f18..67e0595943d356 100644 --- a/Lib/test/test__colorize.py +++ b/Lib/test/test__colorize.py @@ -166,6 +166,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]
