gh-127949: deprecate asyncio.set_event_loop (#128218)

Deprecate `asyncio.set_event_loop` to be removed in Python 3.16.
This commit is contained in:
Kumar Aditya 2024-12-24 19:24:28 +05:30 committed by GitHub
parent 3ddd70ceaa
commit 9fce906825
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 77 additions and 55 deletions

View file

@ -66,6 +66,10 @@ an event loop:
Set *loop* as the current event loop for the current OS thread. Set *loop* as the current event loop for the current OS thread.
.. deprecated:: next
The :func:`set_event_loop` function is deprecated and will be removed
in Python 3.16.
.. function:: new_event_loop() .. function:: new_event_loop()
Create and return a new event loop object. Create and return a new event loop object.

View file

@ -149,7 +149,7 @@ if __name__ == '__main__':
return_code = 0 return_code = 0
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
repl_locals = {'asyncio': asyncio} repl_locals = {'asyncio': asyncio}
for key in {'__name__', '__package__', for key in {'__name__', '__package__',

View file

@ -5,16 +5,22 @@
# 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",
'Handle', 'TimerHandle', "AbstractServer",
'_get_event_loop_policy', "Handle",
'get_event_loop_policy', "TimerHandle",
'_set_event_loop_policy', "_get_event_loop_policy",
'set_event_loop_policy', "get_event_loop_policy",
'get_event_loop', 'set_event_loop', 'new_event_loop', "_set_event_loop_policy",
'_set_running_loop', 'get_running_loop', "set_event_loop_policy",
'_get_running_loop', "get_event_loop",
"_set_event_loop",
"set_event_loop",
"new_event_loop",
"_set_running_loop",
"get_running_loop",
"_get_running_loop",
) )
import contextvars import contextvars
@ -801,9 +807,13 @@ def get_event_loop():
return _get_event_loop_policy().get_event_loop() return _get_event_loop_policy().get_event_loop()
def _set_event_loop(loop):
_get_event_loop_policy().set_event_loop(loop)
def set_event_loop(loop): def set_event_loop(loop):
"""Equivalent to calling get_event_loop_policy().set_event_loop(loop).""" """Equivalent to calling get_event_loop_policy().set_event_loop(loop)."""
_get_event_loop_policy().set_event_loop(loop) warnings._deprecated('asyncio.set_event_loop', remove=(3,16))
_set_event_loop(loop)
def new_event_loop(): def new_event_loop():

View file

@ -74,7 +74,7 @@ class Runner:
loop.shutdown_default_executor(constants.THREAD_JOIN_TIMEOUT)) loop.shutdown_default_executor(constants.THREAD_JOIN_TIMEOUT))
finally: finally:
if self._set_event_loop: if self._set_event_loop:
events.set_event_loop(None) events._set_event_loop(None)
loop.close() loop.close()
self._loop = None self._loop = None
self._state = _State.CLOSED self._state = _State.CLOSED
@ -147,7 +147,7 @@ class Runner:
if not self._set_event_loop: if not self._set_event_loop:
# Call set_event_loop only once to avoid calling # Call set_event_loop only once to avoid calling
# attach_loop multiple times on child watchers # attach_loop multiple times on child watchers
events.set_event_loop(self._loop) events._set_event_loop(self._loop)
self._set_event_loop = True self._set_event_loop = True
else: else:
self._loop = self._loop_factory() self._loop = self._loop_factory()

View file

@ -624,7 +624,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.loop = asyncio.new_event_loop() self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
def tearDown(self): def tearDown(self):
self.loop.close() self.loop.close()

View file

@ -24,7 +24,7 @@ class FunctionalTestCaseMixin:
def setUp(self): def setUp(self):
self.loop = self.new_loop() self.loop = self.new_loop()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
self.loop.set_exception_handler(self.loop_exception_handler) self.loop.set_exception_handler(self.loop_exception_handler)
self.__unhandled_exceptions = [] self.__unhandled_exceptions = []
@ -39,7 +39,7 @@ class FunctionalTestCaseMixin:
self.fail('unexpected calls to loop.call_exception_handler()') self.fail('unexpected calls to loop.call_exception_handler()')
finally: finally:
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
self.loop = None self.loop = None
def tcp_server(self, server_prog, *, def tcp_server(self, server_prog, *,

View file

@ -331,10 +331,10 @@ class BaseEventLoopTests(test_utils.TestCase):
if create_loop: if create_loop:
loop2 = base_events.BaseEventLoop() loop2 = base_events.BaseEventLoop()
try: try:
asyncio.set_event_loop(loop2) asyncio._set_event_loop(loop2)
self.check_thread(loop, debug) self.check_thread(loop, debug)
finally: finally:
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
loop2.close() loop2.close()
else: else:
self.check_thread(loop, debug) self.check_thread(loop, debug)
@ -690,7 +690,7 @@ class BaseEventLoopTests(test_utils.TestCase):
loop = Loop() loop = Loop()
self.addCleanup(loop.close) self.addCleanup(loop.close)
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
def run_loop(): def run_loop():
def zero_error(): def zero_error():
@ -1983,7 +1983,7 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
async def stop_loop_coro(loop): async def stop_loop_coro(loop):
loop.stop() loop.stop()
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
self.loop.set_debug(True) self.loop.set_debug(True)
self.loop.slow_callback_duration = 0.0 self.loop.slow_callback_duration = 0.0

View file

@ -58,7 +58,7 @@ def _test_get_event_loop_new_process__sub_proc():
return 'hello' return 'hello'
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
return loop.run_until_complete(doit()) return loop.run_until_complete(doit())
@ -2695,6 +2695,14 @@ class AbstractEventLoopTests(unittest.TestCase):
class PolicyTests(unittest.TestCase): class PolicyTests(unittest.TestCase):
def test_asyncio_set_event_loop_deprecation(self):
with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.set_event_loop' is deprecated"):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
self.assertIs(loop, asyncio.get_event_loop())
loop.close()
def test_abstract_event_loop_policy_deprecation(self): def test_abstract_event_loop_policy_deprecation(self):
with self.assertWarnsRegex( with self.assertWarnsRegex(
DeprecationWarning, "'asyncio.AbstractEventLoopPolicy' is deprecated"): DeprecationWarning, "'asyncio.AbstractEventLoopPolicy' is deprecated"):
@ -2824,14 +2832,14 @@ class GetEventLoopTestsMixin:
super().setUp() super().setUp()
self.loop = asyncio.new_event_loop() self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
def tearDown(self): def tearDown(self):
try: try:
super().tearDown() super().tearDown()
finally: finally:
self.loop.close() self.loop.close()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
events._get_running_loop = self._get_running_loop_saved events._get_running_loop = self._get_running_loop_saved
events._set_running_loop = self._set_running_loop_saved events._set_running_loop = self._set_running_loop_saved
@ -2885,7 +2893,7 @@ class GetEventLoopTestsMixin:
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
@ -2900,10 +2908,10 @@ class GetEventLoopTestsMixin:
loop.run_until_complete(func()) loop.run_until_complete(func())
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
@ -2927,7 +2935,7 @@ class GetEventLoopTestsMixin:
with self.assertRaisesRegex(RuntimeError, 'no current'): with self.assertRaisesRegex(RuntimeError, 'no current'):
asyncio.get_event_loop() asyncio.get_event_loop()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
with self.assertRaisesRegex(RuntimeError, 'no current'): with self.assertRaisesRegex(RuntimeError, 'no current'):
asyncio.get_event_loop() asyncio.get_event_loop()
@ -2938,10 +2946,10 @@ class GetEventLoopTestsMixin:
loop.run_until_complete(func()) loop.run_until_complete(func())
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
self.assertIs(asyncio.get_event_loop(), loop) self.assertIs(asyncio.get_event_loop(), loop)
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
with self.assertRaisesRegex(RuntimeError, 'no current'): with self.assertRaisesRegex(RuntimeError, 'no current'):
asyncio.get_event_loop() asyncio.get_event_loop()

View file

@ -178,8 +178,8 @@ class BaseFutureTests:
def test_constructor_use_global_loop(self): def test_constructor_use_global_loop(self):
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
f = self._new_future() f = self._new_future()
self.assertIs(f._loop, self.loop) self.assertIs(f._loop, self.loop)
self.assertIs(f.get_loop(), self.loop) self.assertIs(f.get_loop(), self.loop)
@ -566,8 +566,8 @@ class BaseFutureTests:
def test_wrap_future_use_global_loop(self): def test_wrap_future_use_global_loop(self):
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
def run(arg): def run(arg):
return (arg, threading.get_ident()) return (arg, threading.get_ident())
ex = concurrent.futures.ThreadPoolExecutor(1) ex = concurrent.futures.ThreadPoolExecutor(1)

View file

@ -71,7 +71,7 @@ class StreamTests(test_utils.TestCase):
try: try:
reader, writer = self.loop.run_until_complete(open_connection_fut) reader, writer = self.loop.run_until_complete(open_connection_fut)
finally: finally:
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
writer.write(b'GET / HTTP/1.0\r\n\r\n') writer.write(b'GET / HTTP/1.0\r\n\r\n')
f = reader.read() f = reader.read()
data = self.loop.run_until_complete(f) data = self.loop.run_until_complete(f)
@ -839,8 +839,8 @@ class StreamTests(test_utils.TestCase):
# asyncio issue #184: Ensure that StreamReaderProtocol constructor # asyncio issue #184: Ensure that StreamReaderProtocol constructor
# retrieves the current loop if the loop parameter is not set # retrieves the current loop if the loop parameter is not set
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
reader = asyncio.StreamReader() reader = asyncio.StreamReader()
self.assertIs(reader._loop, self.loop) self.assertIs(reader._loop, self.loop)
@ -863,8 +863,8 @@ class StreamTests(test_utils.TestCase):
# asyncio issue #184: Ensure that StreamReaderProtocol constructor # asyncio issue #184: Ensure that StreamReaderProtocol constructor
# retrieves the current loop if the loop parameter is not set # retrieves the current loop if the loop parameter is not set
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
reader = mock.Mock() reader = mock.Mock()
protocol = asyncio.StreamReaderProtocol(reader) protocol = asyncio.StreamReaderProtocol(reader)
self.assertIs(protocol._loop, self.loop) self.assertIs(protocol._loop, self.loop)

View file

@ -212,8 +212,8 @@ class BaseTaskTests:
self.assertEqual(t.result(), 'ok') self.assertEqual(t.result(), 'ok')
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
t = asyncio.ensure_future(notmuch()) t = asyncio.ensure_future(notmuch())
self.assertIs(t._loop, self.loop) self.assertIs(t._loop, self.loop)
self.loop.run_until_complete(t) self.loop.run_until_complete(t)
@ -2202,8 +2202,8 @@ class BaseTaskTests:
async def coro(): async def coro():
return 42 return 42
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
outer = asyncio.shield(coro()) outer = asyncio.shield(coro())
self.assertEqual(outer._loop, self.loop) self.assertEqual(outer._loop, self.loop)
res = self.loop.run_until_complete(outer) res = self.loop.run_until_complete(outer)
@ -2273,7 +2273,7 @@ class BaseTaskTests:
self.assertEqual(self.all_tasks(loop=self.loop), {task}) self.assertEqual(self.all_tasks(loop=self.loop), {task})
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
# execute the task so it waits for future # execute the task so it waits for future
self.loop._run_once() self.loop._run_once()
@ -3278,8 +3278,8 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
def test_constructor_empty_sequence_use_global_loop(self): def test_constructor_empty_sequence_use_global_loop(self):
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
asyncio.set_event_loop(self.one_loop) asyncio._set_event_loop(self.one_loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
fut = asyncio.gather() fut = asyncio.gather()
self.assertIsInstance(fut, asyncio.Future) self.assertIsInstance(fut, asyncio.Future)
self.assertIs(fut._loop, self.one_loop) self.assertIs(fut._loop, self.one_loop)
@ -3386,8 +3386,8 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
# Deprecated in 3.10, undeprecated in 3.12 # Deprecated in 3.10, undeprecated in 3.12
async def coro(): async def coro():
return 'abc' return 'abc'
asyncio.set_event_loop(self.other_loop) asyncio._set_event_loop(self.other_loop)
self.addCleanup(asyncio.set_event_loop, None) self.addCleanup(asyncio._set_event_loop, None)
gen1 = coro() gen1 = coro()
gen2 = coro() gen2 = coro()
fut = asyncio.gather(gen1, gen2) fut = asyncio.gather(gen1, gen2)

View file

@ -1116,11 +1116,11 @@ class TestFunctional(unittest.TestCase):
def setUp(self): def setUp(self):
self.loop = asyncio.new_event_loop() self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop) asyncio._set_event_loop(self.loop)
def tearDown(self): def tearDown(self):
self.loop.close() self.loop.close()
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
def test_add_reader_invalid_argument(self): def test_add_reader_invalid_argument(self):
def assert_raises(): def assert_raises():

View file

@ -541,7 +541,7 @@ class TestCase(unittest.TestCase):
if loop is None: if loop is None:
raise AssertionError('loop is None') raise AssertionError('loop is None')
# ensure that the event loop is passed explicitly in asyncio # ensure that the event loop is passed explicitly in asyncio
events.set_event_loop(None) events._set_event_loop(None)
if cleanup: if cleanup:
self.addCleanup(self.close_loop, loop) self.addCleanup(self.close_loop, loop)
@ -554,7 +554,7 @@ class TestCase(unittest.TestCase):
self._thread_cleanup = threading_helper.threading_setup() self._thread_cleanup = threading_helper.threading_setup()
def tearDown(self): def tearDown(self):
events.set_event_loop(None) events._set_event_loop(None)
# Detect CPython bug #23353: ensure that yield/yield-from is not used # Detect CPython bug #23353: ensure that yield/yield-from is not used
# in an except block of a generator # in an except block of a generator

View file

@ -2287,7 +2287,7 @@ class CoroAsyncIOCompatTest(unittest.TestCase):
buffer.append('unreachable') buffer.append('unreachable')
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio._set_event_loop(loop)
try: try:
loop.run_until_complete(f()) loop.run_until_complete(f())
except MyException: except MyException:

View file

@ -1060,7 +1060,7 @@ class TypeParamsTypeVarTest(unittest.TestCase):
co = get_coroutine() co = get_coroutine()
self.addCleanup(asyncio.set_event_loop_policy, None) self.addCleanup(asyncio._set_event_loop_policy, None)
a, b = asyncio.run(co()) a, b = asyncio.run(co())
self.assertIsInstance(a, TypeVar) self.assertIsInstance(a, TypeVar)

View file

@ -476,7 +476,7 @@ class TestAsyncCase(unittest.TestCase):
def test_setup_get_event_loop(self): def test_setup_get_event_loop(self):
# See https://github.com/python/cpython/issues/95736 # See https://github.com/python/cpython/issues/95736
# Make sure the default event loop is not used # Make sure the default event loop is not used
asyncio.set_event_loop(None) asyncio._set_event_loop(None)
class TestCase1(unittest.IsolatedAsyncioTestCase): class TestCase1(unittest.IsolatedAsyncioTestCase):
def setUp(self): def setUp(self):