Control: tag -1 patch On Tue, 31 Mar 2020 11:39:34 +0200 Jonas Smedegaard <jo...@jones.dk> wrote:
Control: https://github.com/Martiusweb/asynctest/issues/132
The upstream issue has a patch fixing the issue that still has not been applied upstream, from my understanding of the code it seems sane enough to be applied downstream in Debian.
https://github.com/nekokatt/asynctest/commit/50225b83c0c5803b06584b173a5df837361cad3b.patch -- Cheers, Andrej
>From 50225b83c0c5803b06584b173a5df837361cad3b Mon Sep 17 00:00:00 2001 From: "Nekoka.tt" <nekoka...@outlook.com> Date: Sun, 14 Jul 2019 13:36:53 +0100 Subject: [PATCH] Addresses #132, addresses #126: coroutine deprecation warnings on py38 and newer. --- asynctest/case.py | 39 +++++++++++++------------------ asynctest/helpers.py | 5 ++-- asynctest/mock.py | 55 +++++++++++++++++++++++++------------------- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/asynctest/case.py b/asynctest/case.py index ac10ad8..275632d 100644 --- a/asynctest/case.py +++ b/asynctest/case.py @@ -353,8 +353,7 @@ def _run_test_method(self, method): if asyncio.iscoroutine(result): self.loop.run_until_complete(result) - @asyncio.coroutine - def doCleanups(self): + async def doCleanups(self): """ Execute all cleanup functions. Normally called for you after tearDown. """ @@ -363,7 +362,7 @@ def doCleanups(self): function, args, kwargs = self._cleanups.pop() with outcome.testPartExecutor(self): if asyncio.iscoroutinefunction(function): - yield from function(*args, **kwargs) + await function(*args, **kwargs) else: function(*args, **kwargs) @@ -377,8 +376,7 @@ def addCleanup(self, function, *args, **kwargs): """ return super().addCleanup(function, *args, **kwargs) - @asyncio.coroutine - def assertAsyncRaises(self, exception, awaitable): + async def assertAsyncRaises(self, exception, awaitable): """ Test that an exception of type ``exception`` is raised when an exception is raised when awaiting ``awaitable``, a future or coroutine. @@ -386,10 +384,9 @@ def assertAsyncRaises(self, exception, awaitable): :see: :meth:`unittest.TestCase.assertRaises()` """ with self.assertRaises(exception): - return (yield from awaitable) + return await awaitable - @asyncio.coroutine - def assertAsyncRaisesRegex(self, exception, regex, awaitable): + async def assertAsyncRaisesRegex(self, exception, regex, awaitable): """ Like :meth:`assertAsyncRaises()` but also tests that ``regex`` matches on the string representation of the raised exception. @@ -397,10 +394,9 @@ def assertAsyncRaisesRegex(self, exception, regex, awaitable): :see: :meth:`unittest.TestCase.assertRaisesRegex()` """ with self.assertRaisesRegex(exception, regex): - return (yield from awaitable) + return await awaitable - @asyncio.coroutine - def assertAsyncWarns(self, warning, awaitable): + async def assertAsyncWarns(self, warning, awaitable): """ Test that a warning is triggered when awaiting ``awaitable``, a future or a coroutine. @@ -408,10 +404,9 @@ def assertAsyncWarns(self, warning, awaitable): :see: :meth:`unittest.TestCase.assertWarns()` """ with self.assertWarns(warning): - return (yield from awaitable) + return await awaitable - @asyncio.coroutine - def assertAsyncWarnsRegex(self, warning, regex, awaitable): + async def assertAsyncWarnsRegex(self, warning, regex, awaitable): """ Like :meth:`assertAsyncWarns()` but also tests that ``regex`` matches on the message of the triggered warning. @@ -419,7 +414,7 @@ def assertAsyncWarnsRegex(self, warning, regex, awaitable): :see: :meth:`unittest.TestCase.assertWarnsRegex()` """ with self.assertWarnsRegex(warning, regex): - return (yield from awaitable) + return await awaitable class FunctionTestCase(TestCase, unittest.FunctionTestCase): @@ -441,8 +436,7 @@ def _init_loop(self): self.loop.time = functools.wraps(self.loop.time)(lambda: self._time) self._time = 0 - @asyncio.coroutine - def advance(self, seconds): + async def advance(self, seconds): """ Fast forward time by a number of ``seconds``. @@ -463,7 +457,7 @@ def advance(self, seconds): raise ValueError( 'Cannot go back in time ({} seconds)'.format(seconds)) - yield from self._drain_loop() + await self._drain_loop() target_time = self._time + seconds while True: @@ -472,10 +466,10 @@ def advance(self, seconds): break self._time = next_time - yield from self._drain_loop() + await self._drain_loop() self._time = target_time - yield from self._drain_loop() + await self._drain_loop() def _next_scheduled(self): try: @@ -483,15 +477,14 @@ def _next_scheduled(self): except IndexError: return None - @asyncio.coroutine - def _drain_loop(self): + async def _drain_loop(self): while True: next_time = self._next_scheduled() if not self.loop._ready and (next_time is None or next_time > self._time): break - yield from asyncio.sleep(0) + await asyncio.sleep(0) self.loop._TestCase_asynctest_ran = True diff --git a/asynctest/helpers.py b/asynctest/helpers.py index ceea160..5312ede 100644 --- a/asynctest/helpers.py +++ b/asynctest/helpers.py @@ -9,8 +9,7 @@ import asyncio -@asyncio.coroutine -def exhaust_callbacks(loop): +async def exhaust_callbacks(loop): """ Run the loop until all ready callbacks are executed. @@ -21,4 +20,4 @@ def exhaust_callbacks(loop): :param loop: event loop """ while loop._ready: - yield from asyncio.sleep(0, loop=loop) + await asyncio.sleep(0, loop=loop) diff --git a/asynctest/mock.py b/asynctest/mock.py index 25b07e5..8e7a2d0 100644 --- a/asynctest/mock.py +++ b/asynctest/mock.py @@ -72,7 +72,7 @@ def _get_async_iter(mock): See: https://www.python.org/dev/peps/pep-0525/#id23 """ - def __aiter__(): + def callback(): return_value = mock.__aiter__._mock_return_value if return_value is DEFAULT: iterator = iter([]) @@ -82,7 +82,11 @@ def __aiter__(): return _AsyncIterator(iterator) if asyncio.iscoroutinefunction(mock.__aiter__): - return asyncio.coroutine(__aiter__) + async def __aiter__(): + return await callback() + else: + def __aiter__(): + return callback() return __aiter__ @@ -369,8 +373,7 @@ class Mock(unittest.mock.Mock, metaclass=MockMetaMixin): For instance: >>> class Foo: - ... @asyncio.coroutine - ... def foo(self): + ... async def foo(self): ... pass ... ... def bar(self): @@ -430,8 +433,7 @@ def __init__(self, mock): self._mock = mock self._condition = None - @asyncio.coroutine - def wait(self, skip=0): + async def wait(self, skip=0): """ Wait for await. @@ -442,10 +444,9 @@ def wait(self, skip=0): def predicate(mock): return mock.await_count > skip - return (yield from self.wait_for(predicate)) + return await self.wait_for(predicate) - @asyncio.coroutine - def wait_next(self, skip=0): + async def wait_next(self, skip=0): """ Wait for the next await. @@ -462,10 +463,9 @@ def wait_next(self, skip=0): def predicate(mock): return mock.await_count > await_count + skip - return (yield from self.wait_for(predicate)) + return await self.wait_for(predicate) - @asyncio.coroutine - def wait_for(self, predicate): + async def wait_for(self, predicate): """ Wait for a given predicate to become True. @@ -476,21 +476,20 @@ def wait_for(self, predicate): condition = self._get_condition() try: - yield from condition.acquire() + await condition.acquire() def _predicate(): return predicate(self._mock) - return (yield from condition.wait_for(_predicate)) + return await condition.wait_for(_predicate) finally: condition.release() - @asyncio.coroutine - def _notify(self): + async def _notify(self): condition = self._get_condition() try: - yield from condition.acquire() + await condition.acquire() condition.notify_all() finally: condition.release() @@ -582,6 +581,13 @@ def __init__(self, *args, **kwargs): self.__dict__['_mock_await_args_list'] = unittest.mock._CallList() def _mock_call(_mock_self, *args, **kwargs): + """Note: + This will return a coroutine that must be awaited. Not awaiting it + will result in a :class:`RuntimeWarning`_. + """ + async def handle_error(error): + return await _raise(error) + try: result = super()._mock_call(*args, **kwargs) except StopIteration as e: @@ -589,24 +595,23 @@ def _mock_call(_mock_self, *args, **kwargs): if side_effect is not None and not callable(side_effect): raise - result = asyncio.coroutine(_raise)(e) + result = handle_error(e) except BaseException as e: - result = asyncio.coroutine(_raise)(e) + result = handle_error(e) _call = _mock_self.call_args - @asyncio.coroutine - def proxy(): + async def proxy(): try: if inspect.isawaitable(result): - return (yield from result) + return await result else: return result finally: _mock_self.await_count += 1 _mock_self.await_args = _call _mock_self.await_args_list.append(_call) - yield from _mock_self.awaited._notify() + await _mock_self.awaited._notify() return proxy() @@ -1005,7 +1010,9 @@ def patched_generator(*args, **kwargs): if is_coroutine_func: # asyncio.iscoroutinefunction() returns True - patched = asyncio.coroutine(patched) + async def async_patched(*args, **kwargs): + return patched(*args, **kwargs) + else: patched = patched_factory