Skip to content
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

gh-98086: Now patch.dict can decorate async functions #98095

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

sobolevn
Copy link
Member

@sobolevn sobolevn commented Oct 8, 2022

I will check other patch.* types for similar problems in the next issues / PRs.

Issue: gh-98086

Copy link

@seifertm seifertm left a comment

Thanks for looking into this! The changes fix the reported issue: coroutines now stay coroutines when applying the patch.dict decorator.

I checked the behavior of all patch.* functions and they seem to be consistent as of this PR. Patching preserves coroutines, even inside of TestCase classes when used as a class decorator.

Note that async generator functions are not preserved. They become functions when decorated with patch.*. However, this is the same for all variants of patch and not part of the reported issue.

Here's the code I used to verify the behavior:

import inspect
from unittest import TestCase
from unittest.mock import DEFAULT, Mock, patch


patchers = (
    patch("binascii.b64encode"),
    patch.dict("sys.modules", test_module=Mock()),
    patch.object(Mock, "my_func"),
    patch.multiple(Mock, my_attr=DEFAULT, my_other=DEFAULT),
)

async def coro():
    ...

patched_coros = (patcher(coro) for patcher in patchers)

assert inspect.iscoroutinefunction(coro)
assert all(map(inspect.iscoroutinefunction, patched_coros))


# Coroutines in test classes
for patcher in patchers:
    @patcher
    class TestClass(TestCase):
        async def test_coro(self):
            ...
    assert inspect.iscoroutinefunction(TestClass.test_coro)



# The behavior across patch functions is consistent with async generator functions
async def async_gen_func():
    yield

patched_async_gen_funcs = (patcher(async_gen_func) for patcher in patchers)
assert inspect.isasyncgenfunction(async_gen_func)
assert not all(map(inspect.isasyncgenfunction, patched_async_gen_funcs))

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.

None yet

3 participants