Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-94597: add asyncio.EventLoop #110723

Merged
merged 9 commits into from
Oct 12, 2023
8 changes: 8 additions & 0 deletions Doc/library/asyncio-eventloop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,14 @@ on Unix and :class:`ProactorEventLoop` on Windows.
`MSDN documentation on I/O Completion Ports
<https://docs.microsoft.com/en-ca/windows/desktop/FileIO/i-o-completion-ports>`_.

.. class:: EventLoop

Uses the most efficient available event loop for the given
platform.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this ought to explain that it's an alias for one of the above classes, and that it's the one used by default, and that it's selected the way described above (L1689-90). "Uses" doesn't even explain that it's a subclass of AbstractEventLoop.

Maybe we should be less specific about how the default is selected, and probably whatever we say about it should be only said once, but it should be made clear that this class is the default, and the default is this class.

Copy link
Contributor Author

@graingert graingert Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe something like this? The other classes don't explain that they are subclasses of AbstractEventLoop, should that be explained in ProactorEventLoop and SelectorEventLoop?

Suggested change
Uses the most efficient available event loop for the given
platform.
Uses the most efficient available event loop for the given
platform.
It is an alias for :class:`SelectorEventLoop` on Unix and :class:`ProactorEventLoop` on Windows.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite. I don't like any sentence describing a class object starting with "Uses". Classes are nouns, and the description should explain what the class is, not what it does. Also, the current algorithm for choosing a default is now specified in two places. I think it should be specified only here (and the earlier text should be changed to claim that EventLoop is the class used by default).

It's also a good idea to clarify that both concrete classes are subclasses of AbstractEventLoop (but if you're tired of going around in review you can skip that).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I've pushed a change with some doc tweaks


.. versionadded:: 3.13

.. availability:: Unix, Windows.
graingert marked this conversation as resolved.
Show resolved Hide resolved
graingert marked this conversation as resolved.
Show resolved Hide resolved

.. class:: AbstractEventLoop

Expand Down
2 changes: 2 additions & 0 deletions Doc/library/asyncio-runner.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Running an asyncio Program
This function should be used as a main entry point for asyncio programs,
and should ideally only be called once. It is recommended to use
*loop_factory* to configure the event loop instead of policies.
Passing :class:`asyncio.EventLoop` allows running asyncio without the
policy system.

The executor is given a timeout duration of 5 minutes to shutdown.
If the executor hasn't finished within that duration, a warning is
Expand Down
2 changes: 2 additions & 0 deletions Lib/asyncio/unix_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'FastChildWatcher', 'PidfdChildWatcher',
'MultiLoopChildWatcher', 'ThreadedChildWatcher',
'DefaultEventLoopPolicy',
'EventLoop',
)


Expand Down Expand Up @@ -1510,3 +1511,4 @@ def set_child_watcher(self, watcher):

SelectorEventLoop = _UnixSelectorEventLoop
DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy
EventLoop = SelectorEventLoop
3 changes: 2 additions & 1 deletion Lib/asyncio/windows_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
__all__ = (
'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor',
'DefaultEventLoopPolicy', 'WindowsSelectorEventLoopPolicy',
'WindowsProactorEventLoopPolicy',
'WindowsProactorEventLoopPolicy', 'EventLoop',
)


Expand Down Expand Up @@ -894,3 +894,4 @@ class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):


DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy
EventLoop = ProactorEventLoop
11 changes: 11 additions & 0 deletions Lib/test/test_asyncio/test_runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import contextvars
import re
import signal
import sys
import threading
import unittest
from test.test_asyncio import utils as test_utils
Expand Down Expand Up @@ -272,6 +273,16 @@ async def main():
asyncio.run(main(), loop_factory=factory)
factory.assert_called_once_with()

def test_loop_factory_default_event_loop(self):
async def main():
if sys.platform == "win32":
self.assertIsInstance(asyncio.get_running_loop(), asyncio.ProactorEventLoop)
else:
self.assertIsInstance(asyncio.get_running_loop(), asyncio.SelectorEventLoop)


asyncio.run(main(), loop_factory=asyncio.EventLoop)


class RunnerTests(BaseTest):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added :class:`asyncio.EventLoop` for use with the :func:`asyncio.run` *loop_factory* kwarg to avoid calling the asyncio policy system
graingert marked this conversation as resolved.
Show resolved Hide resolved
Loading