]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Introduce IOLoop.spawn_callback.
authorBen Darnell <ben@bendarnell.com>
Mon, 16 Jun 2014 03:49:39 +0000 (23:49 -0400)
committerBen Darnell <ben@bendarnell.com>
Mon, 16 Jun 2014 03:49:39 +0000 (23:49 -0400)
This makes it easier and more discoverable to run a callback without
stack_context.

Closes #867.

tornado/ioloop.py
tornado/test/ioloop_test.py

index bd5ff6fb4d3df4c40d8fd49f10825564427c387c..3477684cbf3369dd03f53473269a66a05870a3be 100644 (file)
@@ -486,6 +486,19 @@ class IOLoop(Configurable):
         """
         raise NotImplementedError()
 
+    def spawn_callback(self, callback, *args, **kwargs):
+        """Calls the given callback on the next IOLoop iteration.
+
+        Unlike all other callback-related methods on IOLoop,
+        ``spawn_callback`` does not associate the callback with its caller's
+        ``stack_context``, so it is suitable for fire-and-forget callbacks
+        that should not interfere with the caller.
+
+        .. versionadded:: 4.0
+        """
+        with stack_context.NullContext():
+            self.add_callback(callback, *args, **kwargs)
+
     def add_future(self, future, callback):
         """Schedules a callback on the ``IOLoop`` when the given
         `.Future` is finished.
index 03b4fddfb32633e4d494bbce4925a100c40e688d..e4f07338efc1b32f35e4753ad65d6d23dd12b645 100644 (file)
@@ -273,6 +273,19 @@ class TestIOLoop(AsyncTestCase):
             with ExpectLog(app_log, "Exception in callback"):
                 self.wait()
 
+    def test_spawn_callback(self):
+        # An added callback runs in the test's stack_context, so will be
+        # re-arised in wait().
+        self.io_loop.add_callback(lambda: 1/0)
+        with self.assertRaises(ZeroDivisionError):
+            self.wait()
+        # A spawned callback is run directly on the IOLoop, so it will be
+        # logged without stopping the test.
+        self.io_loop.spawn_callback(lambda: 1/0)
+        self.io_loop.add_callback(self.stop)
+        with ExpectLog(app_log, "Exception in callback"):
+            self.wait()
+
 
 # Deliberately not a subclass of AsyncTestCase so the IOLoop isn't
 # automatically set as current.