]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Add support for native coroutines in IOLoop.run_sync.
authorBen Darnell <ben@bendarnell.com>
Sun, 4 Oct 2015 00:31:20 +0000 (20:31 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 4 Oct 2015 02:28:14 +0000 (22:28 -0400)
Remove support for synchronous functions with non-None results.

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

index 195475ba061aec7b3a1800b665a79bf035f8f026..742a8487914f106e756cef9cc7064c2c75ccbea9 100644 (file)
@@ -400,10 +400,12 @@ class IOLoop(Configurable):
     def run_sync(self, func, timeout=None):
         """Starts the `IOLoop`, runs the given function, and stops the loop.
 
-        If the function returns a `.Future`, the `IOLoop` will run
-        until the future is resolved.  If it raises an exception, the
-        `IOLoop` will stop and the exception will be re-raised to the
-        caller.
+        The function must return either a yieldable object or
+        ``None``. If the function returns a yieldable object, the
+        `IOLoop` will run until the yieldable is resolved (and
+        `run_sync()` will return the yieldable's result). If it raises
+        an exception, the `IOLoop` will stop and the exception will be
+        re-raised to the caller.
 
         The keyword-only argument ``timeout`` may be used to set
         a maximum duration for the function.  If the timeout expires,
@@ -418,12 +420,18 @@ class IOLoop(Configurable):
 
             if __name__ == '__main__':
                 IOLoop.current().run_sync(main)
+
+        .. versionchanged:: 4.3
+           Returning a non-``None``, non-yieldable value is now an error.
         """
         future_cell = [None]
 
         def run():
             try:
                 result = func()
+                if result is not None:
+                    from tornado.gen import convert_yielded
+                    result = convert_yielded(result)
             except Exception:
                 future_cell[0] = TracebackFuture()
                 future_cell[0].set_exc_info(sys.exc_info())
index 0711282e327b34c4007e8594774ba6e91bebe41b..8c2edd2f9962cf73087a90c762ba17bac7a3af2d 100644 (file)
@@ -16,7 +16,7 @@ from tornado.log import app_log
 from tornado.platform.select import _Select
 from tornado.stack_context import ExceptionStackContext, StackContext, wrap, NullContext
 from tornado.testing import AsyncTestCase, bind_unused_port, ExpectLog
-from tornado.test.util import unittest, skipIfNonUnix, skipOnTravis
+from tornado.test.util import unittest, skipIfNonUnix, skipOnTravis, skipBefore35, exec_test
 
 try:
     from concurrent import futures
@@ -558,7 +558,8 @@ class TestIOLoopRunSync(unittest.TestCase):
         self.io_loop.close()
 
     def test_sync_result(self):
-        self.assertEqual(self.io_loop.run_sync(lambda: 42), 42)
+        with self.assertRaises(gen.BadYieldError):
+            self.io_loop.run_sync(lambda: 42)
 
     def test_sync_exception(self):
         with self.assertRaises(ZeroDivisionError):
@@ -590,6 +591,14 @@ class TestIOLoopRunSync(unittest.TestCase):
             yield gen.Task(self.io_loop.add_timeout, self.io_loop.time() + 1)
         self.assertRaises(TimeoutError, self.io_loop.run_sync, f, timeout=0.01)
 
+    @skipBefore35
+    def test_native_coroutine(self):
+        namespace = exec_test(globals(), locals(), """
+        async def f():
+            await gen.Task(self.io_loop.add_callback)
+        """)
+        self.io_loop.run_sync(namespace['f'])
+
 
 class TestPeriodicCallback(unittest.TestCase):
     def setUp(self):