[3.11] gh-93453: Only emit deprecation warning in asyncio.get_event_loop when a new event loop is created (#99949)

It no longer emits a deprecation warning if the current event loop was set.

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
Serhiy Storchaka 2022-12-06 17:15:44 +02:00 committed by GitHub
parent 235f5fd2ca
commit 3fae04b10e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 109 additions and 123 deletions

View file

@ -43,10 +43,12 @@ an event loop:
Get the current event loop. Get the current event loop.
If there is no current event loop set in the current OS thread, When called from a coroutine or a callback (e.g. scheduled with
the OS thread is main, and :func:`set_event_loop` has not yet call_soon or similar API), this function will always return the
been called, asyncio will create a new event loop and set it as the running event loop.
current one.
If there is no running event loop set, the function will return
the result of ``get_event_loop_policy().get_event_loop()`` call.
Because this function has rather complex behavior (especially Because this function has rather complex behavior (especially
when custom event loop policies are in use), using the when custom event loop policies are in use), using the
@ -58,10 +60,14 @@ an event loop:
event loop. event loop.
.. deprecated:: 3.10 .. deprecated:: 3.10
Emits a deprecation warning if there is no running event loop. Deprecation warning is emitted if there is no current event loop.
In future Python releases, this function may become an alias of In Python 3.12 it will be an error.
:func:`get_running_loop` and will accordingly raise a
:exc:`RuntimeError` if there is no running event loop. .. note::
In Python versions 3.10.0--3.10.8 and 3.11.0 this function
(and other functions which used it implicitly) emitted a
:exc:`DeprecationWarning` if there was no running event loop, even if
the current loop was set.
.. function:: set_event_loop(loop) .. function:: set_event_loop(loop)

View file

@ -19,7 +19,7 @@ Obtaining the Event Loop
- The **preferred** function to get the running event loop. - The **preferred** function to get the running event loop.
* - :func:`asyncio.get_event_loop` * - :func:`asyncio.get_event_loop`
- Get an event loop instance (current or via the policy). - Get an event loop instance (running or current via the current policy).
* - :func:`asyncio.set_event_loop` * - :func:`asyncio.set_event_loop`
- Set the event loop as current via the current policy. - Set the event loop as current via the current policy.

View file

@ -112,6 +112,11 @@ asyncio ships with the following built-in policies:
On Windows, :class:`ProactorEventLoop` is now used by default. On Windows, :class:`ProactorEventLoop` is now used by default.
.. deprecated:: 3.11.1
:meth:`get_event_loop` now emits a :exc:`DeprecationWarning` if there
is no current event loop set and a new event loop has been implicitly
created. In Python 3.12 it will be an error.
.. class:: WindowsSelectorEventLoopPolicy .. class:: WindowsSelectorEventLoopPolicy

View file

@ -671,6 +671,21 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
if (self._local._loop is None and if (self._local._loop is None and
not self._local._set_called and not self._local._set_called and
threading.current_thread() is threading.main_thread()): threading.current_thread() is threading.main_thread()):
stacklevel = 2
try:
f = sys._getframe(1)
except AttributeError:
pass
else:
while f:
module = f.f_globals.get('__name__')
if not (module == 'asyncio' or module.startswith('asyncio.')):
break
f = f.f_back
stacklevel += 1
import warnings
warnings.warn('There is no current event loop',
DeprecationWarning, stacklevel=stacklevel)
self.set_event_loop(self.new_event_loop()) self.set_event_loop(self.new_event_loop())
if self._local._loop is None: if self._local._loop is None:
@ -786,12 +801,13 @@ def get_event_loop():
def _get_event_loop(stacklevel=3): def _get_event_loop(stacklevel=3):
# This internal method is going away in Python 3.12, left here only for
# backwards compatibility with 3.10.0 - 3.10.8 and 3.11.0.
# Similarly, this method's C equivalent in _asyncio is going away as well.
# See GH-99949 for more details.
current_loop = _get_running_loop() current_loop = _get_running_loop()
if current_loop is not None: if current_loop is not None:
return current_loop return current_loop
import warnings
warnings.warn('There is no current event loop',
DeprecationWarning, stacklevel=stacklevel)
return get_event_loop_policy().get_event_loop() return get_event_loop_policy().get_event_loop()

View file

@ -746,7 +746,7 @@ class BaseEventLoopTests(test_utils.TestCase):
def test_env_var_debug(self): def test_env_var_debug(self):
code = '\n'.join(( code = '\n'.join((
'import asyncio', 'import asyncio',
'loop = asyncio.get_event_loop()', 'loop = asyncio.new_event_loop()',
'print(loop.get_debug())')) 'print(loop.get_debug())'))
# Test with -E to not fail if the unit test was run with # Test with -E to not fail if the unit test was run with

View file

@ -2547,8 +2547,9 @@ class PolicyTests(unittest.TestCase):
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.assertWarns(DeprecationWarning) as cm:
loop = policy.get_event_loop() loop = policy.get_event_loop()
self.assertEqual(cm.filename, __file__)
self.assertIsInstance(loop, asyncio.AbstractEventLoop) self.assertIsInstance(loop, asyncio.AbstractEventLoop)
self.assertIs(policy._local._loop, loop) self.assertIs(policy._local._loop, loop)
@ -2562,7 +2563,10 @@ class PolicyTests(unittest.TestCase):
policy, "set_event_loop", policy, "set_event_loop",
wraps=policy.set_event_loop) as m_set_event_loop: wraps=policy.set_event_loop) as m_set_event_loop:
with self.assertWarns(DeprecationWarning) as cm:
loop = policy.get_event_loop() loop = policy.get_event_loop()
self.addCleanup(loop.close)
self.assertEqual(cm.filename, __file__)
# policy._local._loop must be set through .set_event_loop() # policy._local._loop must be set through .set_event_loop()
# (the unix DefaultEventLoopPolicy needs this call to attach # (the unix DefaultEventLoopPolicy needs this call to attach
@ -2596,7 +2600,8 @@ class PolicyTests(unittest.TestCase):
def test_set_event_loop(self): def test_set_event_loop(self):
policy = asyncio.DefaultEventLoopPolicy() policy = asyncio.DefaultEventLoopPolicy()
old_loop = policy.get_event_loop() old_loop = policy.new_event_loop()
policy.set_event_loop(old_loop)
self.assertRaises(TypeError, policy.set_event_loop, object()) self.assertRaises(TypeError, policy.set_event_loop, object())
@ -2709,15 +2714,11 @@ class GetEventLoopTestsMixin:
asyncio.set_event_loop_policy(Policy()) asyncio.set_event_loop_policy(Policy())
loop = asyncio.new_event_loop() loop = asyncio.new_event_loop()
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
asyncio.set_event_loop(None) asyncio.set_event_loop(None)
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
with self.assertRaisesRegex(RuntimeError, 'no running'): with self.assertRaisesRegex(RuntimeError, 'no running'):
asyncio.get_running_loop() asyncio.get_running_loop()
@ -2731,16 +2732,11 @@ class GetEventLoopTestsMixin:
loop.run_until_complete(func()) loop.run_until_complete(func())
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
asyncio.set_event_loop(None) asyncio.set_event_loop(None)
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaises(TestError): with self.assertRaises(TestError):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
finally: finally:
asyncio.set_event_loop_policy(old_policy) asyncio.set_event_loop_policy(old_policy)
@ -2764,10 +2760,8 @@ class GetEventLoopTestsMixin:
self.addCleanup(loop2.close) self.addCleanup(loop2.close)
self.assertEqual(cm.filename, __file__) self.assertEqual(cm.filename, __file__)
asyncio.set_event_loop(None) asyncio.set_event_loop(None)
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaisesRegex(RuntimeError, 'no current'): with self.assertRaisesRegex(RuntimeError, 'no current'):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
with self.assertRaisesRegex(RuntimeError, 'no running'): with self.assertRaisesRegex(RuntimeError, 'no running'):
asyncio.get_running_loop() asyncio.get_running_loop()
@ -2781,15 +2775,11 @@ class GetEventLoopTestsMixin:
loop.run_until_complete(func()) loop.run_until_complete(func())
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
with self.assertWarns(DeprecationWarning) as cm:
self.assertIs(asyncio.get_event_loop(), loop) self.assertIs(asyncio.get_event_loop(), loop)
self.assertEqual(cm.filename, __file__)
asyncio.set_event_loop(None) asyncio.set_event_loop(None)
with self.assertWarns(DeprecationWarning) as cm:
with self.assertRaisesRegex(RuntimeError, 'no current'): with self.assertRaisesRegex(RuntimeError, 'no current'):
asyncio.get_event_loop() asyncio.get_event_loop()
self.assertEqual(cm.filename, __file__)
finally: finally:
asyncio.set_event_loop_policy(old_policy) asyncio.set_event_loop_policy(old_policy)

View file

@ -145,10 +145,8 @@ class BaseFutureTests:
self.assertTrue(f.cancelled()) self.assertTrue(f.cancelled())
def test_constructor_without_loop(self): def test_constructor_without_loop(self):
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
self._new_future() self._new_future()
self.assertEqual(cm.filename, __file__)
def test_constructor_use_running_loop(self): def test_constructor_use_running_loop(self):
async def test(): async def test():
@ -158,12 +156,10 @@ class BaseFutureTests:
self.assertIs(f.get_loop(), self.loop) self.assertIs(f.get_loop(), self.loop)
def test_constructor_use_global_loop(self): def test_constructor_use_global_loop(self):
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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)
with self.assertWarns(DeprecationWarning) as cm:
f = self._new_future() f = self._new_future()
self.assertEqual(cm.filename, __file__)
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)
@ -499,10 +495,8 @@ class BaseFutureTests:
return (arg, threading.get_ident()) return (arg, threading.get_ident())
ex = concurrent.futures.ThreadPoolExecutor(1) ex = concurrent.futures.ThreadPoolExecutor(1)
f1 = ex.submit(run, 'oi') f1 = ex.submit(run, 'oi')
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaises(RuntimeError):
asyncio.wrap_future(f1) asyncio.wrap_future(f1)
self.assertEqual(cm.filename, __file__)
ex.shutdown(wait=True) ex.shutdown(wait=True)
def test_wrap_future_use_running_loop(self): def test_wrap_future_use_running_loop(self):
@ -517,16 +511,14 @@ class BaseFutureTests:
ex.shutdown(wait=True) ex.shutdown(wait=True)
def test_wrap_future_use_global_loop(self): def test_wrap_future_use_global_loop(self):
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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)
f1 = ex.submit(run, 'oi') f1 = ex.submit(run, 'oi')
with self.assertWarns(DeprecationWarning) as cm:
f2 = asyncio.wrap_future(f1) f2 = asyncio.wrap_future(f1)
self.assertEqual(cm.filename, __file__)
self.assertIs(self.loop, f2._loop) self.assertIs(self.loop, f2._loop)
ex.shutdown(wait=True) ex.shutdown(wait=True)

View file

@ -810,10 +810,8 @@ os.close(fd)
self.assertEqual(data, b'data') self.assertEqual(data, b'data')
def test_streamreader_constructor_without_loop(self): def test_streamreader_constructor_without_loop(self):
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
asyncio.StreamReader() asyncio.StreamReader()
self.assertEqual(cm.filename, __file__)
def test_streamreader_constructor_use_running_loop(self): def test_streamreader_constructor_use_running_loop(self):
# asyncio issue #184: Ensure that StreamReaderProtocol constructor # asyncio issue #184: Ensure that StreamReaderProtocol constructor
@ -827,21 +825,17 @@ os.close(fd)
def test_streamreader_constructor_use_global_loop(self): def test_streamreader_constructor_use_global_loop(self):
# 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 # Deprecated in 3.10, undeprecated in 3.11.1
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)
with self.assertWarns(DeprecationWarning) as cm:
reader = asyncio.StreamReader() reader = asyncio.StreamReader()
self.assertEqual(cm.filename, __file__)
self.assertIs(reader._loop, self.loop) self.assertIs(reader._loop, self.loop)
def test_streamreaderprotocol_constructor_without_loop(self): def test_streamreaderprotocol_constructor_without_loop(self):
reader = mock.Mock() reader = mock.Mock()
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
asyncio.StreamReaderProtocol(reader) asyncio.StreamReaderProtocol(reader)
self.assertEqual(cm.filename, __file__)
def test_streamreaderprotocol_constructor_use_running_loop(self): def test_streamreaderprotocol_constructor_use_running_loop(self):
# asyncio issue #184: Ensure that StreamReaderProtocol constructor # asyncio issue #184: Ensure that StreamReaderProtocol constructor
@ -855,13 +849,11 @@ os.close(fd)
def test_streamreaderprotocol_constructor_use_global_loop(self): def test_streamreaderprotocol_constructor_use_global_loop(self):
# 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 # Deprecated in 3.10, undeprecated in 3.11.1
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()
with self.assertWarns(DeprecationWarning) as cm:
protocol = asyncio.StreamReaderProtocol(reader) protocol = asyncio.StreamReaderProtocol(reader)
self.assertEqual(cm.filename, __file__)
self.assertIs(protocol._loop, self.loop) self.assertIs(protocol._loop, self.loop)
def test_multiple_drain(self): def test_multiple_drain(self):

View file

@ -200,10 +200,8 @@ class BaseTaskTests:
a = notmuch() a = notmuch()
self.addCleanup(a.close) self.addCleanup(a.close)
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
asyncio.ensure_future(a) asyncio.ensure_future(a)
self.assertEqual(cm.filename, __file__)
async def test(): async def test():
return asyncio.ensure_future(notmuch()) return asyncio.ensure_future(notmuch())
@ -213,12 +211,10 @@ class BaseTaskTests:
self.assertTrue(t.done()) self.assertTrue(t.done())
self.assertEqual(t.result(), 'ok') self.assertEqual(t.result(), 'ok')
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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)
with self.assertWarns(DeprecationWarning) as cm:
t = asyncio.ensure_future(notmuch()) t = asyncio.ensure_future(notmuch())
self.assertEqual(cm.filename, __file__)
self.assertIs(t._loop, self.loop) self.assertIs(t._loop, self.loop)
self.loop.run_until_complete(t) self.loop.run_until_complete(t)
self.assertTrue(t.done()) self.assertTrue(t.done())
@ -1536,10 +1532,8 @@ class BaseTaskTests:
self.addCleanup(a.close) self.addCleanup(a.close)
futs = asyncio.as_completed([a]) futs = asyncio.as_completed([a])
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
list(futs) list(futs)
self.assertEqual(cm.filename, __file__)
def test_as_completed_coroutine_use_running_loop(self): def test_as_completed_coroutine_use_running_loop(self):
loop = self.new_test_loop() loop = self.new_test_loop()
@ -1969,10 +1963,8 @@ class BaseTaskTests:
inner = coro() inner = coro()
self.addCleanup(inner.close) self.addCleanup(inner.close)
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'):
asyncio.shield(inner) asyncio.shield(inner)
self.assertEqual(cm.filename, __file__)
def test_shield_coroutine_use_running_loop(self): def test_shield_coroutine_use_running_loop(self):
async def coro(): async def coro():
@ -1986,15 +1978,13 @@ class BaseTaskTests:
self.assertEqual(res, 42) self.assertEqual(res, 42)
def test_shield_coroutine_use_global_loop(self): def test_shield_coroutine_use_global_loop(self):
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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)
with self.assertWarns(DeprecationWarning) as cm:
outer = asyncio.shield(coro()) outer = asyncio.shield(coro())
self.assertEqual(cm.filename, __file__)
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)
self.assertEqual(res, 42) self.assertEqual(res, 42)
@ -2820,7 +2810,7 @@ class BaseCurrentLoopTests:
self.assertIsNone(asyncio.current_task(loop=self.loop)) self.assertIsNone(asyncio.current_task(loop=self.loop))
def test_current_task_no_running_loop_implicit(self): def test_current_task_no_running_loop_implicit(self):
with self.assertRaises(RuntimeError): with self.assertRaisesRegex(RuntimeError, 'no running event loop'):
asyncio.current_task() asyncio.current_task()
def test_current_task_with_implicit_loop(self): def test_current_task_with_implicit_loop(self):
@ -2984,10 +2974,8 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
return asyncio.gather(*args, **kwargs) return asyncio.gather(*args, **kwargs)
def test_constructor_empty_sequence_without_loop(self): def test_constructor_empty_sequence_without_loop(self):
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaises(RuntimeError):
asyncio.gather() asyncio.gather()
self.assertEqual(cm.filename, __file__)
def test_constructor_empty_sequence_use_running_loop(self): def test_constructor_empty_sequence_use_running_loop(self):
async def gather(): async def gather():
@ -3000,12 +2988,10 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
self.assertEqual(fut.result(), []) self.assertEqual(fut.result(), [])
def test_constructor_empty_sequence_use_global_loop(self): def test_constructor_empty_sequence_use_global_loop(self):
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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)
with self.assertWarns(DeprecationWarning) as cm:
fut = asyncio.gather() fut = asyncio.gather()
self.assertEqual(cm.filename, __file__)
self.assertIsInstance(fut, asyncio.Future) self.assertIsInstance(fut, asyncio.Future)
self.assertIs(fut._loop, self.one_loop) self.assertIs(fut._loop, self.one_loop)
self._run_loop(self.one_loop) self._run_loop(self.one_loop)
@ -3093,10 +3079,8 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
self.addCleanup(gen1.close) self.addCleanup(gen1.close)
gen2 = coro() gen2 = coro()
self.addCleanup(gen2.close) self.addCleanup(gen2.close)
with self.assertWarns(DeprecationWarning) as cm: with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
with self.assertRaises(RuntimeError):
asyncio.gather(gen1, gen2) asyncio.gather(gen1, gen2)
self.assertEqual(cm.filename, __file__)
def test_constructor_use_running_loop(self): def test_constructor_use_running_loop(self):
async def coro(): async def coro():
@ -3110,16 +3094,14 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
self.one_loop.run_until_complete(fut) self.one_loop.run_until_complete(fut)
def test_constructor_use_global_loop(self): def test_constructor_use_global_loop(self):
# Deprecated in 3.10 # Deprecated in 3.10, undeprecated in 3.11.1
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()
with self.assertWarns(DeprecationWarning) as cm:
fut = asyncio.gather(gen1, gen2) fut = asyncio.gather(gen1, gen2)
self.assertEqual(cm.filename, __file__)
self.assertIs(fut._loop, self.other_loop) self.assertIs(fut._loop, self.other_loop)
self.other_loop.run_until_complete(fut) self.other_loop.run_until_complete(fut)

View file

@ -1740,7 +1740,8 @@ class PolicyTests(unittest.TestCase):
def test_child_watcher_replace_mainloop_existing(self): def test_child_watcher_replace_mainloop_existing(self):
policy = self.create_policy() policy = self.create_policy()
loop = policy.get_event_loop() loop = policy.new_event_loop()
policy.set_event_loop(loop)
# Explicitly setup SafeChildWatcher, # Explicitly setup SafeChildWatcher,
# default ThreadedChildWatcher has no _loop property # default ThreadedChildWatcher has no _loop property

View file

@ -2411,7 +2411,8 @@ class UnawaitedWarningDuringShutdownTest(unittest.TestCase):
def test_unawaited_warning_during_shutdown(self): def test_unawaited_warning_during_shutdown(self):
code = ("import asyncio\n" code = ("import asyncio\n"
"async def f(): pass\n" "async def f(): pass\n"
"asyncio.gather(f())\n") "async def t(): asyncio.gather(f())\n"
"asyncio.run(t())\n")
assert_python_ok("-c", code) assert_python_ok("-c", code)
code = ("import sys\n" code = ("import sys\n"

View file

@ -0,0 +1,3 @@
:func:`asyncio.get_event_loop` now only emits a deprecation warning when a
new event loop was created implicitly. It no longer emits a deprecation
warning if the current event loop was set.

View file

@ -339,13 +339,6 @@ get_event_loop(int stacklevel)
return loop; return loop;
} }
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"There is no current event loop",
stacklevel))
{
return NULL;
}
policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy); policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
if (policy == NULL) { if (policy == NULL) {
return NULL; return NULL;
@ -3129,6 +3122,11 @@ _asyncio_get_event_loop_impl(PyObject *module)
return get_event_loop(1); return get_event_loop(1);
} }
// This internal method is going away in Python 3.12, left here only for
// backwards compatibility with 3.10.0 - 3.10.8 and 3.11.0.
// Similarly, this method's Python equivalent in asyncio.events is going
// away as well.
// See GH-99949 for more details.
/*[clinic input] /*[clinic input]
_asyncio._get_event_loop _asyncio._get_event_loop
stacklevel: int = 3 stacklevel: int = 3