]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Simplify RequestHandler._execute by making it a coroutine.
authorBen Darnell <ben@bendarnell.com>
Mon, 17 Mar 2014 04:25:10 +0000 (00:25 -0400)
committerBen Darnell <ben@bendarnell.com>
Mon, 17 Mar 2014 04:27:28 +0000 (00:27 -0400)
tornado/gen.py
tornado/web.py

index 81de9ff7bc49ae07a0db7f599bb097dac87bdad0..0e6f92c9480201df558697853a33b0e80dcdee5d 100644 (file)
@@ -421,6 +421,22 @@ class Multi(YieldPoint):
             return list(result)
 
 
+def maybe_future(x):
+    """Converts ``x`` into a `.Future`.
+
+    If ``x`` is already a `.Future`, it is simply returned; otherwise
+    it is wrapped in a new `.Future`.  This is suitable for use as
+    ``result = yield gen.maybe_future(f())`` when you don't know whether
+    ``f()`` returns a `.Future` or not.
+    """
+    if is_future(x):
+        return x
+    else:
+        fut = Future()
+        fut.set_result(x)
+        return fut
+
+
 _null_future = Future()
 _null_future.set_result(None)
 
index 3650180dd7217e93d538b64bfba1fbc07907b9ec..ec251d69021a0b004b686c5e92b2acb5354831c4 100644 (file)
@@ -76,6 +76,7 @@ import uuid
 
 from tornado.concurrent import Future
 from tornado import escape
+from tornado import gen
 from tornado import httputil
 from tornado import locale
 from tornado.log import access_log, app_log, gen_log
@@ -1194,6 +1195,7 @@ class RequestHandler(object):
             self._handle_request_exception(value)
         return True
 
+    @gen.coroutine
     def _execute(self, transforms, *args, **kwargs):
         """Executes this request with the given output transforms."""
         self._transforms = transforms
@@ -1208,40 +1210,22 @@ class RequestHandler(object):
             if self.request.method not in ("GET", "HEAD", "OPTIONS") and \
                     self.application.settings.get("xsrf_cookies"):
                 self.check_xsrf_cookie()
-            self._when_complete(self.prepare(), self._execute_method)
-        except Exception as e:
-            self._handle_request_exception(e)
 
-    def _when_complete(self, result, callback):
-        try:
-            if result is None:
-                callback()
-            elif isinstance(result, Future):
-                if result.done():
-                    if result.result() is not None:
-                        raise ValueError('Expected None, got %r' % result.result())
-                    callback()
-                else:
-                    # Delayed import of IOLoop because it's not available
-                    # on app engine
-                    from tornado.ioloop import IOLoop
-                    IOLoop.current().add_future(
-                        result, functools.partial(self._when_complete,
-                                                  callback=callback))
-            else:
-                raise ValueError("Expected Future or None, got %r" % result)
-        except Exception as e:
-            self._handle_request_exception(e)
+            result = yield gen.maybe_future(self.prepare())
+            if result is not None:
+                raise TypeError("Expected None, got %r" % result)
+            if self._finished:
+                return
 
-    def _execute_method(self):
-        if not self._finished:
             method = getattr(self, self.request.method.lower())
-            self._when_complete(method(*self.path_args, **self.path_kwargs),
-                                self._execute_finish)
-
-    def _execute_finish(self):
-        if self._auto_finish and not self._finished:
-            self.finish()
+            result = yield gen.maybe_future(
+                method(*self.path_args, **self.path_kwargs))
+            if result is not None:
+                raise TypeError("Expected None, got %r" % result)
+            if self._auto_finish and not self._finished:
+                self.finish()
+        except Exception as e:
+            self._handle_request_exception(e)
 
     def _log(self):
         """Logs the current request.
@@ -1739,6 +1723,11 @@ class _RequestDispatcher(httputil.HTTPMessageDelegate):
         handler = self.handler_class(self.application, self.request,
                                      **self.handler_kwargs)
         transforms = [t(self.request) for t in self.application.transforms]
+        # Note that if an exception escapes handler._execute it will be
+        # trapped in the Future it returns (which we are ignoring here).
+        # However, that shouldn't happen because _execute has a blanket
+        # except handler, and we cannot easily access the IOLoop here to
+        # call add_future.
         handler._execute(transforms, *self.path_args, **self.path_kwargs)
         return handler