Author xtreak
Recipients asvetlov, cjw296, lisroach, mariocj89, michael.foord, xtreak, yselivanov
Date 2019-05-25.19:38:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
* In create_autospec there is some logic to detect if the function is an async function this could be refactored out as a private function.

* create_autospec has initialization code for async mock. For synchronous functions this is done with _setup_func and is called during setting signature. AsyncMock needs different setup logic code to setup the functions but the code can be refactored out of create_autospec into _setup_async_func.

* In create_autospec awaited attribute is not set for AsyncMock during setup [0] and hence this causes AttributeError when the coroutine is awaited. awaited attribute can be also initialized.

import asyncio
from unittest.mock import create_autospec

async def foo(): pass

spec = create_autospec(foo)
awaitable = spec()

async def main(): await awaitable

Traceback (most recent call last):
  File "/tmp/", line 13, in <module>
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/asyncio/", line 43, in run
    return loop.run_until_complete(main)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/asyncio/", line 614, in run_until_complete
    return future.result()
  File "/tmp/", line 11, in main
    await awaitable
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/", line 2045, in _mock_call
    return await proxy()
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/", line 2043, in proxy
    await self.awaited._notify()
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/", line 596, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'awaited'

* In the setup logic to create attributes like assert_not_awaited uses the pattern setattr(mock, a, f) at [1] . But due to late binding 'a' in the function f has the last value of the loop 'assert_not_awaited' and hence calling other helpers also calls assert_not_awaited. This could be resolved by using a partial function that binds the attribute value early in the loop and respective function would be used in getattr.

>>> spec.assert_awaited_once_with(1) # Due to late binding assert_not_awaited is always called
TypeError: assert_not_awaited() takes 1 positional argument but 2 were given

* assert_not_awaited has the error message indicating it should be awaited once [2] . This can be changed to indicate something like "Expected mock to not have been awaited".

>>> spec.assert_not_awaited()
AssertionError: Expected mock to have been awaited once. Awaited 1 times.

* mock docs have list of magic methods implemented where __aenter__, __aexit__, __aiter__ and __anext__ could be documented with versionadded directive. [3]

I have a PR with the above changes that I will post shortly for review.

Date User Action Args
2019-05-25 19:38:44xtreaksetrecipients: + xtreak, cjw296, michael.foord, asvetlov, yselivanov, lisroach, mariocj89
2019-05-25 19:38:44xtreaksetmessageid: <>
2019-05-25 19:38:44xtreaklinkissue37047 messages
2019-05-25 19:38:44xtreakcreate