1313import os
1414import subprocess
1515import sys
16- from typing import Optional , Protocol , Union
16+ from typing import (
17+ IO ,
18+ Any ,
19+ Callable ,
20+ Iterable ,
21+ Mapping ,
22+ Optional ,
23+ Protocol ,
24+ Sequence ,
25+ Union ,
26+ )
27+
28+ from typing_extensions import TypeAlias
1729
1830from .. import exc
1931from ..types import StrOrBytesPath
@@ -143,28 +155,65 @@ def __call__(self, output: Union[str, bytes], timestamp: datetime.datetime):
143155 ...
144156
145157
158+ if sys .platform == "win32" :
159+ _ENV : TypeAlias = Mapping [str , str ]
160+ else :
161+ _ENV : TypeAlias = Union [
162+ Mapping [bytes , StrOrBytesPath ], Mapping [str , StrOrBytesPath ]
163+ ]
164+
165+ _CMD = Union [StrOrBytesPath , Sequence [StrOrBytesPath ]]
166+ _FILE : TypeAlias = Optional [Union [int , IO [Any ]]]
167+
168+
146169def run (
147- cmd : Union [str , list [str ]],
170+ args : _CMD ,
171+ bufsize : int = - 1 ,
172+ executable : Optional [StrOrBytesPath ] = None ,
173+ stdin : Optional [_FILE ] = None ,
174+ stdout : Optional [_FILE ] = None ,
175+ stderr : Optional [_FILE ] = None ,
176+ preexec_fn : Optional [Callable [[], Any ]] = None ,
177+ close_fds : bool = True ,
148178 shell : bool = False ,
149179 cwd : Optional [StrOrBytesPath ] = None ,
180+ env : Optional [_ENV ] = None ,
181+ universal_newlines : Optional [bool ] = None ,
182+ startupinfo : Optional [Any ] = None ,
183+ creationflags : int = 0 ,
184+ restore_signals : bool = True ,
185+ start_new_session : bool = False ,
186+ pass_fds : Any = (),
187+ * ,
188+ text : Optional [bool ] = None ,
189+ encoding : Optional [str ] = None ,
190+ errors : Optional [str ] = None ,
191+ user : Optional [Union [str , int ]] = None ,
192+ group : Optional [Union [str , int ]] = None ,
193+ extra_groups : Optional [Iterable [Union [str , int ]]] = None ,
194+ umask : int = - 1 ,
195+ # Not until sys.version_info >= (3, 10)
196+ # pipesize: int = -1,
197+ # custom
150198 log_in_real_time : bool = True ,
151199 check_returncode : bool = True ,
152200 callback : Optional [ProgressCallbackProtocol ] = None ,
153201):
154- """Run 'cmd' in a shell and return the combined contents of stdout and
155- stderr (Blocking). Throws an exception if the command exits non-zero.
202+ """Run 'args' in a shell and return the combined contents of stdout and
203+ stderr (Blocking). Throws an exception if the command exits non-zero.
204+
205+ Keyword arguments are passthrough to {class}`subprocess.Popen`.
156206
157207 Parameters
158208 ----------
159- cmd : list or str, or single str, if shell=True
209+ args : list or str, or single str, if shell=True
160210 the command to run
161211
162212 shell : boolean
163213 boolean indicating whether we are using advanced shell
164214 features. Use only when absolutely necessary, since this allows a lot
165215 more freedom which could be exploited by malicious code. See the
166- warning here:
167- http://docs.python.org/library/subprocess.html#popen-constructor
216+ warning here: http://docs.python.org/library/subprocess.html#popen-constructor
168217
169218 cwd : str
170219 dir command is run from. Defaults to ``path``.
@@ -187,11 +236,30 @@ def progress_cb(output, timestamp):
187236 run(['git', 'pull'], callback=progress_cb)
188237 """
189238 proc = subprocess .Popen (
190- cmd ,
239+ args ,
240+ bufsize = bufsize ,
241+ executable = executable ,
242+ stdin = stdin ,
243+ stdout = stdout or subprocess .PIPE ,
244+ stderr = stderr or subprocess .PIPE ,
245+ preexec_fn = preexec_fn ,
246+ close_fds = close_fds ,
191247 shell = shell ,
192- stderr = subprocess .PIPE ,
193- stdout = subprocess .PIPE ,
194248 cwd = cwd ,
249+ env = env ,
250+ universal_newlines = universal_newlines ,
251+ startupinfo = startupinfo ,
252+ creationflags = creationflags ,
253+ restore_signals = restore_signals ,
254+ start_new_session = start_new_session ,
255+ pass_fds = pass_fds ,
256+ text = text ,
257+ encoding = encoding ,
258+ errors = errors ,
259+ user = user ,
260+ group = group ,
261+ extra_groups = extra_groups ,
262+ umask = umask ,
195263 )
196264
197265 all_output = []
@@ -216,5 +284,5 @@ def progress_cb(output, timestamp):
216284 all_output = console_to_str (b"" .join (stderr_lines ))
217285 output = "" .join (all_output )
218286 if code != 0 and check_returncode :
219- raise exc .CommandError (output = output , returncode = code , cmd = cmd )
287+ raise exc .CommandError (output = output , returncode = code , cmd = args )
220288 return output
0 commit comments