Skip to content

Commit ca2bae2

Browse files
committed
Implement fileno method on stdout and stderr
1 parent bdaad24 commit ca2bae2

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

Lib/_android_support.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ def init_streams(android_log_write, stdout_prio, stderr_prio):
3131
logcat = Logcat(android_log_write)
3232

3333
sys.stdout = TextLogStream(
34-
stdout_prio, "python.stdout", errors=sys.stdout.errors)
34+
stdout_prio, "python.stdout", sys.stdout.fileno(),
35+
errors=sys.stdout.errors)
3536
sys.stderr = TextLogStream(
36-
stderr_prio, "python.stderr", errors=sys.stderr.errors)
37+
stderr_prio, "python.stderr", sys.stderr.fileno(),
38+
errors=sys.stderr.errors)
3739

3840

3941
class TextLogStream(io.TextIOWrapper):
40-
def __init__(self, prio, tag, **kwargs):
42+
def __init__(self, prio, tag, fileno=None, **kwargs):
4143
kwargs.setdefault("encoding", "UTF-8")
42-
super().__init__(BinaryLogStream(prio, tag), **kwargs)
44+
super().__init__(BinaryLogStream(prio, tag, fileno), **kwargs)
4345
self._lock = RLock()
4446
self._pending_bytes = []
4547
self._pending_bytes_count = 0
@@ -98,9 +100,10 @@ def line_buffering(self):
98100

99101

100102
class BinaryLogStream(io.RawIOBase):
101-
def __init__(self, prio, tag):
103+
def __init__(self, prio, tag, fileno=None):
102104
self.prio = prio
103105
self.tag = tag
106+
self._fileno = fileno
104107

105108
def __repr__(self):
106109
return f"<BinaryLogStream {self.tag!r}>"
@@ -122,6 +125,12 @@ def write(self, b):
122125
logcat.write(self.prio, self.tag, b)
123126
return len(b)
124127

128+
# This is needed by the test suite --timeout option, which uses faulthandler.
129+
def fileno(self):
130+
if self._fileno is None:
131+
raise io.UnsupportedOperation("fileno")
132+
return self._fileno
133+
125134

126135
# When a large volume of data is written to logcat at once, e.g. when a test
127136
# module fails in --verbose3 mode, there's a risk of overflowing logcat's own

Lib/test/test_android.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
api_level = platform.android_ver().api_level
2121

22+
# (name, level, fileno)
23+
STREAM_INFO = [("stdout", "I", 1), ("stderr", "W", 2)]
24+
2225

2326
# Test redirection of stdout and stderr to the Android log.
2427
@unittest.skipIf(
@@ -94,26 +97,29 @@ def stream_context(self, stream_name, level):
9497
stack = ExitStack()
9598
stack.enter_context(self.subTest(stream_name))
9699
stream = getattr(sys, stream_name)
100+
native_stream = getattr(sys, f"__{stream_name}__")
97101
if isinstance(stream, io.StringIO):
98102
stack.enter_context(
99103
patch(
100104
f"sys.{stream_name}",
101105
TextLogStream(
102-
prio, f"python.{stream_name}", errors="backslashreplace"
106+
prio, f"python.{stream_name}", native_stream.fileno(),
107+
errors="backslashreplace"
103108
),
104109
)
105110
)
106111
return stack
107112

108113
def test_str(self):
109-
for stream_name, level in [("stdout", "I"), ("stderr", "W")]:
114+
for stream_name, level, fileno in STREAM_INFO:
110115
with self.stream_context(stream_name, level):
111116
stream = getattr(sys, stream_name)
112117
tag = f"python.{stream_name}"
113118
self.assertEqual(f"<TextLogStream '{tag}'>", repr(stream))
114119

115120
self.assertIs(stream.writable(), True)
116121
self.assertIs(stream.readable(), False)
122+
self.assertEqual(stream.fileno(), fileno)
117123
self.assertEqual("UTF-8", stream.encoding)
118124
self.assertIs(stream.line_buffering, True)
119125
self.assertIs(stream.write_through, False)
@@ -257,13 +263,14 @@ def __str__(self):
257263
write("\n", [s * 51]) # 0 bytes in, 510 bytes out
258264

259265
def test_bytes(self):
260-
for stream_name, level in [("stdout", "I"), ("stderr", "W")]:
266+
for stream_name, level, fileno in STREAM_INFO:
261267
with self.stream_context(stream_name, level):
262268
stream = getattr(sys, stream_name).buffer
263269
tag = f"python.{stream_name}"
264270
self.assertEqual(f"<BinaryLogStream '{tag}'>", repr(stream))
265271
self.assertIs(stream.writable(), True)
266272
self.assertIs(stream.readable(), False)
273+
self.assertEqual(stream.fileno(), fileno)
267274

268275
def write(b, lines=None, *, write_len=None):
269276
if write_len is None:

0 commit comments

Comments
 (0)