Skip to content

Commit 39ee553

Browse files
committed
Make sure replaced streams have fileno.
This is important for example for subprocess that will peak at the filedescriptor.
1 parent e63c018 commit 39ee553

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

ipykernel/iostream.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,16 @@ class OutStream(TextIOBase):
286286
topic = None
287287
encoding = 'UTF-8'
288288

289+
290+
def fileno(self):
291+
"""
292+
Things like subprocess will peak and write to the fileno() of stderr/stdout.
293+
"""
294+
if getattr(self, '_original_stdstream_copy', None) is not None:
295+
return self._original_stdstream_copy
296+
else:
297+
raise UnsupportedOperation('fileno')
298+
289299
def _watch_pipe_fd(self):
290300
"""
291301
We've redirected standards steams 0 and 1 into a pipe.

ipykernel/kernelapp.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ def init_io(self):
419419
sys.stderr = outstream_factory(
420420
self.session, self.iopub_thread, "stderr", echo=e_stderr
421421
)
422-
self.log.error("this %s", hasattr(sys.stderr, "_original_stdstream_copy"))
423422
if hasattr(sys.stderr, "_original_stdstream_copy"):
424423

425424
for handler in self.log.handlers:
@@ -433,7 +432,6 @@ def init_io(self):
433432
handler.stream = TextIOWrapper(
434433
FileIO(sys.stderr._original_stdstream_copy, "w")
435434
)
436-
self.log.error("Redirected to raw FD.")
437435
if self.displayhook_class:
438436
displayhook_factory = import_item(str(self.displayhook_class))
439437
self.displayhook = displayhook_factory(self.session, self.iopub_socket)

ipykernel/tests/test_kernel.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_simple_print():
4545
"""simple print statement in kernel"""
4646
with kernel() as kc:
4747
iopub = kc.iopub_channel
48-
msg_id, content = execute(kc=kc, code="print ('hi')")
48+
msg_id, content = execute(kc=kc, code="print('hi')")
4949
stdout, stderr = assemble_output(iopub)
5050
assert stdout == 'hi\n'
5151
assert stderr == ''
@@ -63,6 +63,19 @@ def test_capture_fd():
6363
_check_master(kc, expected=True)
6464

6565

66+
@pytest.mark.skipif(sys.platform=='win32', reason='Not meant to work on windows')
67+
def test_subprocess_peek_at_stream_fileno():
68+
""""""
69+
with kernel() as kc:
70+
iopub = kc.iopub_channel
71+
msg_id, content = execute(kc=kc, code="import subprocess, sys; subprocess.run(['python', '-c', 'import os; os.system(\"echo CAP1\"); print(\"CAP2\")'], stderr=sys.stderr)")
72+
stdout, stderr = assemble_output(iopub)
73+
assert stdout == 'CAP1\nCAP2\n'
74+
assert stderr == ''
75+
_check_master(kc, expected=True)
76+
77+
78+
6679

6780
def test_sys_path():
6881
"""test that sys.path doesn't get messed up by default"""

0 commit comments

Comments
 (0)