-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Improve detection of async callables #1444
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
Changes from all commits
ff314dd
a1c0764
636a26f
f6935c3
7312456
4151df6
8438a9f
788f011
dd8b7ed
7c74668
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import asyncio | ||
| import functools | ||
| import typing | ||
|
|
||
|
|
||
| def is_async_callable(obj: typing.Any) -> bool: | ||
| while isinstance(obj, functools.partial): | ||
| obj = obj.func | ||
|
|
||
| return asyncio.iscoroutinefunction(obj) or ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @Kludex, would it make sense to use I understand why we cannot just use the said function alone, since I have looked at the code of Cheers,
This comment was marked as off-topic.
Sorry, something went wrong. |
||
| callable(obj) and asyncio.iscoroutinefunction(obj.__call__) | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import functools | ||
|
|
||
| from starlette._utils import is_async_callable | ||
|
|
||
|
|
||
| def test_async_func(): | ||
| async def async_func(): | ||
| ... # pragma: no cover | ||
|
|
||
| def func(): | ||
| ... # pragma: no cover | ||
|
|
||
| assert is_async_callable(async_func) | ||
| assert not is_async_callable(func) | ||
|
|
||
|
|
||
| def test_async_partial(): | ||
Kludex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| async def async_func(a, b): | ||
| ... # pragma: no cover | ||
|
|
||
| def func(a, b): | ||
| ... # pragma: no cover | ||
|
|
||
| partial = functools.partial(async_func, 1) | ||
| assert is_async_callable(partial) | ||
|
|
||
| partial = functools.partial(func, 1) | ||
| assert not is_async_callable(partial) | ||
|
|
||
|
|
||
| def test_async_method(): | ||
| class Async: | ||
| async def method(self): | ||
| ... # pragma: no cover | ||
|
|
||
| class Sync: | ||
| def method(self): | ||
| ... # pragma: no cover | ||
|
|
||
| assert is_async_callable(Async().method) | ||
| assert not is_async_callable(Sync().method) | ||
|
|
||
|
|
||
| def test_async_object_call(): | ||
| class Async: | ||
| async def __call__(self): | ||
| ... # pragma: no cover | ||
|
|
||
| class Sync: | ||
| def __call__(self): | ||
| ... # pragma: no cover | ||
|
|
||
| assert is_async_callable(Async()) | ||
| assert not is_async_callable(Sync()) | ||
|
|
||
|
|
||
| def test_async_partial_object_call(): | ||
| class Async: | ||
| async def __call__(self, a, b): | ||
| ... # pragma: no cover | ||
|
|
||
| class Sync: | ||
| def __call__(self, a, b): | ||
| ... # pragma: no cover | ||
|
|
||
| partial = functools.partial(Async(), 1) | ||
| assert is_async_callable(partial) | ||
|
|
||
| partial = functools.partial(Sync(), 1) | ||
| assert not is_async_callable(partial) | ||
|
|
||
|
|
||
| def test_async_nested_partial(): | ||
| async def async_func(a, b): | ||
| ... # pragma: no cover | ||
|
|
||
| partial = functools.partial(async_func, b=2) | ||
| nested_partial = functools.partial(partial, a=1) | ||
| assert is_async_callable(nested_partial) | ||
Uh oh!
There was an error while loading. Please reload this page.