]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Refactor coroutine yield handling.
authorBen Darnell <ben@bendarnell.com>
Mon, 19 Jan 2015 03:54:34 +0000 (22:54 -0500)
committerBen Darnell <ben@bendarnell.com>
Mon, 19 Jan 2015 04:15:36 +0000 (23:15 -0500)
Extract a convert_yielded function that can be extended with other types.

tornado/gen.py

index 1d1d267bf6998ab282c174b01daf5a6651c96adb..7333bd6d7d4d3541fc8cdb9b340aa65433d103b5 100644 (file)
@@ -802,18 +802,18 @@ class Runner(object):
             self.running = False
 
     def handle_yield(self, yielded):
-        if isinstance(yielded, list):
-            if all(is_future(f) for f in yielded):
-                yielded = multi_future(yielded)
-            else:
-                yielded = Multi(yielded)
-        elif isinstance(yielded, dict):
-            if all(is_future(f) for f in yielded.values()):
-                yielded = multi_future(yielded)
-            else:
-                yielded = Multi(yielded)
+        # Lists containing YieldPoints require stack contexts;
+        # other lists are handled via multi_future in convert_yielded.
+        if (isinstance(yielded, list) and
+            any(isinstance(f, YieldPoint) for f in yielded)):
+            yielded = Multi(yielded)
+        elif (isinstance(yielded, dict) and
+            any(isinstance(f, YieldPoint) for f in yielded.values())):
+            yielded = Multi(yielded)
 
         if isinstance(yielded, YieldPoint):
+            # YieldPoints are too closely coupled to the Runner to go
+            # through the generic convert_yielded mechanism.
             self.future = TracebackFuture()
             def start_yield_point():
                 try:
@@ -826,6 +826,7 @@ class Runner(object):
                 except Exception:
                     self.future = TracebackFuture()
                     self.future.set_exc_info(sys.exc_info())
+
             if self.stack_context_deactivate is None:
                 # Start a stack context if this is the first
                 # YieldPoint we've seen.
@@ -839,16 +840,17 @@ class Runner(object):
                     return False
             else:
                 start_yield_point()
-        elif is_future(yielded):
-            self.future = yielded
-            if not self.future.done() or self.future is moment:
-                self.io_loop.add_future(
-                    self.future, lambda f: self.run())
-                return False
         else:
-            self.future = TracebackFuture()
-            self.future.set_exception(BadYieldError(
-                "yielded unknown object %r" % (yielded,)))
+            try:
+                self.future = convert_yielded(yielded)
+            except BadYieldError:
+                self.future = TracebackFuture()
+                self.future.set_exc_info(sys.exc_info())
+
+        if not self.future.done() or self.future is moment:
+            self.io_loop.add_future(
+                self.future, lambda f: self.run())
+            return False
         return True
 
     def result_callback(self, key):
@@ -887,3 +889,14 @@ def _argument_adapter(callback):
         else:
             callback(None)
     return wrapper
+
+
+def convert_yielded(yielded):
+    # Lists and dicts containing YieldPoints were handled separately
+    # via Multi().
+    if isinstance(yielded, (list, dict)):
+        return multi_future(yielded)
+    elif is_future(yielded):
+        return yielded
+    else:
+        raise BadYieldError("yielded unknown object %r" % (yielded,))