diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 25eab7fdf14..fb9de2eb2bb 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -447,6 +447,20 @@ def name(self): """Ensure that file.name is a string.""" return repr(self.buffer) + @property + def mode(self): + """ + Present a text-like mode to callers. + + The underlying buffer is opened in binary mode (e.g., 'rb+', 'wb+') + during fd-level capturing. Some libraries (e.g., youtube-dl) inspect + file.mode to decide whether to write bytes or text. Since EncodedFile + expects text on Python 3, report a mode without the binary flag. + """ + m = getattr(self.buffer, "mode", "") + return m.replace("b", "") + + def __getattr__(self, name): return getattr(object.__getattribute__(self, "buffer"), name) diff --git a/testing/test_capture.py b/testing/test_capture.py index 5d80eb63da0..eda56618797 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1194,6 +1194,14 @@ class TestStdCaptureFD(TestStdCapture): pytestmark = needsosdup captureclass = staticmethod(StdCaptureFD) + def test_stdout_mode(self): + with self.getcapture(): + assert hasattr(sys.stdout, "buffer") + # underlying buffer is binary + assert "b" in sys.stdout.buffer.mode + # EncodedFile.mode should not include "b" + assert "b" not in sys.stdout.mode + def test_simple_only_fd(self, testdir): testdir.makepyfile( """