Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4e1b8d3

Browse files
committed
Short in the dark windows issue
1 parent 89d672e commit 4e1b8d3

2 files changed

Lines changed: 36 additions & 17 deletions

File tree

IPython/utils/_process_common.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
import shlex
1919
import sys
2020
import os
21-
21+
from typing import Callable, Optional, Union, List
2222
from IPython.utils import py3compat
2323

2424
#-----------------------------------------------------------------------------
2525
# Function definitions
2626
#-----------------------------------------------------------------------------
2727

28-
def read_no_interrupt(p):
28+
def read_no_interrupt(p: subprocess.Popen):
2929
"""Read from a pipe ignoring EINTR errors.
3030
3131
This is necessary because when reading from pipes with GUI event loops
@@ -40,7 +40,7 @@ def read_no_interrupt(p):
4040
raise
4141

4242

43-
def process_handler(cmd, callback, stderr=subprocess.PIPE):
43+
def process_handler(cmd:Union[str, List[str]], callback:Callable[[subprocess.Popen], int], stderr=subprocess.PIPE) -> Optional[int]:
4444
"""Open a command in a shell subprocess and execute a callback.
4545
4646
This function provides common scaffolding for creating subprocess.Popen()
@@ -67,7 +67,10 @@ def process_handler(cmd, callback, stderr=subprocess.PIPE):
6767
sys.stdout.flush()
6868
sys.stderr.flush()
6969
# On win32, close_fds can't be true when using pipes for stdin/out/err
70-
close_fds = sys.platform != 'win32'
70+
if sys.platform == "win32" and stderr != subprocess.PIPE:
71+
close_fds = False
72+
else:
73+
close_fds = True
7174
# Determine if cmd should be run with system shell.
7275
shell = isinstance(cmd, str)
7376
# On POSIX systems run shell commands with user-preferred shell.

IPython/utils/_process_win32.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from ctypes.wintypes import LPCWSTR, HLOCAL
2525
from subprocess import STDOUT, TimeoutExpired
2626
from threading import Thread
27+
import subprocess
2728

2829
# our own imports
2930
from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
@@ -34,7 +35,7 @@
3435
# Function definitions
3536
#-----------------------------------------------------------------------------
3637

37-
class AvoidUNCPath(object):
38+
class AvoidUNCPath:
3839
"""A context manager to protect command execution from UNC paths.
3940
4041
In the Win32 API, commands can't be invoked with the cwd being a UNC path.
@@ -71,35 +72,50 @@ def __exit__(self, exc_type, exc_value, traceback):
7172
os.chdir(self.path)
7273

7374

74-
def _system_body(p):
75+
def _system_body(p: subprocess.Popen) -> int:
7576
"""Callback for _system."""
7677
enc = DEFAULT_ENCODING
7778

7879
def stdout_read():
79-
for line in read_no_interrupt(p.stdout).splitlines():
80-
line = line.decode(enc, 'replace')
81-
print(line, file=sys.stdout)
80+
try:
81+
for line in read_no_interrupt(p.stdout).splitlines():
82+
line = line.decode(enc, 'replace')
83+
print(line, file=sys.stdout)
84+
except Exception as e:
85+
print(f"Error reading stdout: {e}", file=sys.stderr)
8286

8387
def stderr_read():
84-
for line in read_no_interrupt(p.stderr).splitlines():
85-
line = line.decode(enc, 'replace')
86-
print(line, file=sys.stderr)
88+
try:
89+
for line in read_no_interrupt(p.stderr).splitlines():
90+
line = line.decode(enc, 'replace')
91+
print(line, file=sys.stderr)
92+
except Exception as e:
93+
print(f"Error reading stderr: {e}", file=sys.stderr)
8794

88-
Thread(target=stdout_read).start()
89-
Thread(target=stderr_read).start()
95+
stdout_thread = Thread(target=stdout_read)
96+
stderr_thread = Thread(target=stderr_read)
97+
98+
stdout_thread.start()
99+
stderr_thread.start()
90100

91101
# Wait to finish for returncode. Unfortunately, Python has a bug where
92102
# wait() isn't interruptible (https://bugs.python.org/issue28168) so poll in
93-
# a loop instead of just doing `return p.wait()`.
103+
# a loop instead of just doing `return p.wait()`
94104
while True:
95105
result = p.poll()
96106
if result is None:
97107
time.sleep(0.01)
98108
else:
99-
return result
109+
break
110+
111+
# Join the threads to ensure they complete before returning
112+
stdout_thread.join()
113+
stderr_thread.join()
114+
115+
return result
100116

101117

102-
def system(cmd):
118+
def system(cmd: str):
103119
"""Win32 version of os.system() that works with network shares.
104120
105121
Note that this implementation returns None, as meant for use in IPython.

0 commit comments

Comments
 (0)