gh-127949: deprecate asyncio policy classes (#128216)

This commit is contained in:
Kumar Aditya 2024-12-24 17:30:26 +05:30 committed by GitHub
parent 3f6a618e49
commit a391d80f4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 82 additions and 34 deletions

View File

@ -87,6 +87,10 @@ The abstract event loop policy base class is defined as follows:
This method should never return ``None``. This method should never return ``None``.
.. deprecated:: next
The :class:`AbstractEventLoopPolicy` class is deprecated and
will be removed in Python 3.16.
.. _asyncio-policy-builtin: .. _asyncio-policy-builtin:
@ -109,6 +113,10 @@ asyncio ships with the following built-in policies:
The :meth:`get_event_loop` method of the default asyncio policy now The :meth:`get_event_loop` method of the default asyncio policy now
raises a :exc:`RuntimeError` if there is no set event loop. raises a :exc:`RuntimeError` if there is no set event loop.
.. deprecated:: next
The :class:`DefaultEventLoopPolicy` class is deprecated and
will be removed in Python 3.16.
.. class:: WindowsSelectorEventLoopPolicy .. class:: WindowsSelectorEventLoopPolicy
@ -117,6 +125,10 @@ asyncio ships with the following built-in policies:
.. availability:: Windows. .. availability:: Windows.
.. deprecated:: next
The :class:`WindowsSelectorEventLoopPolicy` class is deprecated and
will be removed in Python 3.16.
.. class:: WindowsProactorEventLoopPolicy .. class:: WindowsProactorEventLoopPolicy
@ -125,6 +137,10 @@ asyncio ships with the following built-in policies:
.. availability:: Windows. .. availability:: Windows.
.. deprecated:: next
The :class:`WindowsProactorEventLoopPolicy` class is deprecated and
will be removed in Python 3.16.
.. _asyncio-custom-policies: .. _asyncio-custom-policies:

View File

@ -45,3 +45,19 @@
else: else:
from .unix_events import * # pragma: no cover from .unix_events import * # pragma: no cover
__all__ += unix_events.__all__ __all__ += unix_events.__all__
def __getattr__(name: str):
import warnings
deprecated = {
"AbstractEventLoopPolicy",
"DefaultEventLoopPolicy",
"WindowsSelectorEventLoopPolicy",
"WindowsProactorEventLoopPolicy",
}
if name in deprecated:
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
# deprecated things have underscores in front of them
return globals()["_" + name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

View File

@ -5,7 +5,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io # SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io
__all__ = ( __all__ = (
'AbstractEventLoopPolicy', '_AbstractEventLoopPolicy',
'AbstractEventLoop', 'AbstractServer', 'AbstractEventLoop', 'AbstractServer',
'Handle', 'TimerHandle', 'Handle', 'TimerHandle',
'_get_event_loop_policy', '_get_event_loop_policy',
@ -632,7 +632,7 @@ def set_debug(self, enabled):
raise NotImplementedError raise NotImplementedError
class AbstractEventLoopPolicy: class _AbstractEventLoopPolicy:
"""Abstract policy for accessing the event loop.""" """Abstract policy for accessing the event loop."""
def get_event_loop(self): def get_event_loop(self):
@ -655,7 +655,7 @@ def new_event_loop(self):
the current context, set_event_loop must be called explicitly.""" the current context, set_event_loop must be called explicitly."""
raise NotImplementedError raise NotImplementedError
class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): class _BaseDefaultEventLoopPolicy(_AbstractEventLoopPolicy):
"""Default policy implementation for accessing the event loop. """Default policy implementation for accessing the event loop.
In this policy, each thread has its own event loop. However, we In this policy, each thread has its own event loop. However, we
@ -758,8 +758,8 @@ def _init_event_loop_policy():
global _event_loop_policy global _event_loop_policy
with _lock: with _lock:
if _event_loop_policy is None: # pragma: no branch if _event_loop_policy is None: # pragma: no branch
from . import DefaultEventLoopPolicy from . import _DefaultEventLoopPolicy
_event_loop_policy = DefaultEventLoopPolicy() _event_loop_policy = _DefaultEventLoopPolicy()
def _get_event_loop_policy(): def _get_event_loop_policy():
@ -777,7 +777,7 @@ def _set_event_loop_policy(policy):
If policy is None, the default policy is restored.""" If policy is None, the default policy is restored."""
global _event_loop_policy global _event_loop_policy
if policy is not None and not isinstance(policy, AbstractEventLoopPolicy): if policy is not None and not isinstance(policy, _AbstractEventLoopPolicy):
raise TypeError(f"policy must be an instance of AbstractEventLoopPolicy or None, not '{type(policy).__name__}'") raise TypeError(f"policy must be an instance of AbstractEventLoopPolicy or None, not '{type(policy).__name__}'")
_event_loop_policy = policy _event_loop_policy = policy
@ -838,7 +838,7 @@ def new_event_loop():
def on_fork(): def on_fork():
# Reset the loop and wakeupfd in the forked child process. # Reset the loop and wakeupfd in the forked child process.
if _event_loop_policy is not None: if _event_loop_policy is not None:
_event_loop_policy._local = BaseDefaultEventLoopPolicy._Local() _event_loop_policy._local = _BaseDefaultEventLoopPolicy._Local()
_set_running_loop(None) _set_running_loop(None)
signal.set_wakeup_fd(-1) signal.set_wakeup_fd(-1)

View File

@ -28,7 +28,7 @@
__all__ = ( __all__ = (
'SelectorEventLoop', 'SelectorEventLoop',
'DefaultEventLoopPolicy', '_DefaultEventLoopPolicy',
'EventLoop', 'EventLoop',
) )
@ -963,11 +963,11 @@ def can_use_pidfd():
return True return True
class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): class _UnixDefaultEventLoopPolicy(events._BaseDefaultEventLoopPolicy):
"""UNIX event loop policy""" """UNIX event loop policy"""
_loop_factory = _UnixSelectorEventLoop _loop_factory = _UnixSelectorEventLoop
SelectorEventLoop = _UnixSelectorEventLoop SelectorEventLoop = _UnixSelectorEventLoop
DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy _DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy
EventLoop = SelectorEventLoop EventLoop = SelectorEventLoop

View File

@ -29,8 +29,8 @@
__all__ = ( __all__ = (
'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor', 'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor',
'DefaultEventLoopPolicy', 'WindowsSelectorEventLoopPolicy', '_DefaultEventLoopPolicy', '_WindowsSelectorEventLoopPolicy',
'WindowsProactorEventLoopPolicy', 'EventLoop', '_WindowsProactorEventLoopPolicy', 'EventLoop',
) )
@ -891,13 +891,13 @@ def callback(f):
SelectorEventLoop = _WindowsSelectorEventLoop SelectorEventLoop = _WindowsSelectorEventLoop
class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): class _WindowsSelectorEventLoopPolicy(events._BaseDefaultEventLoopPolicy):
_loop_factory = SelectorEventLoop _loop_factory = SelectorEventLoop
class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): class _WindowsProactorEventLoopPolicy(events._BaseDefaultEventLoopPolicy):
_loop_factory = ProactorEventLoop _loop_factory = ProactorEventLoop
DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy _DefaultEventLoopPolicy = _WindowsProactorEventLoopPolicy
EventLoop = ProactorEventLoop EventLoop = ProactorEventLoop

View File

@ -2695,14 +2695,26 @@ async def inner():
class PolicyTests(unittest.TestCase): class PolicyTests(unittest.TestCase):
def test_abstract_event_loop_policy_deprecation(self):
with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.AbstractEventLoopPolicy' is deprecated"):
policy = asyncio.AbstractEventLoopPolicy()
self.assertIsInstance(policy, asyncio.AbstractEventLoopPolicy)
def test_default_event_loop_policy_deprecation(self):
with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.DefaultEventLoopPolicy' is deprecated"):
policy = asyncio.DefaultEventLoopPolicy()
self.assertIsInstance(policy, asyncio.DefaultEventLoopPolicy)
def test_event_loop_policy(self): def test_event_loop_policy(self):
policy = asyncio.AbstractEventLoopPolicy() policy = asyncio._AbstractEventLoopPolicy()
self.assertRaises(NotImplementedError, policy.get_event_loop) self.assertRaises(NotImplementedError, policy.get_event_loop)
self.assertRaises(NotImplementedError, policy.set_event_loop, object()) self.assertRaises(NotImplementedError, policy.set_event_loop, object())
self.assertRaises(NotImplementedError, policy.new_event_loop) self.assertRaises(NotImplementedError, policy.new_event_loop)
def test_get_event_loop(self): def test_get_event_loop(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
self.assertIsNone(policy._local._loop) self.assertIsNone(policy._local._loop)
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
@ -2710,7 +2722,7 @@ def test_get_event_loop(self):
self.assertIsNone(policy._local._loop) self.assertIsNone(policy._local._loop)
def test_get_event_loop_does_not_call_set_event_loop(self): def test_get_event_loop_does_not_call_set_event_loop(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
with mock.patch.object( with mock.patch.object(
policy, "set_event_loop", policy, "set_event_loop",
@ -2722,7 +2734,7 @@ def test_get_event_loop_does_not_call_set_event_loop(self):
m_set_event_loop.assert_not_called() m_set_event_loop.assert_not_called()
def test_get_event_loop_after_set_none(self): def test_get_event_loop_after_set_none(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
policy.set_event_loop(None) policy.set_event_loop(None)
self.assertRaises(RuntimeError, policy.get_event_loop) self.assertRaises(RuntimeError, policy.get_event_loop)
@ -2730,7 +2742,7 @@ def test_get_event_loop_after_set_none(self):
def test_get_event_loop_thread(self, m_current_thread): def test_get_event_loop_thread(self, m_current_thread):
def f(): def f():
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
self.assertRaises(RuntimeError, policy.get_event_loop) self.assertRaises(RuntimeError, policy.get_event_loop)
th = threading.Thread(target=f) th = threading.Thread(target=f)
@ -2738,14 +2750,14 @@ def f():
th.join() th.join()
def test_new_event_loop(self): def test_new_event_loop(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
loop = policy.new_event_loop() loop = policy.new_event_loop()
self.assertIsInstance(loop, asyncio.AbstractEventLoop) self.assertIsInstance(loop, asyncio.AbstractEventLoop)
loop.close() loop.close()
def test_set_event_loop(self): def test_set_event_loop(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
old_loop = policy.new_event_loop() old_loop = policy.new_event_loop()
policy.set_event_loop(old_loop) policy.set_event_loop(old_loop)
@ -2762,7 +2774,7 @@ def test_get_event_loop_policy(self):
with self.assertWarnsRegex( with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.get_event_loop_policy' is deprecated"): DeprecationWarning, "'asyncio.get_event_loop_policy' is deprecated"):
policy = asyncio.get_event_loop_policy() policy = asyncio.get_event_loop_policy()
self.assertIsInstance(policy, asyncio.AbstractEventLoopPolicy) self.assertIsInstance(policy, asyncio._AbstractEventLoopPolicy)
self.assertIs(policy, asyncio.get_event_loop_policy()) self.assertIs(policy, asyncio.get_event_loop_policy())
def test_set_event_loop_policy(self): def test_set_event_loop_policy(self):
@ -2775,7 +2787,7 @@ def test_set_event_loop_policy(self):
DeprecationWarning, "'asyncio.get_event_loop_policy' is deprecated"): DeprecationWarning, "'asyncio.get_event_loop_policy' is deprecated"):
old_policy = asyncio.get_event_loop_policy() old_policy = asyncio.get_event_loop_policy()
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio._DefaultEventLoopPolicy()
with self.assertWarnsRegex( with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.set_event_loop_policy' is deprecated"): DeprecationWarning, "'asyncio.set_event_loop_policy' is deprecated"):
asyncio.set_event_loop_policy(policy) asyncio.set_event_loop_policy(policy)
@ -2862,7 +2874,7 @@ def test_get_event_loop_returns_running_loop(self):
class TestError(Exception): class TestError(Exception):
pass pass
class Policy(asyncio.DefaultEventLoopPolicy): class Policy(asyncio._DefaultEventLoopPolicy):
def get_event_loop(self): def get_event_loop(self):
raise TestError raise TestError
@ -2908,7 +2920,7 @@ async def func():
def test_get_event_loop_returns_running_loop2(self): def test_get_event_loop_returns_running_loop2(self):
old_policy = asyncio._get_event_loop_policy() old_policy = asyncio._get_event_loop_policy()
try: try:
asyncio._set_event_loop_policy(asyncio.DefaultEventLoopPolicy()) asyncio._set_event_loop_policy(asyncio._DefaultEventLoopPolicy())
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
self.addCleanup(loop.close) self.addCleanup(loop.close)

View File

@ -19,7 +19,7 @@ def interrupt_self():
_thread.interrupt_main() _thread.interrupt_main()
class TestPolicy(asyncio.AbstractEventLoopPolicy): class TestPolicy(asyncio._AbstractEventLoopPolicy):
def __init__(self, loop_factory): def __init__(self, loop_factory):
self.loop_factory = loop_factory self.loop_factory = loop_factory

View File

@ -328,14 +328,15 @@ class WinPolicyTests(WindowsEventsTestCase):
def test_selector_win_policy(self): def test_selector_win_policy(self):
async def main(): async def main():
self.assertIsInstance( self.assertIsInstance(asyncio.get_running_loop(), asyncio.SelectorEventLoop)
asyncio.get_running_loop(),
asyncio.SelectorEventLoop)
old_policy = asyncio._get_event_loop_policy() old_policy = asyncio._get_event_loop_policy()
try: try:
asyncio._set_event_loop_policy( with self.assertWarnsRegex(
asyncio.WindowsSelectorEventLoopPolicy()) DeprecationWarning,
"'asyncio.WindowsSelectorEventLoopPolicy' is deprecated",
):
asyncio._set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main()) asyncio.run(main())
finally: finally:
asyncio._set_event_loop_policy(old_policy) asyncio._set_event_loop_policy(old_policy)
@ -348,8 +349,11 @@ async def main():
old_policy = asyncio._get_event_loop_policy() old_policy = asyncio._get_event_loop_policy()
try: try:
asyncio._set_event_loop_policy( with self.assertWarnsRegex(
asyncio.WindowsProactorEventLoopPolicy()) DeprecationWarning,
"'asyncio.WindowsProactorEventLoopPolicy' is deprecated",
):
asyncio._set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
asyncio.run(main()) asyncio.run(main())
finally: finally:
asyncio._set_event_loop_policy(old_policy) asyncio._set_event_loop_policy(old_policy)