Simplify the async handling code

Firstly `run_sync` was a misleading name as it didn't run anything,
instead I think `async_to_sync` is much clearer as it converts a
coroutine function to a function. (Name stolen from asgiref).

Secondly trying to run the ensure_sync during registration made the
code more complex and brittle, e.g. the _flask_async_wrapper
usage. This was done to pay any setup costs during registration rather
than runtime, however this only saved a iscoroutne check. It allows
the weirdness of the Blueprint and Scaffold ensure_sync methods to be
removed.

Switching to runtime ensure_sync usage provides a method for
extensions to also support async, as now documented.
This commit is contained in:
pgjones 2021-05-02 20:49:46 +01:00 committed by David Lord
parent cb13128cf0
commit 7f87f3dd93
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
6 changed files with 53 additions and 68 deletions

View file

@ -6,7 +6,6 @@ import typing as t
import warnings
from datetime import timedelta
from functools import update_wrapper
from functools import wraps
from threading import RLock
import werkzeug.utils
@ -803,10 +802,15 @@ def is_ip(value: str) -> bool:
return False
def run_async(func: t.Callable[..., t.Coroutine]) -> t.Callable[..., t.Any]:
"""Return a sync function that will run the coroutine function *func*."""
def async_to_sync(func: t.Callable[..., t.Coroutine]) -> t.Callable[..., t.Any]:
"""Return a sync function that will run the coroutine function *func*.
This can be used as so
result = async_to_async(func)(*args, **kwargs)
"""
try:
from asgiref.sync import async_to_sync
from asgiref.sync import async_to_sync as asgiref_async_to_sync
except ImportError:
raise RuntimeError(
"Install Flask with the 'async' extra in order to use async views."
@ -818,9 +822,4 @@ def run_async(func: t.Callable[..., t.Coroutine]) -> t.Callable[..., t.Any]:
"Async cannot be used with this combination of Python & Greenlet versions."
)
@wraps(func)
def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:
return async_to_sync(func)(*args, **kwargs)
wrapper._flask_sync_wrapper = True # type: ignore
return wrapper
return asgiref_async_to_sync(func)