]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
ioloop: Setting AsyncIOLoop as current also sets asyncio event loop 2218/head
authorBen Darnell <ben@bendarnell.com>
Sun, 17 Dec 2017 16:36:53 +0000 (11:36 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 17 Dec 2017 16:36:53 +0000 (11:36 -0500)
This should eliminate the need for explicit asyncio manipulations
from applications migrating to Tornado 5.0

tornado/ioloop.py
tornado/platform/asyncio.py
tornado/test/asyncio_test.py
tornado/test/twisted_test.py
tornado/testing.py

index 5d359d062a6ffb4ae79f00d7977cfcfb9532b2cb..0a1056fb0555a5ded00b5aa473a2f375c45cbda8 100644 (file)
@@ -300,8 +300,18 @@ class IOLoop(Configurable):
 
         Intended primarily for use by test frameworks in between tests.
         """
+        old = IOLoop._current.instance
+        if old is not None:
+            old._clear_current_hook()
         IOLoop._current.instance = None
 
+    def _clear_current_hook(self):
+        """Instance method called when an IOLoop ceases to be current.
+
+        May be overridden by subclasses as a counterpart to make_current.
+        """
+        pass
+
     @classmethod
     def configurable_base(cls):
         return IOLoop
index 5066fe4ba097b47e642add5b5e16fe385ad48da8..2a90099e44b9bd332354c79f2697e5a73dccfbbf 100644 (file)
@@ -31,7 +31,6 @@ import asyncio
 
 class BaseAsyncIOLoop(IOLoop):
     def initialize(self, asyncio_loop, close_loop=False, **kwargs):
-        super(BaseAsyncIOLoop, self).initialize(**kwargs)
         self.asyncio_loop = asyncio_loop
         self.close_loop = close_loop
         # Maps fd to (fileobj, handler function) pair (as in IOLoop.add_handler)
@@ -40,6 +39,7 @@ class BaseAsyncIOLoop(IOLoop):
         self.readers = set()
         self.writers = set()
         self.closing = False
+        super(BaseAsyncIOLoop, self).initialize(**kwargs)
 
     def close(self, all_fds=False):
         self.closing = True
@@ -104,22 +104,15 @@ class BaseAsyncIOLoop(IOLoop):
 
     def start(self):
         old_current = IOLoop.current(instance=False)
-        try:
-            old_asyncio = asyncio.get_event_loop()
-        except RuntimeError:
-            old_asyncio = None
         try:
             self._setup_logging()
             self.make_current()
-            # This is automatic in 3.5, but must be done manually in 3.4.
-            asyncio.set_event_loop(self.asyncio_loop)
             self.asyncio_loop.run_forever()
         finally:
             if old_current is None:
                 IOLoop.clear_current()
             else:
                 old_current.make_current()
-            asyncio.set_event_loop(old_asyncio)
 
     def stop(self):
         self.asyncio_loop.stop()
@@ -188,6 +181,17 @@ class AsyncIOLoop(BaseAsyncIOLoop):
             loop.close()
             raise
 
+    def make_current(self):
+        super(AsyncIOLoop, self).make_current()
+        try:
+            self.old_asyncio = asyncio.get_event_loop()
+        except RuntimeError:
+            self.old_asyncio = None
+        asyncio.set_event_loop(self.asyncio_loop)
+
+    def _clear_current_hook(self):
+        asyncio.set_event_loop(self.old_asyncio)
+
 
 def to_tornado_future(asyncio_future):
     """Convert an `asyncio.Future` to a `tornado.concurrent.Future`.
index 1bfbe76ca9c058a49c16d3e0b728c97278c6965f..54d9fa03f7ab98b236259448de8b14644e0de81a 100644 (file)
@@ -30,7 +30,6 @@ else:
 class AsyncIOLoopTest(AsyncTestCase):
     def get_new_ioloop(self):
         io_loop = AsyncIOLoop()
-        asyncio.set_event_loop(io_loop.asyncio_loop)
         return io_loop
 
     def test_asyncio_callback(self):
index 5c9884dfdf838f3b77958b7d4090737fe5de1e83..84a9f44dff24517551ae0c5b2db4173d98a4bc37 100644 (file)
@@ -505,14 +505,6 @@ class CompatibilityTests(unittest.TestCase):
 
 @skipIfNoTwisted
 class ConvertDeferredTest(unittest.TestCase):
-    def setUp(self):
-        if asyncio is not None:
-            asyncio.set_event_loop(asyncio.new_event_loop())
-
-    def tearDown(self):
-        if asyncio is not None:
-            asyncio.set_event_loop(None)
-
     def test_success(self):
         @inlineCallbacks
         def fn():
index 975df86cc9d6dea66b7fa743c1c10123df6249d3..95f0ec538b11209762961a1931f81ec5dd400294 100644 (file)
@@ -217,9 +217,6 @@ class AsyncTestCase(unittest.TestCase):
         super(AsyncTestCase, self).setUp()
         self.io_loop = self.get_new_ioloop()
         self.io_loop.make_current()
-        if hasattr(self.io_loop, 'asyncio_loop'):
-            # Ensure that asyncio's current event loop matches ours.
-            asyncio.set_event_loop(self.io_loop.asyncio_loop)
 
     def tearDown(self):
         # Clean up Subprocess, so it can be used again with a new ioloop.
@@ -231,8 +228,6 @@ class AsyncTestCase(unittest.TestCase):
         # set FD_CLOEXEC on its file descriptors)
         self.io_loop.close(all_fds=True)
         super(AsyncTestCase, self).tearDown()
-        if hasattr(self.io_loop, 'asyncio_loop'):
-            asyncio.set_event_loop(None)
         # In case an exception escaped or the StackContext caught an exception
         # when there wasn't a wait() to re-raise it, do so here.
         # This is our last chance to raise an exception in a way that the