From 73b28608fade7ea9826ed7b9108845be517a78f7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 23 Jun 2022 16:06:22 +0200 Subject: [PATCH] gh-94174: asyncio.get_event_loop() fails if no current event loop asyncio.get_event_loop() now fails if there is no current event loop. In Python 3.10, it emits a DeprecationWarning in this case. --- Doc/whatsnew/3.12.rst | 4 ++ Lib/asyncio/events.py | 6 +-- Lib/test/test_asyncio/test_events.py | 47 +++++++------------ ...2-06-23-16-11-20.gh-issue-94174.RwQhUA.rst | 3 ++ Modules/_asynciomodule.c | 20 +------- 5 files changed, 27 insertions(+), 53 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-06-23-16-11-20.gh-issue-94174.RwQhUA.rst diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 8dde1350a7b166..dd25a407ddd487 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -239,6 +239,10 @@ Changes in the Python API to :term:`filesystem encoding and error handler`. Argument files should be encoded in UTF-8 instead of ANSI Codepage on Windows. +* :func:`asyncio.get_event_loop` now fails if there is no current event loop. + In Python 3.10, it emits a :exc:`DeprecationWarning` in this case. + (Contributed by Victor Stinner in :gh:`94174`.) + Build Changes ============= diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 0d26ea545baa5d..44d1946723235a 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -789,10 +789,8 @@ def _get_event_loop(stacklevel=3): current_loop = _get_running_loop() if current_loop is not None: return current_loop - import warnings - warnings.warn('There is no current event loop', - DeprecationWarning, stacklevel=stacklevel) - return get_event_loop_policy().get_event_loop() + raise RuntimeError('There is no current event loop in thread %r.' + % threading.current_thread().name) def set_event_loop(loop): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 80d7152128c469..25b5eb366e8124 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2708,15 +2708,11 @@ def get_event_loop(self): asyncio.set_event_loop_policy(Policy()) loop = asyncio.new_event_loop() - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() with self.assertRaisesRegex(RuntimeError, 'no running'): asyncio.get_running_loop() @@ -2730,16 +2726,12 @@ async def func(): loop.run_until_complete(func()) asyncio.set_event_loop(loop) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() finally: asyncio.set_event_loop_policy(old_policy) @@ -2758,15 +2750,11 @@ def test_get_event_loop_returns_running_loop2(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) - with self.assertWarns(DeprecationWarning) as cm: - loop2 = asyncio.get_event_loop() - self.addCleanup(loop2.close) - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'no current'): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() with self.assertRaisesRegex(RuntimeError, 'no running'): asyncio.get_running_loop() @@ -2780,15 +2768,12 @@ async def func(): loop.run_until_complete(func()) asyncio.set_event_loop(loop) - with self.assertWarns(DeprecationWarning) as cm: - self.assertIs(asyncio.get_event_loop(), loop) - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'no current'): - asyncio.get_event_loop() - self.assertEqual(cm.filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.get_event_loop() finally: asyncio.set_event_loop_policy(old_policy) diff --git a/Misc/NEWS.d/next/Library/2022-06-23-16-11-20.gh-issue-94174.RwQhUA.rst b/Misc/NEWS.d/next/Library/2022-06-23-16-11-20.gh-issue-94174.RwQhUA.rst new file mode 100644 index 00000000000000..d439464c28ee67 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-23-16-11-20.gh-issue-94174.RwQhUA.rst @@ -0,0 +1,3 @@ +:func:`asyncio.get_event_loop` now fails if there is no current event loop. +In Python 3.10, it emits a :exc:`DeprecationWarning` in this case. +Patch by Victor Stinner diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index bb7c5a7c3ec550..8d2d137f9e1c57 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -21,7 +21,6 @@ _Py_IDENTIFIER(_asyncio_future_blocking); _Py_IDENTIFIER(add_done_callback); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); -_Py_IDENTIFIER(get_event_loop); _Py_IDENTIFIER(throw); _Py_IDENTIFIER(_check_future); @@ -330,8 +329,6 @@ static PyObject * get_event_loop(int stacklevel) { PyObject *loop; - PyObject *policy; - if (get_running_loop(&loop)) { return NULL; } @@ -339,21 +336,8 @@ get_event_loop(int stacklevel) return loop; } - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "There is no current event loop", - stacklevel)) - { - return NULL; - } - - policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy); - if (policy == NULL) { - return NULL; - } - - loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop); - Py_DECREF(policy); - return loop; + PyErr_SetString(PyExc_RuntimeError, "There is no current event loop"); + return NULL; }