1818import shlex
1919import subprocess
2020import sys
21- from typing import IO , Any , List , Union
21+ from typing import IO , List , TypeVar , Union
2222from collections .abc import Callable
2323
24+ _T = TypeVar ("_T" )
25+
2426from IPython .utils import py3compat
2527
2628#-----------------------------------------------------------------------------
2729# Function definitions
2830#-----------------------------------------------------------------------------
2931
30- def read_no_interrupt (stream : IO [Any ]) -> bytes :
32+ def read_no_interrupt (stream : IO [bytes ]) -> bytes | None :
3133 """Read from a pipe ignoring EINTR errors.
3234
3335 This is necessary because when reading from pipes with GUI event loops
@@ -40,13 +42,14 @@ def read_no_interrupt(stream: IO[Any]) -> bytes:
4042 except IOError as err :
4143 if err .errno != errno .EINTR :
4244 raise
45+ return None
4346
4447
4548def process_handler (
4649 cmd : Union [str , List [str ]],
47- callback : Callable [[subprocess .Popen ], int | str | bytes ],
48- stderr = subprocess .PIPE ,
49- ) -> int | str | bytes :
50+ callback : Callable [[subprocess .Popen [ bytes ]], _T ],
51+ stderr : int = subprocess .PIPE ,
52+ ) -> _T | None :
5053 """Open a command in a shell subprocess and execute a callback.
5154
5255 This function provides common scaffolding for creating subprocess.Popen()
@@ -118,7 +121,7 @@ def process_handler(
118121 return out
119122
120123
121- def getoutput (cmd ) :
124+ def getoutput (cmd : str | list [ str ]) -> str :
122125 """Run a command and return its stdout/stderr as a string.
123126
124127 Parameters
@@ -137,11 +140,10 @@ def getoutput(cmd):
137140 out = process_handler (cmd , lambda p : p .communicate ()[0 ], subprocess .STDOUT )
138141 if out is None :
139142 return ''
140- assert isinstance (out , bytes )
141143 return py3compat .decode (out )
142144
143145
144- def getoutputerror (cmd ) :
146+ def getoutputerror (cmd : str | list [ str ]) -> tuple [ str , str ] :
145147 """Return (standard output, standard error) of executing cmd in a shell.
146148
147149 Accepts the same arguments as os.system().
@@ -158,7 +160,8 @@ def getoutputerror(cmd):
158160 """
159161 return get_output_error_code (cmd )[:2 ]
160162
161- def get_output_error_code (cmd ):
163+
164+ def get_output_error_code (cmd : str | list [str ]) -> tuple [str , str , int | None ]:
162165 """Return (standard output, standard error, return code) of executing cmd
163166 in a shell.
164167
@@ -176,13 +179,13 @@ def get_output_error_code(cmd):
176179 returncode: int
177180 """
178181
179- out_err , p = process_handler (cmd , lambda p : (p .communicate (), p ))
180- if out_err is None :
181- return '' , '' , p . returncode
182- out , err = out_err
182+ result = process_handler (cmd , lambda p : (p .communicate (), p ))
183+ if result is None :
184+ return '' , '' , None
185+ ( out , err ), p = result
183186 return py3compat .decode (out ), py3compat .decode (err ), p .returncode
184187
185- def arg_split (s , posix = False , strict = True ):
188+ def arg_split (commandline : str , posix : bool = False , strict : bool = True ) -> list [ str ] :
186189 """Split a command line's arguments in a shell-like manner.
187190
188191 This is a modified version of the standard library's shlex.split()
@@ -195,7 +198,7 @@ def arg_split(s, posix=False, strict=True):
195198 command-line args.
196199 """
197200
198- lex = shlex .shlex (s , posix = posix )
201+ lex = shlex .shlex (commandline , posix = posix )
199202 lex .whitespace_split = True
200203 # Extract tokens, ensuring that things like leaving open quotes
201204 # does not cause this to raise. This is important, because we
0 commit comments