]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
web: Convert RequestHandler._execute to a native coroutine
authorBen Darnell <ben@bendarnell.com>
Sun, 14 Oct 2018 17:30:54 +0000 (13:30 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 14 Oct 2018 17:30:54 +0000 (13:30 -0400)
tornado/test/httpserver_test.py
tornado/test/simple_httpclient_test.py
tornado/test/web_test.py
tornado/web.py

index b46a0a396c4f34912919b0a33609a58e0f45570e..2a8b6a5b14b0efcda6bb2e01d93848b73b1de581 100644 (file)
@@ -751,11 +751,13 @@ class KeepAliveTest(AsyncHTTPTestCase):
                 self.write("".join(chr(i % 256) * 1024 for i in range(512)))
 
         class FinishOnCloseHandler(RequestHandler):
+            def initialize(self, cleanup_event):
+                self.cleanup_event = cleanup_event
+
             @gen.coroutine
             def get(self):
                 self.flush()
-                never_finish = Event()
-                yield never_finish.wait()
+                yield self.cleanup_event.wait()
 
             def on_connection_close(self):
                 # This is not very realistic, but finishing the request
@@ -763,11 +765,16 @@ class KeepAliveTest(AsyncHTTPTestCase):
                 # some errors seen in the wild.
                 self.finish("closed")
 
+        self.cleanup_event = Event()
         return Application(
             [
                 ("/", HelloHandler),
                 ("/large", LargeHandler),
-                ("/finish_on_close", FinishOnCloseHandler),
+                (
+                    "/finish_on_close",
+                    FinishOnCloseHandler,
+                    dict(cleanup_event=self.cleanup_event),
+                ),
             ]
         )
 
@@ -894,6 +901,8 @@ class KeepAliveTest(AsyncHTTPTestCase):
         self.stream.write(b"GET /finish_on_close HTTP/1.1\r\n\r\n")
         yield self.read_headers()
         self.close()
+        # Let the hanging coroutine clean up after itself
+        self.cleanup_event.set()
 
     @gen_test
     def test_keepalive_chunked(self):
index ed399ae0563068b90730775a876a3966e0e6518f..11539a2f7270868aa33350c48d88549db7a753ad 100644 (file)
@@ -58,18 +58,11 @@ class TriggerHandler(RequestHandler):
     @gen.coroutine
     def get(self):
         logging.debug("queuing trigger")
-        self.queue.append(self.finish)
+        event = Event()
+        self.queue.append(event.set)
         if self.get_argument("wake", "true") == "true":
             self.wake_callback()
-        never_finish = Event()
-        yield never_finish.wait()
-
-
-class HangHandler(RequestHandler):
-    @gen.coroutine
-    def get(self):
-        never_finish = Event()
-        yield never_finish.wait()
+        yield event.wait()
 
 
 class ContentLengthHandler(RequestHandler):
@@ -163,7 +156,6 @@ class SimpleHTTPClientTestMixin(object):
                 ),
                 url("/chunk", ChunkHandler),
                 url("/countdown/([0-9]+)", CountdownHandler, name="countdown"),
-                url("/hang", HangHandler),
                 url("/hello", HelloWorldHandler),
                 url("/content_length", ContentLengthHandler),
                 url("/head", HeadHandler),
@@ -304,6 +296,7 @@ class SimpleHTTPClientTestMixin(object):
             self.fetch("/trigger?wake=false", request_timeout=timeout, raise_error=True)
         # trigger the hanging request to let it clean up after itself
         self.triggers.popleft()()
+        self.io_loop.run_sync(lambda: gen.sleep(0))
 
     @skipIfNoIPv6
     def test_ipv6(self):
index 87738ba3c7ba673fb4d83fb6f1d2619e02ac2448..96a787bb312b0af6a9991ed5e8c88a24bb486255 100644 (file)
@@ -441,8 +441,7 @@ class ConnectionCloseHandler(RequestHandler):
     @gen.coroutine
     def get(self):
         self.test.on_handler_waiting()
-        never_finish = Event()
-        yield never_finish.wait()
+        yield self.test.cleanup_event.wait()
 
     def on_connection_close(self):
         self.test.on_connection_close()
@@ -450,6 +449,7 @@ class ConnectionCloseHandler(RequestHandler):
 
 class ConnectionCloseTest(WebTestCase):
     def get_handlers(self):
+        self.cleanup_event = Event()
         return [("/", ConnectionCloseHandler, dict(test=self))]
 
     def test_connection_close(self):
@@ -458,6 +458,9 @@ class ConnectionCloseTest(WebTestCase):
         self.stream = IOStream(s)
         self.stream.write(b"GET / HTTP/1.0\r\n\r\n")
         self.wait()
+        # Let the hanging coroutine clean up after itself
+        self.cleanup_event.set()
+        self.io_loop.run_sync(lambda: gen.sleep(0))
 
     def on_handler_waiting(self):
         logging.debug("handler waiting")
index a9d28a600afb4f790b1cc01fbc56294c509f587e..c6dca17ffb6295e01ec9151493864f00714defc1 100644 (file)
@@ -1659,10 +1659,9 @@ class RequestHandler(object):
                     break
         return match
 
-    @gen.coroutine
-    def _execute(
+    async def _execute(
         self, transforms: List["OutputTransform"], *args: bytes, **kwargs: bytes
-    ) -> Generator[Any, Any, None]:
+    ) -> None:
         """Executes this request with the given output transforms."""
         self._transforms = transforms
         try:
@@ -1683,7 +1682,7 @@ class RequestHandler(object):
 
             result = self.prepare()
             if result is not None:
-                result = yield result
+                result = await result
             if self._prepared_future is not None:
                 # Tell the Application we've finished with prepare()
                 # and are ready for the body to arrive.
@@ -1697,14 +1696,14 @@ class RequestHandler(object):
                 # result; the data has been passed to self.data_received
                 # instead.
                 try:
-                    yield self.request._body_future
+                    await self.request._body_future
                 except iostream.StreamClosedError:
                     return
 
             method = getattr(self, self.request.method.lower())
             result = method(*self.path_args, **self.path_kwargs)
             if result is not None:
-                result = yield result
+                result = await result
             if self._auto_finish and not self._finished:
                 self.finish()
         except Exception as e:
@@ -2329,7 +2328,10 @@ class _HandlerDelegate(httputil.HTTPMessageDelegate):
         # except handler, and we cannot easily access the IOLoop here to
         # call add_future (because of the requirement to remain compatible
         # with WSGI)
-        self.handler._execute(transforms, *self.path_args, **self.path_kwargs)
+        fut = gen.convert_yielded(
+            self.handler._execute(transforms, *self.path_args, **self.path_kwargs)
+        )
+        fut.add_done_callback(lambda f: f.result())
         # If we are streaming the request body, then execute() is finished
         # when the handler has prepared to receive the body.  If not,
         # it doesn't matter when execute() finishes (so we return None)