Skip to content

Fix RuntimeWarning in unittest.mock asyncio example #13449

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 21, 2019

Conversation

tirkarthi
Copy link
Member

  • This PR fixes the RuntimeWarning in inspect.isawaitable(mock()) where mock() was not awaited.
  • Fix typo in asynctest project.

@tirkarthi tirkarthi changed the title Fix RuntimeWarning in docs Fix RuntimeWarning in unittest.mock asyncio example May 20, 2019
@tirkarthi
Copy link
Member Author

cc: @lisroach I couldn't find a better way to suppress the RuntimeWarning than using the object in the example. Feel free to suggest if there is a better method.

Sample warning : https://travis-ci.org/python/cpython/jobs/534904298#L1553

@asvetlov
Copy link
Contributor

thanks!

@asvetlov
Copy link
Contributor

I removed automerge label.
Will apply it tomorrow if nobody will propose an alternative solution.

@asvetlov asvetlov self-assigned this May 20, 2019
@tirkarthi
Copy link
Member Author

@asvetlov There is one more https://travis-ci.org/python/cpython/jobs/534932562#L1564 . I am not sure why my local build and CI doesn't show all the warnings initially.

@tirkarthi
Copy link
Member Author

I went ahead and removed the warning line in current CI and I get below one. For each line I remove, the subsequent line that accesses mock.await* attribute gets me this warning. Making it as a separate doctest with python -Wall -m doctest doesn't show any warning. I guess I must be missing something since subsequent lines keep raising RuntimeWarning.

<doctest default[3]>:1: RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited
  mock.await_args

@tirkarthi
Copy link
Member Author

I have removed another call by guessing at 7ece18f and there is no RuntimeWarning now in CI. But removing it seems incorrect because as per the section it's there to illustrate that setting spec on Mock/MagicMock will return coroutine object on calling the object. Adding asyncio.main() to await it seems to clutter the simple example. Perhaps doctest can be converted to a codeblock with the repr of the object as comment on the same line to illustrate this. Suggestions welcome.

Copy link
Contributor

@eamanu eamanu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lisroach
Copy link
Contributor

Hmm weird, I hadn't seen these warnings when I ran locally. Thanks for digging into it @tirkarthi! I definitely wish we could avoid cluttering the simple examples. I'll try to take a look tonight but no solution off the top of my head.

@tirkarthi
Copy link
Member Author

A simplified version of the changes. The builtins._ = None is just mock() with incorrect traceback I assume which is at the end of file

foo.rst

>>> import asyncio
>>> import inspect
>>> from unittest.mock import AsyncMock, MagicMock
>>> mock = AsyncMock()
>>> asyncio.iscoroutinefunction(mock)
True
>>> inspect.isawaitable(mock())
True
>>> async def async_func(): pass
...
>>> mock = MagicMock(async_func)
>>> mock   # doctest: +ELLIPSIS
<MagicMock spec='function' id='...'>
>>> mock()  # doctest: +ELLIPSIS
<coroutine object AsyncMockMixin._mock_call at ...>
./python.exe -X tracemalloc -Wall -m doctest foo.rst
<doctest foo.rst[5]>:1: RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited
  inspect.isawaitable(mock())
Object allocated at (most recent call last):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", lineno 992
    return _mock_self._mock_call(*args, **kwargs)
/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py:1485: RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited
  builtins._ = None
Object allocated at (most recent call last):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", lineno 992
    return _mock_self._mock_call(*args, **kwargs)

@asvetlov
Copy link
Contributor

Dropping doctests for async mocks is another option.
asyncio is still not doctest-friendly.
Perhaps #13148 can change the situation a lot.

@tirkarthi
Copy link
Member Author

Dropping doctest is a good idea. I have added # doctest: +SKIP to the statements that return coroutine objects not awaited. This fixes the warnings and also ensures that the examples are also concise. Thanks.

@miss-islington miss-islington merged commit e7cb23b into python:master May 21, 2019
@asvetlov
Copy link
Contributor

thanks!

@Carreau
Copy link
Contributor

Carreau commented May 21, 2019

Perhaps #13148 can change the situation a lot.

Not quite sure I understand why. Do you mean you want >>> await coro in doctest ?

Another option is to set coroutine_wrapper (which is due for removal), track coroutine creations, and after each doctest check if the list of coro we have collected have been awaited at least once. If not raise an error, so now you can narrow down which doctest did forget to await coros instead of waiting for interpreter shutdown for the warning.

@asvetlov
Copy link
Contributor

Yes, I mean after #13148 landing there is a possibility for extending doctest to support asyncio.
This requires some amount of work, sure. A good target for Python 3.9 :)

@tirkarthi tirkarthi deleted the fix-asyncio-warning branch May 26, 2019 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants