blob: 26f626968034a744b5f48a6328d22acf865f1f40 [file] [log] [blame]
[email protected]4860f052011-03-25 20:34:381# coding=utf8
[email protected]4f6852c2012-04-20 20:39:202# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]4860f052011-03-25 20:34:383# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""Collection of subprocess wrapper functions.
6
7In theory you shouldn't need anything else in subprocess, or this module failed.
8"""
9
[email protected]94c712f2011-12-01 15:04:5710import cStringIO
[email protected]1d9f6292011-04-07 14:15:3611import errno
[email protected]4860f052011-03-25 20:34:3812import logging
13import os
[email protected]94c712f2011-12-01 15:04:5714import Queue
[email protected]4860f052011-03-25 20:34:3815import subprocess
16import sys
[email protected]4860f052011-03-25 20:34:3817import time
18import threading
19
[email protected]a8e81632011-12-01 00:35:2420
[email protected]4860f052011-03-25 20:34:3821# Constants forwarded from subprocess.
22PIPE = subprocess.PIPE
23STDOUT = subprocess.STDOUT
[email protected]421982f2011-04-01 17:38:0624# Sends stdout or stderr to os.devnull.
[email protected]0d5ef242011-04-18 13:52:5825VOID = object()
[email protected]1d9f6292011-04-07 14:15:3626# Error code when a process was killed because it timed out.
27TIMED_OUT = -2001
[email protected]4860f052011-03-25 20:34:3828
29# Globals.
30# Set to True if you somehow need to disable this hack.
31SUBPROCESS_CLEANUP_HACKED = False
32
33
34class CalledProcessError(subprocess.CalledProcessError):
35 """Augment the standard exception with more data."""
36 def __init__(self, returncode, cmd, cwd, stdout, stderr):
[email protected]c15fe572014-09-19 11:51:4337 super(CalledProcessError, self).__init__(returncode, cmd, output=stdout)
38 self.stdout = self.output # for backward compatibility.
[email protected]4860f052011-03-25 20:34:3839 self.stderr = stderr
40 self.cwd = cwd
41
42 def __str__(self):
[email protected]217330f2015-06-01 22:10:1443 out = 'Command %r returned non-zero exit status %s' % (
[email protected]4860f052011-03-25 20:34:3844 ' '.join(self.cmd), self.returncode)
45 if self.cwd:
46 out += ' in ' + self.cwd
47 return '\n'.join(filter(None, (out, self.stdout, self.stderr)))
48
49
[email protected]1d9f6292011-04-07 14:15:3650class CygwinRebaseError(CalledProcessError):
51 """Occurs when cygwin's fork() emulation fails due to rebased dll."""
52
53
[email protected]fb3d3242011-04-01 14:03:0854## Utility functions
55
56
57def kill_pid(pid):
58 """Kills a process by its process id."""
59 try:
60 # Unable to import 'module'
Quinten Yearsleyb2cc4a92016-12-15 21:53:2661 # pylint: disable=no-member,F0401
[email protected]fb3d3242011-04-01 14:03:0862 import signal
63 return os.kill(pid, signal.SIGKILL)
64 except ImportError:
65 pass
66
67
68def kill_win(process):
69 """Kills a process with its windows handle.
70
71 Has no effect on other platforms.
72 """
73 try:
74 # Unable to import 'module'
Quinten Yearsleyb2cc4a92016-12-15 21:53:2675 # pylint: disable=import-error
[email protected]fb3d3242011-04-01 14:03:0876 import win32process
77 # Access to a protected member _handle of a client class
Quinten Yearsleyb2cc4a92016-12-15 21:53:2678 # pylint: disable=protected-access
[email protected]fb3d3242011-04-01 14:03:0879 return win32process.TerminateProcess(process._handle, -1)
80 except ImportError:
81 pass
82
83
84def add_kill():
85 """Adds kill() method to subprocess.Popen for python <2.6"""
86 if hasattr(subprocess.Popen, 'kill'):
87 return
88
89 if sys.platform == 'win32':
90 subprocess.Popen.kill = kill_win
91 else:
92 subprocess.Popen.kill = lambda process: kill_pid(process.pid)
93
94
[email protected]4860f052011-03-25 20:34:3895def hack_subprocess():
96 """subprocess functions may throw exceptions when used in multiple threads.
97
98 See http://bugs.python.org/issue1731717 for more information.
99 """
100 global SUBPROCESS_CLEANUP_HACKED
101 if not SUBPROCESS_CLEANUP_HACKED and threading.activeCount() != 1:
102 # Only hack if there is ever multiple threads.
103 # There is no point to leak with only one thread.
104 subprocess._cleanup = lambda: None
105 SUBPROCESS_CLEANUP_HACKED = True
106
107
108def get_english_env(env):
109 """Forces LANG and/or LANGUAGE to be English.
110
111 Forces encoding to utf-8 for subprocesses.
112
113 Returns None if it is unnecessary.
114 """
[email protected]c98c0c52011-04-06 13:39:43115 if sys.platform == 'win32':
116 return None
[email protected]4860f052011-03-25 20:34:38117 env = env or os.environ
118
119 # Test if it is necessary at all.
120 is_english = lambda name: env.get(name, 'en').startswith('en')
121
122 if is_english('LANG') and is_english('LANGUAGE'):
123 return None
124
125 # Requires modifications.
126 env = env.copy()
127 def fix_lang(name):
128 if not is_english(name):
129 env[name] = 'en_US.UTF-8'
130 fix_lang('LANG')
131 fix_lang('LANGUAGE')
132 return env
133
134
[email protected]12b07e72013-05-03 22:06:34135class NagTimer(object):
136 """
137 Triggers a callback when a time interval passes without an event being fired.
138
139 For example, the event could be receiving terminal output from a subprocess;
140 and the callback could print a warning to stderr that the subprocess appeared
141 to be hung.
142 """
143 def __init__(self, interval, cb):
144 self.interval = interval
145 self.cb = cb
146 self.timer = threading.Timer(self.interval, self.fn)
147 self.last_output = self.previous_last_output = 0
148
149 def start(self):
150 self.last_output = self.previous_last_output = time.time()
151 self.timer.start()
152
153 def event(self):
154 self.last_output = time.time()
155
156 def fn(self):
157 now = time.time()
158 if self.last_output == self.previous_last_output:
159 self.cb(now - self.previous_last_output)
160 # Use 0.1 fudge factor, just in case
161 # (self.last_output - now) is very close to zero.
162 sleep_time = (self.last_output - now - 0.1) % self.interval
163 self.previous_last_output = self.last_output
164 self.timer = threading.Timer(sleep_time + 0.1, self.fn)
165 self.timer.start()
166
167 def cancel(self):
168 self.timer.cancel()
169
170
[email protected]ef77f9e2011-11-24 15:24:02171class Popen(subprocess.Popen):
[email protected]57bf78d2011-09-08 18:57:33172 """Wraps subprocess.Popen() with various workarounds.
[email protected]4860f052011-03-25 20:34:38173
[email protected]421982f2011-04-01 17:38:06174 - Forces English output since it's easier to parse the stdout if it is always
175 in English.
176 - Sets shell=True on windows by default. You can override this by forcing
177 shell parameter to a value.
178 - Adds support for VOID to not buffer when not needed.
[email protected]dd9837f2011-11-30 01:55:22179 - Adds self.start property.
[email protected]4860f052011-03-25 20:34:38180
[email protected]57bf78d2011-09-08 18:57:33181 Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate
182 exceptions generated by cygwin when it fails trying to emulate fork().
[email protected]4860f052011-03-25 20:34:38183 """
[email protected]434e7902015-09-15 09:57:01184 # subprocess.Popen.__init__() is not threadsafe; there is a race between
185 # creating the exec-error pipe for the child and setting it to CLOEXEC during
186 # which another thread can fork and cause the pipe to be inherited by its
187 # descendents, which will cause the current Popen to hang until all those
188 # descendents exit. Protect this with a lock so that only one fork/exec can
189 # happen at a time.
190 popen_lock = threading.Lock()
191
[email protected]ef77f9e2011-11-24 15:24:02192 def __init__(self, args, **kwargs):
193 # Make sure we hack subprocess if necessary.
194 hack_subprocess()
195 add_kill()
[email protected]4860f052011-03-25 20:34:38196
[email protected]ef77f9e2011-11-24 15:24:02197 env = get_english_env(kwargs.get('env'))
198 if env:
199 kwargs['env'] = env
200 if kwargs.get('shell') is None:
201 # *Sigh*: Windows needs shell=True, or else it won't search %PATH% for
202 # the executable, but shell=True makes subprocess on Linux fail when it's
203 # called with a list because it only tries to execute the first item in
204 # the list.
205 kwargs['shell'] = bool(sys.platform=='win32')
[email protected]4860f052011-03-25 20:34:38206
[email protected]ef77f9e2011-11-24 15:24:02207 if isinstance(args, basestring):
208 tmp_str = args
209 elif isinstance(args, (list, tuple)):
210 tmp_str = ' '.join(args)
211 else:
212 raise CalledProcessError(None, args, kwargs.get('cwd'), None, None)
213 if kwargs.get('cwd', None):
214 tmp_str += '; cwd=%s' % kwargs['cwd']
215 logging.debug(tmp_str)
[email protected]421982f2011-04-01 17:38:06216
[email protected]94c712f2011-12-01 15:04:57217 self.stdout_cb = None
218 self.stderr_cb = None
[email protected]740a6c02011-12-05 23:46:44219 self.stdin_is_void = False
220 self.stdout_is_void = False
221 self.stderr_is_void = False
[email protected]e0558e62013-05-02 02:48:51222 self.cmd_str = tmp_str
[email protected]740a6c02011-12-05 23:46:44223
224 if kwargs.get('stdin') is VOID:
225 kwargs['stdin'] = open(os.devnull, 'r')
226 self.stdin_is_void = True
227
228 for stream in ('stdout', 'stderr'):
[email protected]ef77f9e2011-11-24 15:24:02229 if kwargs.get(stream) in (VOID, os.devnull):
[email protected]ef77f9e2011-11-24 15:24:02230 kwargs[stream] = open(os.devnull, 'w')
[email protected]740a6c02011-12-05 23:46:44231 setattr(self, stream + '_is_void', True)
[email protected]94c712f2011-12-01 15:04:57232 if callable(kwargs.get(stream)):
[email protected]94c712f2011-12-01 15:04:57233 setattr(self, stream + '_cb', kwargs[stream])
234 kwargs[stream] = PIPE
[email protected]1d9f6292011-04-07 14:15:36235
[email protected]dd9837f2011-11-30 01:55:22236 self.start = time.time()
[email protected]94c712f2011-12-01 15:04:57237 self.timeout = None
[email protected]e0558e62013-05-02 02:48:51238 self.nag_timer = None
[email protected]12b07e72013-05-03 22:06:34239 self.nag_max = None
[email protected]a8e81632011-12-01 00:35:24240 self.shell = kwargs.get('shell', None)
[email protected]14e37ad2011-11-30 20:26:16241 # Silence pylint on MacOSX
242 self.returncode = None
[email protected]a8e81632011-12-01 00:35:24243
[email protected]ef77f9e2011-11-24 15:24:02244 try:
[email protected]434e7902015-09-15 09:57:01245 with self.popen_lock:
246 super(Popen, self).__init__(args, **kwargs)
[email protected]ef77f9e2011-11-24 15:24:02247 except OSError, e:
248 if e.errno == errno.EAGAIN and sys.platform == 'cygwin':
249 # Convert fork() emulation failure into a CygwinRebaseError().
250 raise CygwinRebaseError(
251 e.errno,
252 args,
253 kwargs.get('cwd'),
254 None,
255 'Visit '
256 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure '
257 'to learn how to fix this error; you need to rebase your cygwin '
258 'dlls')
[email protected]7f627a92014-03-28 00:57:44259 # Popen() can throw OSError when cwd or args[0] doesn't exist.
[email protected]fb653b62014-04-29 17:29:18260 raise OSError('Execution failed with error: %s.\n'
261 'Check that %s or %s exist and have execution permission.'
262 % (str(e), kwargs.get('cwd'), args[0]))
[email protected]4860f052011-03-25 20:34:38263
Quinten Yearsleyb2cc4a92016-12-15 21:53:26264 def _tee_threads(self, input): # pylint: disable=redefined-builtin
[email protected]94c712f2011-12-01 15:04:57265 """Does I/O for a process's pipes using threads.
266
267 It's the simplest and slowest implementation. Expect very slow behavior.
268
269 If there is a callback and it doesn't keep up with the calls, the timeout
270 effectiveness will be delayed accordingly.
271 """
272 # Queue of either of <threadname> when done or (<threadname>, data). In
273 # theory we would like to limit to ~64kb items to not cause large memory
274 # usage when the callback blocks. It is not done because it slows down
275 # processing on OSX10.6 by a factor of 2x, making it even slower than
276 # Windows! Revisit this decision if it becomes a problem, e.g. crash
277 # because of memory exhaustion.
278 queue = Queue.Queue()
279 done = threading.Event()
[email protected]12b07e72013-05-03 22:06:34280 nag = None
[email protected]94c712f2011-12-01 15:04:57281
282 def write_stdin():
283 try:
284 stdin_io = cStringIO.StringIO(input)
285 while True:
286 data = stdin_io.read(1024)
287 if data:
288 self.stdin.write(data)
289 else:
290 self.stdin.close()
291 break
292 finally:
293 queue.put('stdin')
294
295 def _queue_pipe_read(pipe, name):
296 """Queues characters read from a pipe into a queue."""
297 try:
298 while True:
299 data = pipe.read(1)
300 if not data:
301 break
[email protected]12b07e72013-05-03 22:06:34302 if nag:
303 nag.event()
[email protected]94c712f2011-12-01 15:04:57304 queue.put((name, data))
305 finally:
306 queue.put(name)
307
308 def timeout_fn():
309 try:
310 done.wait(self.timeout)
311 finally:
312 queue.put('timeout')
313
314 def wait_fn():
315 try:
316 self.wait()
317 finally:
318 queue.put('wait')
319
320 # Starts up to 5 threads:
321 # Wait for the process to quit
322 # Read stdout
323 # Read stderr
324 # Write stdin
325 # Timeout
326 threads = {
327 'wait': threading.Thread(target=wait_fn),
328 }
329 if self.timeout is not None:
330 threads['timeout'] = threading.Thread(target=timeout_fn)
331 if self.stdout_cb:
332 threads['stdout'] = threading.Thread(
333 target=_queue_pipe_read, args=(self.stdout, 'stdout'))
334 if self.stderr_cb:
335 threads['stderr'] = threading.Thread(
336 target=_queue_pipe_read, args=(self.stderr, 'stderr'))
337 if input:
338 threads['stdin'] = threading.Thread(target=write_stdin)
[email protected]740a6c02011-12-05 23:46:44339 elif self.stdin:
340 # Pipe but no input, make sure it's closed.
341 self.stdin.close()
[email protected]94c712f2011-12-01 15:04:57342 for t in threads.itervalues():
343 t.start()
344
[email protected]e0558e62013-05-02 02:48:51345 if self.nag_timer:
[email protected]12b07e72013-05-03 22:06:34346 def _nag_cb(elapsed):
347 logging.warn(' No output for %.0f seconds from command:' % elapsed)
348 logging.warn(' %s' % self.cmd_str)
349 if (self.nag_max and
350 int('%.0f' % (elapsed / self.nag_timer)) >= self.nag_max):
351 queue.put('timeout')
352 done.set() # Must do this so that timeout thread stops waiting.
353 nag = NagTimer(self.nag_timer, _nag_cb)
354 nag.start()
[email protected]e0558e62013-05-02 02:48:51355
[email protected]94c712f2011-12-01 15:04:57356 timed_out = False
357 try:
358 # This thread needs to be optimized for speed.
359 while threads:
360 item = queue.get()
[email protected]cd8d8e12012-10-03 17:16:25361 if item[0] == 'stdout':
[email protected]94c712f2011-12-01 15:04:57362 self.stdout_cb(item[1])
[email protected]cd8d8e12012-10-03 17:16:25363 elif item[0] == 'stderr':
[email protected]94c712f2011-12-01 15:04:57364 self.stderr_cb(item[1])
365 else:
366 # A thread terminated.
[email protected]12b07e72013-05-03 22:06:34367 if item in threads:
368 threads[item].join()
369 del threads[item]
[email protected]94c712f2011-12-01 15:04:57370 if item == 'wait':
371 # Terminate the timeout thread if necessary.
372 done.set()
373 elif item == 'timeout' and not timed_out and self.poll() is None:
[email protected]12b07e72013-05-03 22:06:34374 logging.debug('Timed out after %.0fs: killing' % (
375 time.time() - self.start))
[email protected]94c712f2011-12-01 15:04:57376 self.kill()
377 timed_out = True
378 finally:
379 # Stop the threads.
380 done.set()
[email protected]12b07e72013-05-03 22:06:34381 if nag:
382 nag.cancel()
[email protected]94c712f2011-12-01 15:04:57383 if 'wait' in threads:
384 # Accelerate things, otherwise it would hang until the child process is
385 # done.
386 logging.debug('Killing child because of an exception')
387 self.kill()
388 # Join threads.
389 for thread in threads.itervalues():
390 thread.join()
391 if timed_out:
392 self.returncode = TIMED_OUT
393
Quinten Yearsleyb2cc4a92016-12-15 21:53:26394 # pylint: disable=arguments-differ,W0622
[email protected]12b07e72013-05-03 22:06:34395 def communicate(self, input=None, timeout=None, nag_timer=None,
396 nag_max=None):
[email protected]94c712f2011-12-01 15:04:57397 """Adds timeout and callbacks support.
398
399 Returns (stdout, stderr) like subprocess.Popen().communicate().
400
401 - The process will be killed after |timeout| seconds and returncode set to
402 TIMED_OUT.
[email protected]e0558e62013-05-02 02:48:51403 - If the subprocess runs for |nag_timer| seconds without producing terminal
404 output, print a warning to stderr.
[email protected]94c712f2011-12-01 15:04:57405 """
406 self.timeout = timeout
[email protected]e0558e62013-05-02 02:48:51407 self.nag_timer = nag_timer
[email protected]12b07e72013-05-03 22:06:34408 self.nag_max = nag_max
[email protected]e0558e62013-05-02 02:48:51409 if (not self.timeout and not self.nag_timer and
410 not self.stdout_cb and not self.stderr_cb):
[email protected]94c712f2011-12-01 15:04:57411 return super(Popen, self).communicate(input)
412
413 if self.timeout and self.shell:
414 raise TypeError(
415 'Using timeout and shell simultaneously will cause a process leak '
416 'since the shell will be killed instead of the child process.')
417
418 stdout = None
419 stderr = None
420 # Convert to a lambda to workaround python's deadlock.
421 # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
[email protected]740a6c02011-12-05 23:46:44422 # When the pipe fills up, it would deadlock this process.
423 if self.stdout and not self.stdout_cb and not self.stdout_is_void:
424 stdout = []
425 self.stdout_cb = stdout.append
426 if self.stderr and not self.stderr_cb and not self.stderr_is_void:
427 stderr = []
428 self.stderr_cb = stderr.append
[email protected]94c712f2011-12-01 15:04:57429 self._tee_threads(input)
[email protected]740a6c02011-12-05 23:46:44430 if stdout is not None:
431 stdout = ''.join(stdout)
[email protected]740a6c02011-12-05 23:46:44432 if stderr is not None:
433 stderr = ''.join(stderr)
[email protected]94c712f2011-12-01 15:04:57434 return (stdout, stderr)
435
[email protected]4860f052011-03-25 20:34:38436
[email protected]12b07e72013-05-03 22:06:34437def communicate(args, timeout=None, nag_timer=None, nag_max=None, **kwargs):
[email protected]dd9837f2011-11-30 01:55:22438 """Wraps subprocess.Popen().communicate() and add timeout support.
[email protected]4860f052011-03-25 20:34:38439
[email protected]421982f2011-04-01 17:38:06440 Returns ((stdout, stderr), returncode).
[email protected]4860f052011-03-25 20:34:38441
[email protected]1d9f6292011-04-07 14:15:36442 - The process will be killed after |timeout| seconds and returncode set to
443 TIMED_OUT.
[email protected]e0558e62013-05-02 02:48:51444 - If the subprocess runs for |nag_timer| seconds without producing terminal
445 output, print a warning to stderr.
[email protected]421982f2011-04-01 17:38:06446 - Automatically passes stdin content as input so do not specify stdin=PIPE.
[email protected]4860f052011-03-25 20:34:38447 """
448 stdin = kwargs.pop('stdin', None)
449 if stdin is not None:
[email protected]740a6c02011-12-05 23:46:44450 if isinstance(stdin, basestring):
[email protected]0d5ef242011-04-18 13:52:58451 # When stdin is passed as an argument, use it as the actual input data and
452 # set the Popen() parameter accordingly.
453 kwargs['stdin'] = PIPE
[email protected]740a6c02011-12-05 23:46:44454 else:
455 kwargs['stdin'] = stdin
456 stdin = None
[email protected]4860f052011-03-25 20:34:38457
[email protected]94c712f2011-12-01 15:04:57458 proc = Popen(args, **kwargs)
[email protected]740a6c02011-12-05 23:46:44459 if stdin:
[email protected]e0558e62013-05-02 02:48:51460 return proc.communicate(stdin, timeout, nag_timer), proc.returncode
[email protected]94c712f2011-12-01 15:04:57461 else:
[email protected]e0558e62013-05-02 02:48:51462 return proc.communicate(None, timeout, nag_timer), proc.returncode
[email protected]4860f052011-03-25 20:34:38463
464
[email protected]1f063db2011-04-18 19:04:52465def call(args, **kwargs):
466 """Emulates subprocess.call().
467
468 Automatically convert stdout=PIPE or stderr=PIPE to VOID.
[email protected]87e6d332011-09-09 19:01:28469 In no case they can be returned since no code path raises
470 subprocess2.CalledProcessError.
[email protected]1f063db2011-04-18 19:04:52471 """
472 if kwargs.get('stdout') == PIPE:
473 kwargs['stdout'] = VOID
474 if kwargs.get('stderr') == PIPE:
475 kwargs['stderr'] = VOID
476 return communicate(args, **kwargs)[1]
477
478
[email protected]0bcd1d32011-04-26 15:55:49479def check_call_out(args, **kwargs):
[email protected]421982f2011-04-01 17:38:06480 """Improved version of subprocess.check_call().
[email protected]4860f052011-03-25 20:34:38481
[email protected]421982f2011-04-01 17:38:06482 Returns (stdout, stderr), unlike subprocess.check_call().
[email protected]4860f052011-03-25 20:34:38483 """
[email protected]1f063db2011-04-18 19:04:52484 out, returncode = communicate(args, **kwargs)
[email protected]4860f052011-03-25 20:34:38485 if returncode:
486 raise CalledProcessError(
487 returncode, args, kwargs.get('cwd'), out[0], out[1])
488 return out
489
490
[email protected]0bcd1d32011-04-26 15:55:49491def check_call(args, **kwargs):
492 """Emulate subprocess.check_call()."""
493 check_call_out(args, **kwargs)
494 return 0
495
496
[email protected]4860f052011-03-25 20:34:38497def capture(args, **kwargs):
498 """Captures stdout of a process call and returns it.
499
[email protected]421982f2011-04-01 17:38:06500 Returns stdout.
[email protected]4860f052011-03-25 20:34:38501
[email protected]421982f2011-04-01 17:38:06502 - Discards returncode.
[email protected]87e6d332011-09-09 19:01:28503 - Blocks stdin by default if not specified since no output will be visible.
[email protected]4860f052011-03-25 20:34:38504 """
[email protected]87e6d332011-09-09 19:01:28505 kwargs.setdefault('stdin', VOID)
506
507 # Like check_output, deny the caller from using stdout arg.
508 return communicate(args, stdout=PIPE, **kwargs)[0][0]
[email protected]4860f052011-03-25 20:34:38509
510
511def check_output(args, **kwargs):
[email protected]0bcd1d32011-04-26 15:55:49512 """Emulates subprocess.check_output().
[email protected]4860f052011-03-25 20:34:38513
[email protected]0bcd1d32011-04-26 15:55:49514 Captures stdout of a process call and returns stdout only.
[email protected]4860f052011-03-25 20:34:38515
[email protected]421982f2011-04-01 17:38:06516 - Throws if return code is not 0.
517 - Works even prior to python 2.7.
[email protected]87e6d332011-09-09 19:01:28518 - Blocks stdin by default if not specified since no output will be visible.
519 - As per doc, "The stdout argument is not allowed as it is used internally."
[email protected]4860f052011-03-25 20:34:38520 """
[email protected]87e6d332011-09-09 19:01:28521 kwargs.setdefault('stdin', VOID)
[email protected]db59bfc2011-11-30 14:03:14522 if 'stdout' in kwargs:
[email protected]022d06e2014-04-29 17:08:12523 raise ValueError('stdout argument not allowed, it would be overridden.')
[email protected]87e6d332011-09-09 19:01:28524 return check_call_out(args, stdout=PIPE, **kwargs)[0]