]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Add raise_error behavior to Subprocess.wait_for_exit.
authorBen Darnell <ben@bendarnell.com>
Sat, 18 Apr 2015 18:12:44 +0000 (14:12 -0400)
committerBen Darnell <ben@bendarnell.com>
Sat, 18 Apr 2015 18:14:08 +0000 (14:14 -0400)
Closes #1205.

tornado/process.py
tornado/test/process_test.py

index fb9254fc0314cbf7c0b2d8f2378435c9728b8a5f..f580e19253340ac892f502043ad7bf4cacdbfd0a 100644 (file)
@@ -49,6 +49,10 @@ except NameError:
     long = int  # py3
 
 
+# Re-export this exception for convenience.
+CalledProcessError = subprocess.CalledProcessError
+
+
 def cpu_count():
     """Returns the number of processors on this machine."""
     if multiprocessing is None:
@@ -259,7 +263,7 @@ class Subprocess(object):
         Subprocess._waiting[self.pid] = self
         Subprocess._try_cleanup_process(self.pid)
 
-    def wait_for_exit(self):
+    def wait_for_exit(self, raise_error=True):
         """Returns a `.Future` which resolves when the process exits.
 
         Usage::
@@ -269,10 +273,21 @@ class Subprocess(object):
         This is a coroutine-friendly alternative to `set_exit_callback`
         (and a replacement for the blocking `subprocess.Popen.wait`).
 
+        By default, raises `subprocess.CalledProcessError` if the process
+        has a non-zero exit status. Use ``wait_for_exit(raise_error=False)``
+        to suppress this behavior and return the exit status without raising.
+
         .. versionadded:: 4.2
         """
         future = Future()
-        self.set_exit_callback(future.set_result)
+
+        def callback(ret):
+            if ret != 0 and raise_error:
+                # Unfortunately we don't have the original args any more.
+                future.set_exception(CalledProcessError(ret, None))
+            else:
+                future.set_result(ret)
+        self.set_exit_callback(callback)
         return future
 
     @classmethod
index 72474167ceb2727a9d51f15b3756cb6f34ce8f69..58cc410b68ab90542e9e0fa813649afb5c706d02 100644 (file)
@@ -222,3 +222,22 @@ class SubprocessTest(AsyncTestCase):
         ret = self.wait()
         self.assertEqual(subproc.returncode, ret)
         self.assertEqual(ret, -signal.SIGTERM)
+
+    @gen_test
+    def test_wait_for_exit_raise(self):
+        skip_if_twisted()
+        Subprocess.initialize()
+        self.addCleanup(Subprocess.uninitialize)
+        subproc = Subprocess([sys.executable, '-c', 'import sys; sys.exit(1)'])
+        with self.assertRaises(subprocess.CalledProcessError) as cm:
+            yield subproc.wait_for_exit()
+        self.assertEqual(cm.exception.returncode, 1)
+
+    @gen_test
+    def test_wait_for_exit_raise_disabled(self):
+        skip_if_twisted()
+        Subprocess.initialize()
+        self.addCleanup(Subprocess.uninitialize)
+        subproc = Subprocess([sys.executable, '-c', 'import sys; sys.exit(1)'])
+        ret = yield subproc.wait_for_exit(raise_error=False)
+        self.assertEqual(ret, 1)