summaryrefslogtreecommitdiffstats
path: root/third_party/python/cram/cram/_process.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/cram/cram/_process.py')
-rw-r--r--third_party/python/cram/cram/_process.py54
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