classification
Title: asyncio.iscoroutinefunction returns unexpected results when presented with unittest.mock.Mock
Type: behavior Stage: resolved
Components: asyncio Versions: Python 3.6, Python 3.2, Python 3.3, Python 3.4, Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: gvanrossum, jcea, josephgordon, luhn, vstinner, xtreak, yselivanov
Priority: normal Keywords: patch

Created on 2015-11-10 17:26 by luhn, last changed 2019-06-12 18:13 by xtreak. This issue is now closed.

Files
File name Uploaded Description Edit
issue25599.patch josephgordon, 2015-12-23 07:04 review
Messages (10)
msg254457 - (view) Author: Theron Luhn (luhn) Date: 2015-11-10 17:26
>>> asyncio.iscoroutinefunction(unittest.mock.Mock())
<Mock name='mock._is_coroutine' id='4544068072'>

This is an unexpected response, both in type (Mock rather than boolean) and value (truthy).

inspect.iscoroutinefunction behaves as expected.

Workaround:

>>> m = unittest.mock.Mock()
>>> m._is_coroutine = False
>>> asyncio.iscoroutinefunction(m)
False
msg254459 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2015-11-10 17:48
Hm... I don't know what answer you would expect. Who says your mock shouldn't behave like a coroutine? In general, passing mocks to functions is likely to return a mock -- even boolean functions.

Can you provide more context?
msg254464 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-11-10 21:53
>>> asyncio.iscoroutinefunction(unittest.mock.Mock())
<Mock name='mock._is_coroutine' id='4544068072'>

Yeah, I already had this issue when I wrote unit tests using mock :-/ I didn't find an obvious fix for this issue, and it's quite easy to workaround it.

It looks like the "m._is_coroutine = False" is not used in asyncio tests. I don't recall how I worked around the issue in asyncio tests...
msg254491 - (view) Author: Theron Luhn (luhn) Date: 2015-11-11 16:50
For me, the context is a test I was writing that went something like this:

>>> import asyncio
>>> from unittest.mock import Mock
>>> loop = asyncio.get_event_loop()
>>> blocking_func = Mock()
>>> loop.run_in_executor(None, blocking_func)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/base_events.py", line 497, in run_in_executor
    raise TypeError("coroutines cannot be used with run_in_executor()")
TypeError: coroutines cannot be used with run_in_executor()

I understand that the nature of Mock makes its behaviors ambiguous.  However, there are a few reasons I think asyncio.iscoroutinefunction(Mock()) should be false:

1) inspect.iscoroutinefunction reports false.  asyncio.iscoroutinefunction should be consistent with this.
2) A coroutine function should return a coroutine object.  Mock's default behavior won't return a coroutine object, so it shouldn't be identified as a coroutine function by default.
3) It's tidier to make a non-coroutine function Mock into a coroutine function (asyncio.coroutine(Mock())) than it is to make a coroutine function Mock into a non-coroutine function Mock (mock._is_coroutine is implementation-specific hack).
msg254543 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2015-11-12 18:15
OK, I concede your point. It shouldn't be too hard to make
asyncio.iscoroutinefunction() behave the same way as
inspect.iscoroutinefunction(). Can you submit a patch?
msg256865 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2015-12-22 20:47
Oh dang. We were waiting for the OP to submit a patch (not very complex)
but they never did. Now we missed the 3.5.2 deadline. Maybe someone can try
again for 3.5.3?

On Tue, Dec 22, 2015 at 12:30 AM, Joseph Gordon <report@bugs.python.org>
wrote:

>
> Changes by Joseph Gordon <j.gordon.matthew@gmail.com>:
>
>
> ----------
> nosy: +josephgordon
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue25599>
> _______________________________________
>
msg256867 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2015-12-22 20:57
> Now we missed the 3.5.2 deadline.

Did you mean 3.5.1?  Or Larry is going to rush 3.5.2 soon?
msg256868 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2015-12-22 21:02
No I just misremembered.

--Guido (mobile)
msg256903 - (view) Author: Joseph Gordon (josephgordon) Date: 2015-12-23 07:04
I uploaded a patch that appears to fix the issue.
msg345397 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-06-12 18:13
I guess the inconsistency in original report is fixed with issue28703 where both inspect.iscoroutinefunction and asyncio.iscoroutinefunction return False for Mock(). The fix is available from 3.5.3 . There is also async support for mock added in 3.8 with issue26467. I am closing this as part of triaging. Feel free to reopen this if I am missing something. Thanks.

# Python 3.5

python3.5
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> from unittest.mock import *
>>> asyncio.iscoroutinefunction(Mock())
<Mock name='mock._is_coroutine' id='140563339256496'>

# Master

./python.exe
Python 3.9.0a0 (heads/master:daf6262751, Jun 12 2019, 23:12:37)
[Clang 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from unittest.mock import Mock
>>> import asyncio, inspect
>>> inspect.iscoroutinefunction(Mock())
False
>>> asyncio.iscoroutinefunction(Mock())
False
History
Date User Action Args
2019-06-12 18:13:27xtreaksetstatus: open -> closed

nosy: + xtreak
messages: + msg345397

resolution: fixed
stage: resolved
2016-04-24 00:20:57jceasetnosy: + jcea
2015-12-23 07:04:17josephgordonsetfiles: + issue25599.patch
keywords: + patch
messages: + msg256903
2015-12-22 21:02:27gvanrossumsetmessages: + msg256868
2015-12-22 20:57:42yselivanovsetmessages: + msg256867
2015-12-22 20:47:24gvanrossumsetmessages: + msg256865
2015-12-22 08:30:41josephgordonsetnosy: + josephgordon
2015-11-12 18:15:48gvanrossumsetmessages: + msg254543
2015-11-11 16:50:39luhnsetmessages: + msg254491
2015-11-10 21:53:45vstinnersetmessages: + msg254464
2015-11-10 17:48:40gvanrossumsetmessages: + msg254459
2015-11-10 17:26:22luhncreate