GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — bpo-26467: Adds AsyncMock for asyncio Mock library support by lisroach · Pull Request #9296 · python/cpython

Conversation

@lisroach

@lisroach lisroach commented Sep 14, 2018 •
edited by bedevere-bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This is my initial pass at supporting coroutine mocking via a new Mock subclass, CoroutineMock.

It can be used to mock out coroutines and have them validate as coroutines:

>>> mock = CoroutineMock()
>>> asyncio.iscoroutinefunction(mock)
True

Test that a coroutine was awaited:

class TestTests(unittest.TestCase):
    def test_assert_awaited(self):
        async def main():
            mock = CoroutineMock()
            with self.assertRaises(AssertionError):
                mock.assert_awaited()
            await mock()
            mock.assert_awaited()
        asyncio.run(main())

Also awaited_with, awaited_once_with, etc.

Things that I could use advice on:

  1. Some of the code has been borrowed by asynctest (https://pypi.org/project/asynctest/) which is licensed under Apache 2. I have reached out to the author and am waiting to hear back, but am not sure how we feel about having Apache 2 licensed stuff in CPython. I could rewrite those spots if needed.

  2. inspect.iscoroutine will return False for CoroutineMock objects. This is because the check is isinstance(object, types.CoroutineType), and CoroutineTypes are concrete. I've looked into using something like, register, but it doesn't work here, so I need someway to make a Mock look like a types.CoroutineType but I am unsure how.

  3. In CoroutineMockAssert tests, I have asyncio.events._event_loop_policy unset because it causes the env to change when running tests if it is not unset. There is probably a better way to do this where the environment doesn't get polluted?

  4. I plan on working on getting more example test cases for the CoroutineArguments test section, would be happy for advice though.

And I will be writing up the documentation once the code has settled.

https://bugs.python.org/issue26467

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

dimaqq reacted with thumbs up emoji balloob, elyssonmr, and RaphaelVRossi reacted with hooray emoji dimaqq and cooperlees reacted with heart emoji
All reactions
  • 👍 1 reaction
  • 🎉 3 reactions
  • ❤️ 2 reactions
lisroach added 11 commits September 12, 2018 08:59
@lisroach
Initial commmit adding asyncio mock support.
4353041
@lisroach
Adding async support to the mock library.
b83e5a5
@lisroach
Removes superfluous changes.
a9ea983
@lisroach
Cleans up comments.
50581e3
@lisroach
Fixes inspect and attribute error issues.
96ddb0e
@lisroach
Fixes test_unittest changing env because of version issue.
a4d4dbc
@lisroach
Removes newlines from inspect.
bfdd5a7
@lisroach
Removes unneeded comment and newlines.
ed7f13c
@lisroach
Fixes async tests. Removes inspect fix.
34fa74e
@lisroach
Fixes environment test issue.
302ef64
@lisroach
Adds argument tests.
bf749ac
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Sep 14, 2018
@bedevere-bot bedevere-bot added the awaiting review label Sep 14, 2018
@lisroach
Adding the side_effect exception test.
30b64b5
@1st1 1st1 self-assigned this Sep 14, 2018
@lisroach

lisroach commented Sep 14, 2018

Copy link
Copy Markdown
Contributor Author

Talking with @asvetlov, it might be easier/more useful to implement this purely as an AwaitableMock, instead of mocking Coroutines themselves. This should also be more flexible in terms of inspect, because I could assert isawaitable() more easily than iscoroutine().

We also chatted about ideas around mocking AsyncIterators so we can continue to support aiter and anext, but that will probably come in a separate commit.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@1st1

1st1 commented Sep 14, 2018

Copy link
Copy Markdown
Member

Talking with @asvetlov, it might be easier/more useful to implement this purely as an AwaitableMock, instead of mocking Coroutines themselves.

+1.

dave-shawley and cjw296 reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tirkarthi tirkarthi mentioned this pull request May 2, 2019
TypeError when patching a dictionary with a Unicode string literal on Python 2 testing-cabal/mock#458
Closed
@cjw296

cjw296 commented May 2, 2019

Copy link
Copy Markdown
Contributor

@lisroach - I'm afraid I don't any anywhere near enough experience with asyncio to sensibly review this, however one request: please can you split any tests that use the 3.7+ async syntax into their own file (test..._async.py or something) so that this can more easily be merged into the rolling backport.

I'm not sure if this will be possible, but if you could avoid using any 3.7+ syntax inside mock.py itself, that would, again, make backporting significantly easier :-)

tirkarthi reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach

lisroach commented May 6, 2019

Copy link
Copy Markdown
Contributor Author

@cjw296 Good point about the backporting. So separating the tests is no problem, easy-peasy. For the internals of mock.py itself it's a bit more challenging because of the async def __anext__ I need.

What if I try to wrap all the AsyncMock related code in mock.py in some regexable comment block (like # Nonbackportable AsyncMock), and all code within those blocks could be searched for and removed before backporting?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@cjw296

cjw296 commented May 7, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

What might work better is if you could put the AsyncMock class and anything else that needs 3.7+ syntax into a mockasync.py next to mock.py and then do a from .mockasync import * inside mock.py (for circular import fun reasons, this may need to be at the bottom of mock.py). That way, the code can stay in one place and we can make that a conditional import in the backport.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach
Changes CoroutineMock to AsyncMock. Removes old-style coroutine refer…
5edac2a
…ences.
@lisroach

lisroach commented May 7, 2019

Copy link
Copy Markdown
Contributor Author

I don't think it's possible to separate it out into a different file, the code is too integrated with the mock code itself we can't avoid the circular dependencies. I've moved all of the 3.7+ syntax code to the bottom of mock.py so it's all in one spot, will it be possible for it to be dropped when backporting with it like this?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach
Merge branch 'master' into asyncio_mock
fa978cc
@asvetlov asvetlov changed the title bpo-26467: Adds CoroutineMock for asyncio Mock library support bpo-26467: Adds AsyncMock for asyncio Mock library support May 7, 2019
@asvetlov

asvetlov commented May 7, 2019

Copy link
Copy Markdown
Contributor

@cjw296 the PR not only adds AsyncMock class but hacks already existing mock classes.
There is nothing new, mock is already has circular dependencies.

Please elaborate how from .mockasync import * at the end for mock.py can make backporting easier?
Do you want to remove this line and all usages for mockasync objects from mock.py during a backport?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach
Changes fnmatch to list comp.
24920a6
tirkarthi
tirkarthi reviewed May 7, 2019
View reviewed changes
Comment thread Lib/unittest/mock.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

cjw296
cjw296 reviewed May 7, 2019
View reviewed changes
Comment thread Lib/unittest/mock.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@cjw296

cjw296 commented May 7, 2019

Copy link
Copy Markdown
Contributor

@asvetlov - yeah, I've commented on the "hacks already existing mock classes". This doesn't feel like a good idea to me, do we really need it?

The elaboration requested, would be this in cpython:

mock.py:
...all existing mock stuff...
from .mockasync import *

mockasync.py:
from .mock import *  # should work as we've already got the unittest.mock setup above
... anything using 3.7+ syntax...

This would be backported as:

mock.py:
...all existing mock stuff...
if sys.version_info >= (3, 7, ):
    from .mockasync import *

...so the patch can stay pretty much identical bar adding one line and changing another. It does require all Python 3.7+-only syntax going into mockasync.py.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@1st1

1st1 commented May 16, 2019

Copy link
Copy Markdown
Member

@tirkarthi Most of your comments are on point, but I think we can address them once this is merged.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tirkarthi

tirkarthi commented May 16, 2019

Copy link
Copy Markdown
Member

@1st1 I would request create_autospec to be fixed as it's one line change causing NameError before beta release and if possible as part of this PR. Fixing the ResourceWarning would also be great just to make sure there is no buildbot failure outside of primary CI since I don't know the configuration in which they are run.

More tests and docs could be added after beta and I would be happy to help with follow up PRs for the same. Thanks for approving this.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tirkarthi

tirkarthi commented May 16, 2019

Copy link
Copy Markdown
Member

@lisroach Attached is a patch fixing docs and doctest that would make CI green. I tested it on my fork and seems to work fine.

diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst
index a8d05b216c..5d4737b60f 100644
--- a/Doc/library/unittest.mock.rst
+++ b/Doc/library/unittest.mock.rst
@@ -201,9 +201,11 @@ The Mock Class

 .. testsetup::

+    import asyncio
+    import inspect
     import unittest
     from unittest.mock import sentinel, DEFAULT, ANY
-    from unittest.mock import patch, call, Mock, MagicMock, PropertyMock
+    from unittest.mock import patch, call, Mock, MagicMock, PropertyMock, AsyncMock
     from unittest.mock import mock_open

 :class:`Mock` is a flexible mock object intended to replace the use of stubs and
@@ -885,9 +887,9 @@ object::
     ...
     >>> mock = MagicMock(async_func)
     >>> mock
-    <MagicMock spec='function' id='4568403696'>
+    <MagicMock spec='function' id='...'>
     >>> mock()
-    <coroutine object AsyncMockMixin._mock_call at 0x1104cb440>
+    <coroutine object AsyncMockMixin._mock_call at ...>

   .. method:: assert_awaited()

@@ -976,11 +978,11 @@ object::
       Assert the mock has been awaited with the specified calls.
       The :attr:`await_args_list` list is checked for the awaits.

-      If `any_order` is False (the default) then the awaits must be
+      If *any_order* is False (the default) then the awaits must be
       sequential. There can be extra calls before or after the
       specified awaits.

-      If `any_order` is True then the awaits can be in any order, but
+      If *any_order* is True then the awaits can be in any order, but
       they must all appear in :attr:`await_args_list`.

         >>> mock = AsyncMock()
lisroach reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach
Fixes based on comments.
64301e2
tirkarthi
tirkarthi reviewed May 17, 2019
View reviewed changes
Comment thread Lib/unittest/test/testmock/testasync.py

def test_create_autospec_instance(self):
with self.assertRaises(RuntimeError):
create_autospec(async_func, instance=True)

@tirkarthi tirkarthi May 17, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

This test fails since the RuntimeError check is commented out.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@lisroach lisroach May 17, 2019

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Ah yeah, sorry I was trying to remember the answer to your question on why it was needed. It might not be and I'm debating about taking it out, I think I don't fully understand the purpose of instance=True and what we would want the behavior to be if it is True with create_autospec on a async function.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@tirkarthi tirkarthi May 18, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

No problem, we can remove the restriction later if needed. I have added one more doctest suggestion that would make the CI green and this can be merged.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/unittest.mock.rst Outdated

>>> mock = AsyncMock()
>>> async def main(*args):
... await mock()

@tirkarthi tirkarthi May 17, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
... await mock()
... await mock(*args)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/unittest.mock.rst Outdated

>>> mock = AsyncMock()
>>> async def main(*args):
... await mock()

@tirkarthi tirkarthi May 17, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
... await mock()
... await mock(*args)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@lisroach
Fixes broken docs.
c7cd95e
tirkarthi
tirkarthi reviewed May 18, 2019
View reviewed changes
Comment thread Doc/library/unittest.mock.rst Outdated
>>> mock.await_args_list
[]
>>> asyncio.run(main('foo'))
>>> mock.await_args

@tirkarthi tirkarthi May 18, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
>>> mock.await_args
>>> mock.await_args_list

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
lisroach added 2 commits May 18, 2019 15:45
@lisroach
Fixes broken doc await_arg.
033f7d3
@lisroach
Adds shoutout to Martin Richard for asynctest.
2fef02c
tirkarthi
tirkarthi approved these changes May 19, 2019
View reviewed changes

@tirkarthi tirkarthi left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

LGTM. Buildbots are green and it will be great to have this merged for beta. I will create a followup PR that can be reviewed separately without holding this up any further.

Thank you very much @lisroach :)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lisroach reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@lisroach

lisroach commented May 20, 2019

Copy link
Copy Markdown
Contributor Author

Thanks for all the help and reviews everyone!

asvetlov, tirkarthi, dimaqq, and mikegoodspeed reacted with hooray emoji
All reactions
  • 🎉 4 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach
lisroach merged commit 77b3b77 into python:master May 20, 2019
@bedevere-bot bedevere-bot removed the awaiting merge label May 20, 2019
@mariocj89

mariocj89 commented May 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

I know I am late to the party. Real apologies about it, I had LASIK past week and could not check this on the weekend. I don't know how many times people have asked about AsyncMock, this is just great :).

My main comment here would be whether it is useful or confusing the fact that AsyncMock will generate "inner mocks" when attributes are called on it. I would find that confusing though I am far from an expert on async. Is there any use-case were calling an attribute in an async object it yields naturally another async object?

Example, not sure this is expected:

>>> from unittest.mock import AsyncMock
>>> m = AsyncMock()
>>> m.a.return_value = 1
>>> print(m.a)
<AsyncMock name='mock.a' id='140389785043824'>
>>> print(m.a())
<coroutine object AsyncMockMixin._mock_call at 0x7faf0ab8d240>
<stdin>:1: RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

I think I'd use the AsyncMock to mock specific function calls. It is also really handy that it works with patch. I was just wondering whether getting an attribute of the AsyncMock should return:

  1. Nothing at all, attribute error and let users set attributes if desired.
  2. A normal mock as that might be more common (Patching an async callable class for example).
  3. Default to async mock as the current implementation does. People can set normal mocks if wanted.

In short, if we have a class that has async and normal methods, Should we use a normal mock and add AsyncMock to the methods that are async or the other way around?

If this was thought and 3 was chosen purposely because it makes more sense for async users, all good (as said, not an expert in async at all), just raising the question.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mariocj89

mariocj89 commented May 22, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Example, how do we expect users to simulate the following class?

class X:
  async def a(self):
    return "a"
  def b(self):
    return "b"

If the plan is to use AsyncMock for it, the following does not work:

m = AsyncMock(**{"a.return_value": "mocka", "b.return_value": "mockb"})
async def check(m):
    print(m.b())
    print(await m.a())

Output:

>>> asyncio.run(check(m))
<coroutine object AsyncMockMixin._mock_call at 0x7f39dea8cac0>
<stdin>:2: RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
mocka

If we say that users should specify the exact type of mock on each of the attribute, what is the purpose of automatically generating them for the attribute for AsyncMock then?

As said, minor concern, there might be no better solution, but wanted to have a look at it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@asvetlov

asvetlov commented May 22, 2019

Copy link
Copy Markdown
Contributor

Thanks for the comment.
I see a bunch of RuntimeWarning: coroutine 'AsyncMockMixin._mock_call' was never awaited when running tests.test_asyncio suite.
Need to investigate.
See https://bugs.python.org/issue37015 for the reference.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach

lisroach commented May 24, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Thanks for pointing that out @mariocj89! I made it recursive asyncmocks more as a way to copy the normal functionality of Mock, which creates an internal mock of the same kind when calling an attribute, for example:

>>> from unittest.mock import MagicMock
>>> m = MagicMock()
>>> m.a.return_value = 1
>>> print(m.a)
<MagicMock name='mock.a' id='4490221040'>

It is mentioned in the docstring "By default child mocks will be the same type as the parent", although this can be overridden.
I wanted to mimic the same functionality because I do think that is what is expected when using the mock library.

The current functionality is that if you want to mock a mixed class, you use a normal mock and it figures out for you which functions are async:

>>> class X:
...   async def a(self):
...     return "a"
...   def b(self):
...     return "b"
...
>>> m = MagicMock(X, autospec=True)
>>> m.b
<MagicMock name='mock.b' id='4490513224'>
>>> m.a
<AsyncMock name='mock.a' id='4490514088'>

But you are right if someone was attempting to build their own class via mock the would need to specify the mock type of the arguments. I don't usually use mock this way so I hadn't considered that use case. In your example it looks like there would be no way to tell it is supposed to be an awaitable mock until the actual call occurs, which might be tricky to implement. If you think it will be useful though I don't mind if you open up a new bug and we can figure it out there!

mariocj89 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mariocj89 mariocj89 mentioned this pull request May 30, 2019
docs: Add references to AsyncMock in unittest.mock.patch #13681
Merged
@jeremycline

jeremycline commented Jun 11, 2019

Copy link
Copy Markdown
Contributor

Hi folks,

I've hit an issue I think is related to this PR in Python 3.8b1. The minimal reproducer I came up with is:

from unittest import mock

mock_obj = mock.MagicMock()
mock_obj.mock_func = mock.MagicMock(spec=lambda x: x)

with mock.patch.object(mock_obj, "mock_func") as nested:
    print(type(nested))

What happens is that nested is an AsyncMock in Python 3.8, but a MagicMock in Python 3.7. The reason is when the MagicMock has a function spec, __code__ is defined so the check for the coroutine flags returns a truthy MagicMock object. In other words, import inspect; from unittest import mock; inspect.iscoroutinefunction(mock.MagicMock(spec=lambda x: x)) is True (and that holds in Python 3.7 as well).

I thought about just submitting a fix, but it's not clear to me whether adding a check to unittest.mock._is_async_obj for MagicMock and behaving differently is truly the right fix. Having asyncio.iscoroutinefunction return True seems wrong for MagicMocks with function specs. Maybe MagicMock needs to have something to make it behave correctly there?

tirkarthi reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lisroach

lisroach commented Jun 12, 2019

Copy link
Copy Markdown
Contributor Author

Hey @jeremycline, would you mind making a bug on bugs.python.org? It will be best to centralize discussion there. Thanks for reporting this! It is definitely a bug.

I understand the desire to change MagicMock to avoid this behavior, but I think it is the wrong approach. It is not evaluating to True because of the __code__.co_flag attribute, that doesn't get set until after the check for _is_async_obj has already evaluated truthy.

The issue comes in when checking:

bool(f.__code__.co_flags & flag)

in inspect._has_code_flag. The & is a call, which with MagicMocks will result in another MagicMock object:

<MagicMock name='mock.mock_func.__code__.co_flags.__and__()' id='4467594096'>

It does not take into account the flag argument at all, and calling bool() on the MagicMock evaluates to True.

The only way I see us getting around this would be to set the mock.__code__.co_flags attribute everytime a spec with __code__ is passed in to MagicMock, but this changes the way mock typically behaves. It would be unexpected for one attribute to be set (I think) if others are not.

It might be best to make a workaround in the _is_async_obj, although it feels more hacky.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@njsmith

njsmith commented Jun 12, 2019

Copy link
Copy Markdown
Contributor

Maybe bool(MagicMock) should raise an error?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@tirkarthi

tirkarthi commented Jun 12, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

It might be best to make a workaround in the _is_async_obj, although it feels more hacky.

I feel this is a reasonable trade off that maybe we could check if __code__ is actually a CodeType to ensure MagicMock is not passed to iscoroutinefunction to give a false positive.

def _is_async_obj(obj):
    code = getattr(obj, '__code__', None)
    if code and isinstance(code, CodeType):
        return asyncio.iscoroutinefunction(obj) or inspect.isawaitable(obj)
    else:
        return False
lisroach reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jeremycline

jeremycline commented Jun 12, 2019

Copy link
Copy Markdown
Contributor

Hey @jeremycline, would you mind making a bug on bugs.python.org? It will be best to centralize discussion there. Thanks for reporting this! It is definitely a bug.

Thanks for the quick response, I've filed an issue at https://bugs.python.org/issue37251.

lisroach reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dimaqq dimaqq mentioned this pull request Jun 24, 2019
Question on upstream AsyncMock Martiusweb/asynctest#130
Open
This was referenced Nov 12, 2019
Integrating with Python 3.8 Martiusweb/asynctest#144
Open
Adding missing acknowledgement #17130
Merged
bpo-17013: Extend Mock.called to allow waiting for calls #17133
Closed
@Kentzo Kentzo mentioned this pull request Jun 9, 2020
gh-61215: Add Mock.call_event to allow waiting for calls #20759
Closed
f0k
f0k reviewed Feb 21, 2023
View reviewed changes
Comment thread Lib/unittest/mock.py
_spec_asyncs = []

for attr in dir(spec):
if asyncio.iscoroutinefunction(getattr(spec, attr, None)):

@f0k f0k Feb 21, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Late note, not sure if anyone gets a notification for this: This broke a use case for me. Before this change, the Mock constructor did not call getattr on any of the attributes of the mocked object specification. I used it to mock an instance of a base class that does not have all its properties implemented, using the **kwargs in the Mock constructor to ensure that unimplemented properties that were accessed by any tests got a sane value. I can solve this by using a subclass that does not have unimplemented properties. But maybe it would be wise to skip all attributes here that appear in **kwargs, because they will be subsequently overwritten?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

arhadthedev reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@arhadthedev arhadthedev Feb 21, 2023

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

not sure if anyone gets a notification for this

For this reason it's worth creating a new issue and mentioning this PR there.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@cjw296 cjw296 Feb 21, 2023

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

@f0k - better yet, if you could work up a PR with a test that shows the problem you encountered, along with a fix for it, that would be better!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@tirkarthi tirkarthi Feb 21, 2023 •
edited by cjw296
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

@f0k some related issues . Please use search before creating the issue so that you can check for previous issues and make sure it's not duplicate. Thanks.

#89917
#85934

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@f0k f0k Feb 22, 2023

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

For this reason it's worth creating a new issue

I wasn't sure yet whether this warrants a fix, and was aiming low :)

some related issues

Good spot, yes, they're both the same problem, and there are already three PRs proposing a fix. I will continue the discussion in #85934, as it's the older one of the two issues.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@python python deleted a comment from fok Feb 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@1st1 1st1 1st1 approved these changes
@cjw296 cjw296 cjw296 left review comments
@tirkarthi tirkarthi tirkarthi approved these changes
@arhadthedev arhadthedev arhadthedev left review comments
@asvetlov asvetlov asvetlov approved these changes
+2 more reviewers
@voidspace voidspace voidspace left review comments
@f0k f0k f0k left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@1st1 1st1

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

13 participants

@lisroach @1st1 @cjw296 @asvetlov @voidspace @tirkarthi @mariocj89 @jeremycline @njsmith @f0k @arhadthedev @the-knights-who-say-ni @bedevere-bot
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.