Skip to content

Commit

Permalink
Allow passing asyncio_loop argument to AsyncIOLoop
Browse files Browse the repository at this point in the history
allows patterns of creating and explicitly passing the asyncio loop before creating IOLoop

For example: creating a loop with the non-default event loop policy without having to set the current policy
  • Loading branch information
minrk committed Jun 15, 2022
1 parent 713f06b commit c5b669d
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
15 changes: 12 additions & 3 deletions tornado/platform/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ class AsyncIOLoop(BaseAsyncIOLoop):
Each ``AsyncIOLoop`` creates a new ``asyncio.EventLoop``; this object
can be accessed with the ``asyncio_loop`` attribute.
.. versionchanged:: 6.2
Support explicit `asyncio_loop` argument
for specifying the asyncio loop to attach to,
rather than always creating a new one with the default policy.
.. versionchanged:: 5.0
When an ``AsyncIOLoop`` becomes the current `.IOLoop`, it also sets
Expand All @@ -323,13 +329,16 @@ class AsyncIOLoop(BaseAsyncIOLoop):

def initialize(self, **kwargs: Any) -> None: # type: ignore
self.is_current = False
loop = asyncio.new_event_loop()
loop = None
if "asyncio_loop" not in kwargs:
kwargs["asyncio_loop"] = loop = asyncio.new_event_loop()
try:
super().initialize(loop, **kwargs)
super().initialize(**kwargs)
except Exception:
# If initialize() does not succeed (taking ownership of the loop),
# we have to close it.
loop.close()
if loop is not None:
loop.close()
raise

def close(self, all_fds: bool = False) -> None:
Expand Down
7 changes: 7 additions & 0 deletions tornado/test/ioloop_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from concurrent.futures import ThreadPoolExecutor
from concurrent import futures
from collections.abc import Generator
Expand Down Expand Up @@ -427,6 +428,12 @@ def f():

yield gen.multi([self.io_loop.run_in_executor(None, f) for i in range(2)])

def test_explicit_asyncio_loop(self):
asyncio_loop = asyncio.new_event_loop()
loop = IOLoop(asyncio_loop=asyncio_loop, make_current=False)
assert loop.asyncio_loop is asyncio_loop
loop.close()


# Deliberately not a subclass of AsyncTestCase so the IOLoop isn't
# automatically set as current.
Expand Down

0 comments on commit c5b669d

Please sign in to comment.