mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Support non-async view functions, closes #867
This commit is contained in:
parent
1bb33dab49
commit
4b142862f2
4 changed files with 33 additions and 10 deletions
|
|
@ -3,6 +3,7 @@ import asgi_csrf
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import inspect
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
@ -40,6 +41,7 @@ from .database import Database, QueryInterrupted
|
||||||
|
|
||||||
from .utils import (
|
from .utils import (
|
||||||
async_call_with_supported_arguments,
|
async_call_with_supported_arguments,
|
||||||
|
call_with_supported_arguments,
|
||||||
escape_css_string,
|
escape_css_string,
|
||||||
escape_sqlite,
|
escape_sqlite,
|
||||||
format_bytes,
|
format_bytes,
|
||||||
|
|
@ -1056,14 +1058,24 @@ def _cleaner_task_str(task):
|
||||||
|
|
||||||
def wrap_view(view_fn, datasette):
|
def wrap_view(view_fn, datasette):
|
||||||
async def asgi_view_fn(scope, receive, send):
|
async def asgi_view_fn(scope, receive, send):
|
||||||
response = await async_call_with_supported_arguments(
|
if inspect.iscoroutinefunction(view_fn):
|
||||||
view_fn,
|
response = await async_call_with_supported_arguments(
|
||||||
scope=scope,
|
view_fn,
|
||||||
receive=receive,
|
scope=scope,
|
||||||
send=send,
|
receive=receive,
|
||||||
request=Request(scope, receive),
|
send=send,
|
||||||
datasette=datasette,
|
request=Request(scope, receive),
|
||||||
)
|
datasette=datasette,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
response = call_with_supported_arguments(
|
||||||
|
view_fn,
|
||||||
|
scope=scope,
|
||||||
|
receive=receive,
|
||||||
|
send=send,
|
||||||
|
request=Request(scope, receive),
|
||||||
|
datasette=datasette,
|
||||||
|
)
|
||||||
if response is not None:
|
if response is not None:
|
||||||
await response.asgi_send(send)
|
await response.asgi_send(send)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ register_routes()
|
||||||
|
|
||||||
Register additional view functions to execute for specified URL routes.
|
Register additional view functions to execute for specified URL routes.
|
||||||
|
|
||||||
Return a list of ``(regex, async_view_function)`` pairs, something like this:
|
Return a list of ``(regex, view_function)`` pairs, something like this:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
@ -554,6 +554,8 @@ The optional view function arguments are as follows:
|
||||||
``receive`` - function
|
``receive`` - function
|
||||||
The ASGI receive function.
|
The ASGI receive function.
|
||||||
|
|
||||||
|
The view function can be a regular function or an ``async def`` function, depending on if it needs to use any ``await`` APIs.
|
||||||
|
|
||||||
The function can either return a :ref:`internals_response` or it can return nothing and instead respond directly to the request using the ASGI ``send`` function (for advanced uses only).
|
The function can either return a :ref:`internals_response` or it can return nothing and instead respond directly to the request using the ASGI ``send`` function (for advanced uses only).
|
||||||
|
|
||||||
Examples: `datasette-auth-github <https://github.com/simonw/datasette-auth-github>`__, `datasette-psutil <https://github.com/simonw/datasette-psutil>`__
|
Examples: `datasette-auth-github <https://github.com/simonw/datasette-auth-github>`__, `datasette-psutil <https://github.com/simonw/datasette-psutil>`__
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,16 @@ def register_routes():
|
||||||
await datasette.render_template("csrftoken_form.html", request=request)
|
await datasette.render_template("csrftoken_form.html", request=request)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def not_async():
|
||||||
|
return Response.html("This was not async")
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(r"/one/$", one),
|
(r"/one/$", one),
|
||||||
(r"/two/(?P<name>.*)$", two),
|
(r"/two/(?P<name>.*)$", two),
|
||||||
(r"/three/$", three),
|
(r"/three/$", three),
|
||||||
(r"/post/$", post),
|
(r"/post/$", post),
|
||||||
(r"/csrftoken-form/$", csrftoken_form),
|
(r"/csrftoken-form/$", csrftoken_form),
|
||||||
|
(r"/not-async/$", not_async),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -565,7 +565,12 @@ def test_actor_json(app_client):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"path,body", [("/one/", "2"), ("/two/Ray?greeting=Hail", "Hail Ray"),]
|
"path,body",
|
||||||
|
[
|
||||||
|
("/one/", "2"),
|
||||||
|
("/two/Ray?greeting=Hail", "Hail Ray"),
|
||||||
|
("/not-async/", "This was not async"),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
def test_register_routes(app_client, path, body):
|
def test_register_routes(app_client, path, body):
|
||||||
response = app_client.get(path)
|
response = app_client.get(path)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue