This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: All unittest.mock autospec-generated methods are coroutine functions
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: lisroach, twm, xtreak
Priority: normal Keywords:

Created on 2020-08-24 23:31 by twm, last changed 2022-04-11 14:59 by admin.

Files
File name Uploaded Description Edit
repro4.py twm, 2020-08-24 23:31
Messages (2)
msg375862 - (view) Author: Tom Most (twm) Date: 2020-08-24 23:31
Given a class:

    class Foo:
        def bar(self):
            pass

And an autospec'd mock of it:

    foo_mock = mock.create_autospec(spec=Foo)

The result of `asyncio.iscoroutinefunction()` differs:

    asyncio.iscoroutinefunction(Foo.bar)        # -> False
    asyncio.iscoroutinefunction(foo_mock.bar)   # -> True

This behavior is the same on Python 3.7 and 3.8.

I've attached a demonstration script, repro4.py. Here is the output on Python 3.7.9:

$ python3.7 repro4.py 
baz is a coroutine function?                        False
Foo.bar is a coroutine function?                    False
foo_instance.bar is a coroutine function?           False
baz_mock is a coroutine function?                   False
foo_mock.bar is a coroutine function?               True
foo_mock_instance.bar is a coroutine function?      True
foo_mock_mock.bar is a coroutine function?          False
foo_mock_mock_instance.bar is a coroutine function? False
foo_mock_instance.bar()      ->  <MagicMock name='mock().bar()' id='140602586963280'>
foo_mock_mock_instance.bar() ->  <Mock name='mock().bar()' id='140602587010192'>

And on Python 3.8.2:

python3.8 repro4.py 
baz is a coroutine function?                        False
Foo.bar is a coroutine function?                    False
foo_instance.bar is a coroutine function?           False
baz_mock is a coroutine function?                   False
foo_mock.bar is a coroutine function?               True
foo_mock_instance.bar is a coroutine function?      True
foo_mock_mock.bar is a coroutine function?          True
foo_mock_mock_instance.bar is a coroutine function? False
foo_mock_instance.bar()      ->  <MagicMock name='mock().bar()' id='139847100001728'>
foo_mock_mock_instance.bar() ->  <Mock name='mock().bar()' id='139847100037968'>
msg375864 - (view) Author: Tom Most (twm) Date: 2020-08-24 23:36
Note that this can interact poorly with AsyncMock, introduced in Python 3.8, because it causes a mock generated from a mock produces an object with async methods rather than regular ones. In Python 3.7 chaining mocks like this would produce regular methods. (This is how I discovered this issue.)
History
Date User Action Args
2022-04-11 14:59:35adminsetgithub: 85794
2020-08-25 09:17:33xtreaksetnosy: + lisroach, xtreak

versions: + Python 3.9, Python 3.10, - Python 3.7
2020-08-24 23:36:50twmsetmessages: + msg375864
2020-08-24 23:31:52twmcreate