diff options
Diffstat (limited to 'third_party/python/cram/cram/_process.py')
-rw-r--r-- | third_party/python/cram/cram/_process.py | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/third_party/python/cram/cram/_process.py b/third_party/python/cram/cram/_process.py new file mode 100644 index 0000000000..decdfbc3a7 --- /dev/null +++ b/third_party/python/cram/cram/_process.py @@ -0,0 +1,54 @@ +"""Utilities for running subprocesses""" + +import os +import signal +import subprocess +import sys + +from cram._encoding import fsdecode + +__all__ = ['PIPE', 'STDOUT', 'execute'] + +PIPE = subprocess.PIPE +STDOUT = subprocess.STDOUT + +def _makeresetsigpipe(): + """Make a function to reset SIGPIPE to SIG_DFL (for use in subprocesses). + + Doing subprocess.Popen(..., preexec_fn=makeresetsigpipe()) will prevent + Python's SIGPIPE handler (SIG_IGN) from being inherited by the + child process. + """ + if (sys.platform == 'win32' or + getattr(signal, 'SIGPIPE', None) is None): # pragma: nocover + return None + return lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL) + +def execute(args, stdin=None, stdout=None, stderr=None, cwd=None, env=None): + """Run a process and return its output and return code. + + stdin may either be None or a string to send to the process. + + stdout may either be None or PIPE. If set to PIPE, the process's output + is returned as a string. + + stderr may either be None or STDOUT. If stdout is set to PIPE and stderr + is set to STDOUT, the process's stderr output will be interleaved with + stdout and returned as a string. + + cwd sets the process's current working directory. + + env can be set to a dictionary to override the process's environment + variables. + + This function returns a 2-tuple of (output, returncode). + """ + if sys.platform == 'win32': # pragma: nocover + args = [fsdecode(arg) for arg in args] + + p = subprocess.Popen(args, stdin=PIPE, stdout=stdout, stderr=stderr, + cwd=cwd, env=env, bufsize=-1, + preexec_fn=_makeresetsigpipe(), + close_fds=os.name == 'posix') + out, err = p.communicate(stdin) + return out, p.returncode |