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

Don't warn 'non-async-marked callable' for async callable instance #325

Merged
merged 2 commits into from May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion asgiref/sync.py
Expand Up @@ -107,7 +107,12 @@ class AsyncToSync:
loop_thread_executors: "Dict[asyncio.AbstractEventLoop, CurrentThreadExecutor]" = {}

def __init__(self, awaitable, force_new_loop=False):
if not callable(awaitable) or not _iscoroutinefunction_or_partial(awaitable):
if not callable(awaitable) or (
not _iscoroutinefunction_or_partial(awaitable)
and not _iscoroutinefunction_or_partial(
getattr(awaitable, "__call__", awaitable)
)
):
# Python does not have very reliable detection of async functions
# (lots of false negatives) so this is just a warning.
warnings.warn(
Expand Down
24 changes: 24 additions & 0 deletions tests/test_sync.py
Expand Up @@ -3,6 +3,7 @@
import multiprocessing
import threading
import time
import warnings
from concurrent.futures import ThreadPoolExecutor
from functools import wraps
from unittest import TestCase
Expand Down Expand Up @@ -365,6 +366,29 @@ async def inner_async_function(*args):
assert result["worked"]


def test_async_to_sync_on_callable_object():
"""
Tests async_to_sync on a callable class instance
"""

result = {}

class CallableClass:
async def __call__(self, value):
await asyncio.sleep(0)
result["worked"] = True
return value

# Run it (without warnings)
with warnings.catch_warnings():
warnings.simplefilter("error")
sync_function = async_to_sync(CallableClass())
out = sync_function(42)

assert out == 42
assert result["worked"] is True


def test_async_to_sync_method_self_attribute():
"""
Tests async_to_sync on a method copies __self__.
Expand Down