Message346150
> BUT I think removing the `if getattr(obj, '__code__', None)` from `_is_async_obj` actually makes this work correctly. It is possible for a coroutine object to not have a __code__, but I don't think it is possible for a coroutine function to be missing a __code__. Sorry, I am little confused here. If the code attribute check is removed then my test case in PR fails since obj.__code__ that is passed through iscoroutinefunction returns True. Maybe something along the lines of below that if there is a __code__ attribute then always check it's of CodeType. So that my test passes with MagicMock.__code__ detected. If I understand the awaitable examples correctly, mocking the obj which is an Awaitable should be returning an AsyncMock. But obj doesn't contain __code__ and hence check for inspect.isawaitable is never done causing _is_async_obj(obj) to return False and subsequently it's patched with MagicMock. from collections.abc import Awaitable from unittest.mock import patch class NewCoroutine(Awaitable): def __await__(): pass obj = NewCoroutine() with patch(f"{__name__}.obj") as m: print(m) $ ./python.exe ../backups/bpo37251_awaitable.py <MagicMock name='obj' id='4552158896'> On removing the __code__ attribute check my test case of MagicMock with __code__ passes through iscoroutinefunction. Perhaps an acceptable tradeoff would be to check for __code__ and if present to be a CodeType or else to resume normal check like below. This way an AsyncMock is returned. Also there is no test failure. I have less understanding on asyncio terminologies over coroutine and awaitables so feel free to correct me if I am wrong. I guess it would be also helpful to have good number of tests for different asyncio object cases so that this could also be documented. $ ./python.exe ../backups/bpo37251_awaitable.py <AsyncMock name='obj' id='4363294672'> # _is_async_obj to check for __code__ to be CodeType only if present. def _is_async_obj(obj): code = getattr(obj, '__code__', None) if code and not isinstance(code, CodeType): return False return asyncio.iscoroutinefunction(obj) or inspect.isawaitable(obj) # Also verified asyncio.sleep() to return True for _is_async_obj with above definition >>> from unittest.mock import _is_async_func, _is_async_obj >>> import asyncio >>> _is_async_obj(asyncio.sleep(1)) <stdin>:1: RuntimeWarning: coroutine 'sleep' was never awaited RuntimeWarning: Enable tracemalloc to get the object allocation traceback True | |
| Date | User | Action | Args | | 2019-06-20 18:11:12 | xtreak | set | recipients: + xtreak, lisroach, hroncok, mariocj89, jcline | | 2019-06-20 18:11:12 | xtreak | set | messageid: <1561054272.37.0.489639313573.issue37251@roundup.psfhosted.org> | | 2019-06-20 18:11:12 | xtreak | link | issue37251 messages | | 2019-06-20 18:11:12 | xtreak | create | | |