From 0ed7c5062e8a4be1b383b640d50b68c181d6c3be Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 12 Oct 2023 16:06:25 +0100 Subject: [PATCH 1/4] allow setting the Runner(loop_factory=...) from IsolatedAsyncioTestCase --- Lib/unittest/async_case.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index bd2a471156065b..63ff6a5d1f8b61 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -25,12 +25,15 @@ class IsolatedAsyncioTestCase(TestCase): # them inside the same task. # Note: the test case modifies event loop policy if the policy was not instantiated - # yet. + # yet, unless loop_factory=asyncio.EventLoop is set. # asyncio.get_event_loop_policy() creates a default policy on demand but never # returns None # I believe this is not an issue in user level tests but python itself for testing # should reset a policy in every test module # by calling asyncio.set_event_loop_policy(None) in tearDownModule() + # or set loop_factory=asyncio.EventLoop + + loop_factory = None def __init__(self, methodName='runTest'): super().__init__(methodName) @@ -118,7 +121,7 @@ def _callMaybeAsync(self, func, /, *args, **kwargs): def _setupAsyncioRunner(self): assert self._asyncioRunner is None, 'asyncio runner is already initialized' - runner = asyncio.Runner(debug=True) + runner = asyncio.Runner(debug=True, loop_factory=self.loop_factory) self._asyncioRunner = runner def _tearDownAsyncioRunner(self): From 216dc96866632e6502a0c8832f6c112750065616 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 12 Oct 2023 16:10:34 +0100 Subject: [PATCH 2/4] test IsolatedAsyncioTestCase.loop_factory --- Lib/test/test_unittest/test_async_case.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_unittest/test_async_case.py b/Lib/test/test_unittest/test_async_case.py index a465103b59b6ec..ba1ab838cd4a22 100644 --- a/Lib/test/test_unittest/test_async_case.py +++ b/Lib/test/test_unittest/test_async_case.py @@ -484,5 +484,19 @@ async def test_demo1(self): result = test.run() self.assertTrue(result.wasSuccessful()) + def test_loop_factory(self): + asyncio.set_event_loop_policy(None) + + class TestCase1(unittest.IsolatedAsyncioTestCase): + loop_factory = asyncio.EventLoop + + async def test_demo1(self): + pass + + test = TestCase1('test_demo1') + result = test.run() + self.assertTrue(result.wasSuccessful()) + self.assertIsNone(support.maybe_get_event_loop_policy()) + if __name__ == "__main__": unittest.main() From a05085f90aa406fc4ff38d1ff92f479f6a4ff6cb Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 12 Oct 2023 16:14:41 +0100 Subject: [PATCH 3/4] document loop_factory attribute --- Doc/library/unittest.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 21abc583f853a7..c90c554591e748 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1571,6 +1571,14 @@ Test cases .. versionadded:: 3.8 + .. attribute:: loop_factory + + The *loop_factory* passed to :class:`asyncio.Runner`. Override + in subclasses with :class:`asyncio.EventLoop` to avoid using the + asyncio policy system. + + .. versionadded:: 3.13 + .. coroutinemethod:: asyncSetUp() Method called to prepare the test fixture. This is called after :meth:`setUp`. From 0fbb8943b73cb332cd1c1a928995f8e61d7a5c7f Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:16:48 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst diff --git a/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst b/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst new file mode 100644 index 00000000000000..a5a9fed11864d6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst @@ -0,0 +1 @@ +Support setting the :class:`asyncio.Runner` loop_factory kwarg in :class:`unittest.IsolatedAsyncioTestCase`