Skip to content

Commit 49a5c57

Browse files
committed
can_colorize: Expect fileno() to raise OSError, as documented
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 #141570
1 parent b87613f commit 49a5c57

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

Lib/_colorize.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import io
21
import os
32
import sys
43

@@ -330,7 +329,7 @@ def _safe_getenv(k: str, fallback: str | None = None) -> str | None:
330329

331330
try:
332331
return os.isatty(file.fileno())
333-
except io.UnsupportedOperation:
332+
except OSError:
334333
return hasattr(file, "isatty") and file.isatty()
335334

336335

Lib/test/test__colorize.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,17 @@ def test_colorized_detection_checks_for_file(self):
166166
file.isatty.return_value = False
167167
self.assertEqual(_colorize.can_colorize(file=file), False)
168168

169+
# The documentation for file.fileno says:
170+
# > An OSError is raised if the IO object does not use a file descriptor.
171+
# See https://github.com/python/cpython/issues/141570
172+
with unittest.mock.patch("os.isatty", side_effect=ZeroDivisionError):
173+
file = unittest.mock.MagicMock()
174+
file.fileno.side_effect = OSError
175+
file.isatty.return_value = True
176+
self.assertEqual(_colorize.can_colorize(file=file), True)
177+
file.isatty.return_value = False
178+
self.assertEqual(_colorize.can_colorize(file=file), False)
179+
169180

170181
if __name__ == "__main__":
171182
unittest.main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
In :func:`_colorize.can_colorize`, support file objects rising
2+
:exc:`OSError` from the :meth:`~io.IOBase.fileno` method, as docuemtned. An
3+
example of such an object is a ``mod_wsgi`` logger.

0 commit comments

Comments
 (0)