From: Ben Darnell Date: Fri, 18 Oct 2013 20:07:11 +0000 (-0400) Subject: Split AsyncIOLoop to make it possible to use the global asyncio event loop. X-Git-Tag: v3.2.0b1~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e074040c5754198b6fe6e2c57c4587534ea5c799;p=thirdparty%2Ftornado.git Split AsyncIOLoop to make it possible to use the global asyncio event loop. AsyncIOLoop works more like Tornado's native IOLoop so it's better for our tests, but AsyncIOMainLoop is more appropriate for most real-world usage. --- diff --git a/tornado/platform/asyncio.py b/tornado/platform/asyncio.py index f59b11028..a8f5bad47 100644 --- a/tornado/platform/asyncio.py +++ b/tornado/platform/asyncio.py @@ -2,7 +2,11 @@ This is a work in progress and interfaces are subject to change. -To test: python3.4 -m tornado.test.runtests --ioloop=tornado.platform.asyncio.AsyncIOLoop +To test: +python3.4 -m tornado.test.runtests --ioloop=tornado.platform.asyncio.AsyncIOLoop +python3.4 -m tornado.test.runtests --ioloop=tornado.platform.asyncio.AsyncIOMainLoop +(the tests log a few warnings with AsyncIOMainLoop because they leave some +unfinished callbacks on the event loop that fail when it resumes) """ import asyncio import datetime @@ -12,11 +16,10 @@ import os from tornado.ioloop import IOLoop from tornado import stack_context -# This name is really unfortunate. -class AsyncIOLoop(IOLoop): - def initialize(self): - # TODO: we need a way to use the global get_event_loop. - self.asyncio_loop = asyncio.events.new_event_loop() +class BaseAsyncIOLoop(IOLoop): + def initialize(self, asyncio_loop, close_loop=False): + self.asyncio_loop = asyncio_loop + self.close_loop = close_loop self.asyncio_loop.call_soon(self.make_current) # Maps fd to handler function (as in IOLoop.add_handler) self.handlers = {} @@ -31,7 +34,8 @@ class AsyncIOLoop(IOLoop): self.remove_handler(fd) if all_fds: os.close(fd) - self.asyncio_loop.close() + if self.close_loop: + self.asyncio_loop.close() def add_handler(self, fd, handler, events): if fd in self.handlers: @@ -117,3 +121,14 @@ class AsyncIOLoop(IOLoop): self._run_callback, stack_context.wrap(callback), *args) add_callback_from_signal = add_callback + + +class AsyncIOMainLoop(BaseAsyncIOLoop): + def initialize(self): + super(AsyncIOMainLoop, self).initialize(asyncio.get_event_loop(), + close_loop=False) + +class AsyncIOLoop(BaseAsyncIOLoop): + def initialize(self): + super(AsyncIOLoop, self).initialize(asyncio.new_event_loop(), + close_loop=True) diff --git a/tornado/test/httpclient_test.py b/tornado/test/httpclient_test.py index 0efef9b32..15bb8e44b 100644 --- a/tornado/test/httpclient_test.py +++ b/tornado/test/httpclient_test.py @@ -433,11 +433,16 @@ class HTTPResponseTestCase(unittest.TestCase): class SyncHTTPClientTest(unittest.TestCase): def setUp(self): - if IOLoop.configured_class().__name__ == 'TwistedIOLoop': + if IOLoop.configured_class().__name__ in ('TwistedIOLoop', + 'AsyncIOMainLoop'): # TwistedIOLoop only supports the global reactor, so we can't have # separate IOLoops for client and server threads. + # AsyncIOMainLoop doesn't work with the default policy + # (although it could with some tweaks to this test and a + # policy that created loops for non-main threads). raise unittest.SkipTest( - 'Sync HTTPClient not compatible with TwistedIOLoop') + 'Sync HTTPClient not compatible with TwistedIOLoop or ' + 'AsyncIOMainLoop') self.server_ioloop = IOLoop() sock, self.port = bind_unused_port() diff --git a/tornado/test/process_test.py b/tornado/test/process_test.py index 86f5f141e..de727607a 100644 --- a/tornado/test/process_test.py +++ b/tornado/test/process_test.py @@ -19,8 +19,10 @@ from tornado.web import RequestHandler, Application def skip_if_twisted(): - if IOLoop.configured_class().__name__.endswith('TwistedIOLoop'): - raise unittest.SkipTest("Process tests not compatible with TwistedIOLoop") + if IOLoop.configured_class().__name__.endswith(('TwistedIOLoop', + 'AsyncIOMainLoop')): + raise unittest.SkipTest("Process tests not compatible with " + "TwistedIOLoop or AsyncIOMainLoop") # Not using AsyncHTTPTestCase because we need control over the IOLoop.