summaryrefslogtreecommitdiff
path: root/vendor/Twisted-10.0.0/twisted/internet/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/Twisted-10.0.0/twisted/internet/utils.py')
-rw-r--r--vendor/Twisted-10.0.0/twisted/internet/utils.py219
1 files changed, 219 insertions, 0 deletions
diff --git a/vendor/Twisted-10.0.0/twisted/internet/utils.py b/vendor/Twisted-10.0.0/twisted/internet/utils.py
new file mode 100644
index 0000000000..0a781489d3
--- /dev/null
+++ b/vendor/Twisted-10.0.0/twisted/internet/utils.py
@@ -0,0 +1,219 @@
+# -*- test-case-name: twisted.test.test_iutils -*-
+# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Utility methods.
+"""
+
+import sys, warnings
+
+from twisted.internet import protocol, defer
+from twisted.python import failure, util as tputil
+
+try:
+ import cStringIO as StringIO
+except ImportError:
+ import StringIO
+
+def _callProtocolWithDeferred(protocol, executable, args, env, path, reactor=None):
+ if reactor is None:
+ from twisted.internet import reactor
+
+ d = defer.Deferred()
+ p = protocol(d)
+ reactor.spawnProcess(p, executable, (executable,)+tuple(args), env, path)
+ return d
+
+
+
+class _UnexpectedErrorOutput(IOError):
+ """
+ Standard error data was received where it was not expected. This is a
+ subclass of L{IOError} to preserve backward compatibility with the previous
+ error behavior of L{getProcessOutput}.
+
+ @ivar processEnded: A L{Deferred} which will fire when the process which
+ produced the data on stderr has ended (exited and all file descriptors
+ closed).
+ """
+ def __init__(self, text, processEnded):
+ IOError.__init__(self, "got stderr: %r" % (text,))
+ self.processEnded = processEnded
+
+
+
+class _BackRelay(protocol.ProcessProtocol):
+ """
+ Trivial protocol for communicating with a process and turning its output
+ into the result of a L{Deferred}.
+
+ @ivar deferred: A L{Deferred} which will be called back with all of stdout
+ and, if C{errortoo} is true, all of stderr as well (mixed together in
+ one string). If C{errortoo} is false and any bytes are received over
+ stderr, this will fire with an L{_UnexpectedErrorOutput} instance and
+ the attribute will be set to C{None}.
+
+ @ivar onProcessEnded: If C{errortoo} is false and bytes are received over
+ stderr, this attribute will refer to a L{Deferred} which will be called
+ back when the process ends. This C{Deferred} is also associated with
+ the L{_UnexpectedErrorOutput} which C{deferred} fires with earlier in
+ this case so that users can determine when the process has actually
+ ended, in addition to knowing when bytes have been received via stderr.
+ """
+
+ def __init__(self, deferred, errortoo=0):
+ self.deferred = deferred
+ self.s = StringIO.StringIO()
+ if errortoo:
+ self.errReceived = self.errReceivedIsGood
+ else:
+ self.errReceived = self.errReceivedIsBad
+
+ def errReceivedIsBad(self, text):
+ if self.deferred is not None:
+ self.onProcessEnded = defer.Deferred()
+ err = _UnexpectedErrorOutput(text, self.onProcessEnded)
+ self.deferred.errback(failure.Failure(err))
+ self.deferred = None
+ self.transport.loseConnection()
+
+ def errReceivedIsGood(self, text):
+ self.s.write(text)
+
+ def outReceived(self, text):
+ self.s.write(text)
+
+ def processEnded(self, reason):
+ if self.deferred is not None:
+ self.deferred.callback(self.s.getvalue())
+ elif self.onProcessEnded is not None:
+ self.onProcessEnded.errback(reason)
+
+
+
+def getProcessOutput(executable, args=(), env={}, path=None, reactor=None,
+ errortoo=0):
+ """
+ Spawn a process and return its output as a deferred returning a string.
+
+ @param executable: The file name to run and get the output of - the
+ full path should be used.
+
+ @param args: the command line arguments to pass to the process; a
+ sequence of strings. The first string should *NOT* be the
+ executable's name.
+
+ @param env: the environment variables to pass to the processs; a
+ dictionary of strings.
+
+ @param path: the path to run the subprocess in - defaults to the
+ current directory.
+
+ @param reactor: the reactor to use - defaults to the default reactor
+
+ @param errortoo: If true, include stderr in the result. If false, if
+ stderr is received the returned L{Deferred} will errback with an
+ L{IOError} instance with a C{processEnded} attribute. The
+ C{processEnded} attribute refers to a L{Deferred} which fires when the
+ executed process ends.
+ """
+ return _callProtocolWithDeferred(lambda d:
+ _BackRelay(d, errortoo=errortoo),
+ executable, args, env, path,
+ reactor)
+
+
+class _ValueGetter(protocol.ProcessProtocol):
+
+ def __init__(self, deferred):
+ self.deferred = deferred
+
+ def processEnded(self, reason):
+ self.deferred.callback(reason.value.exitCode)
+
+
+def getProcessValue(executable, args=(), env={}, path=None, reactor=None):
+ """Spawn a process and return its exit code as a Deferred."""
+ return _callProtocolWithDeferred(_ValueGetter, executable, args, env, path,
+ reactor)
+
+
+class _EverythingGetter(protocol.ProcessProtocol):
+
+ def __init__(self, deferred):
+ self.deferred = deferred
+ self.outBuf = StringIO.StringIO()
+ self.errBuf = StringIO.StringIO()
+ self.outReceived = self.outBuf.write
+ self.errReceived = self.errBuf.write
+
+ def processEnded(self, reason):
+ out = self.outBuf.getvalue()
+ err = self.errBuf.getvalue()
+ e = reason.value
+ code = e.exitCode
+ if e.signal:
+ self.deferred.errback((out, err, e.signal))
+ else:
+ self.deferred.callback((out, err, code))
+
+def getProcessOutputAndValue(executable, args=(), env={}, path=None,
+ reactor=None):
+ """Spawn a process and returns a Deferred that will be called back with
+ its output (from stdout and stderr) and it's exit code as (out, err, code)
+ If a signal is raised, the Deferred will errback with the stdout and
+ stderr up to that point, along with the signal, as (out, err, signalNum)
+ """
+ return _callProtocolWithDeferred(_EverythingGetter, executable, args, env, path,
+ reactor)
+
+def _resetWarningFilters(passthrough, addedFilters):
+ for f in addedFilters:
+ try:
+ warnings.filters.remove(f)
+ except ValueError:
+ pass
+ return passthrough
+
+
+def runWithWarningsSuppressed(suppressedWarnings, f, *a, **kw):
+ """Run the function C{f}, but with some warnings suppressed.
+
+ @param suppressedWarnings: A list of arguments to pass to filterwarnings.
+ Must be a sequence of 2-tuples (args, kwargs).
+ @param f: A callable, followed by its arguments and keyword arguments
+ """
+ for args, kwargs in suppressedWarnings:
+ warnings.filterwarnings(*args, **kwargs)
+ addedFilters = warnings.filters[:len(suppressedWarnings)]
+ try:
+ result = f(*a, **kw)
+ except:
+ exc_info = sys.exc_info()
+ _resetWarningFilters(None, addedFilters)
+ raise exc_info[0], exc_info[1], exc_info[2]
+ else:
+ if isinstance(result, defer.Deferred):
+ result.addBoth(_resetWarningFilters, addedFilters)
+ else:
+ _resetWarningFilters(None, addedFilters)
+ return result
+
+
+def suppressWarnings(f, *suppressedWarnings):
+ """
+ Wrap C{f} in a callable which suppresses the indicated warnings before
+ invoking C{f} and unsuppresses them afterwards. If f returns a Deferred,
+ warnings will remain suppressed until the Deferred fires.
+ """
+ def warningSuppressingWrapper(*a, **kw):
+ return runWithWarningsSuppressed(suppressedWarnings, f, *a, **kw)
+ return tputil.mergeFunctionMetadata(f, warningSuppressingWrapper)
+
+
+__all__ = [
+ "runWithWarningsSuppressed", "suppressWarnings",
+
+ "getProcessOutput", "getProcessValue", "getProcessOutputAndValue",
+ ]