Replaced sanic.response and finished removing Sanic entirely in favour of ASGI

pull/518/head
Simon Willison 2019-06-23 20:03:33 -07:00
rodzic eba15fb5a8
commit b794554a26
6 zmienionych plików z 74 dodań i 43 usunięć

Wyświetl plik

@ -168,23 +168,7 @@ class AsgiView:
response = await self.dispatch_request(
request, **scope["url_route"]["kwargs"]
)
if hasattr(response, "asgi_send"):
await response.asgi_send(send)
else:
headers = {}
headers.update(response.headers)
headers["content-type"] = response.content_type
await send(
{
"type": "http.response.start",
"status": response.status,
"headers": [
[key.encode("utf-8"), value.encode("utf-8")]
for key, value in headers.items()
],
}
)
await send({"type": "http.response.body", "body": response.body})
await response.asgi_send(send)
view.view_class = cls
view.__doc__ = cls.__doc__
@ -330,6 +314,57 @@ def asgi_static(root_path, chunk_size=4096, headers=None, content_type=None):
return inner_static
class Response:
def __init__(self, body=None, status=200, headers=None, content_type="text/plain"):
self.body = body
self.status = status
self.headers = headers or {}
self.content_type = content_type
async def asgi_send(self, send):
headers = {}
headers.update(self.headers)
headers["content-type"] = self.content_type
await send(
{
"type": "http.response.start",
"status": self.status,
"headers": [
[key.encode("utf-8"), value.encode("utf-8")]
for key, value in headers.items()
],
}
)
body = self.body
if not isinstance(body, bytes):
body = body.encode("utf-8")
await send({"type": "http.response.body", "body": body})
@classmethod
def html(cls, body, status=200, headers=None):
return cls(
body,
status=status,
headers=headers,
content_type="text/html; charset=utf-8",
)
@classmethod
def text(cls, body, status=200, headers=None):
return cls(
body,
status=status,
headers=headers,
content_type="text/plain; charset=utf-8",
)
@classmethod
def redirect(cls, path, status=302, headers=None):
headers = headers or {}
headers["Location"] = path
return cls("", status=status, headers=headers)
class AsgiFileDownload:
def __init__(
self, filepath, filename=None, content_type="application/octet-stream"

Wyświetl plik

@ -7,7 +7,6 @@ import urllib
import jinja2
import pint
from sanic import response
from html import escape
@ -26,7 +25,14 @@ from datasette.utils import (
sqlite3,
to_css_class,
)
from datasette.utils.asgi import AsgiStream, AsgiWriter, AsgiRouter, AsgiView, NotFound
from datasette.utils.asgi import (
AsgiStream,
AsgiWriter,
AsgiRouter,
AsgiView,
NotFound,
Response,
)
ureg = pint.UnitRegistry()
@ -112,7 +118,7 @@ class BaseView(AsgiView):
datasette=self.ds,
):
body_scripts.append(jinja2.Markup(script))
return response.html(
return Response.html(
template.render(
{
**context,
@ -144,7 +150,7 @@ class DataView(BaseView):
self.ds = datasette
def options(self, request, *args, **kwargs):
r = response.text("ok")
r = Response.text("ok")
if self.ds.cors:
r.headers["Access-Control-Allow-Origin"] = "*"
return r
@ -154,7 +160,7 @@ class DataView(BaseView):
path = "{}?{}".format(path, request.query_string)
if remove_args:
path = path_with_removed_args(request, remove_args, path=path)
r = response.redirect(path)
r = Response.redirect(path)
r.headers["Link"] = "<{}>; rel=preload".format(path)
if self.ds.cors:
r.headers["Access-Control-Allow-Origin"] = "*"
@ -254,7 +260,7 @@ class DataView(BaseView):
response_or_template_contexts = await self.data(
request, database, hash, **kwargs
)
if isinstance(response_or_template_contexts, response.HTTPResponse):
if isinstance(response_or_template_contexts, Response):
return response_or_template_contexts
else:
data, _, _ = response_or_template_contexts
@ -371,7 +377,7 @@ class DataView(BaseView):
response_or_template_contexts = await self.data(
request, database, hash, **kwargs
)
if isinstance(response_or_template_contexts, response.HTTPResponse):
if isinstance(response_or_template_contexts, Response):
return response_or_template_contexts
else:
@ -422,17 +428,11 @@ class DataView(BaseView):
if result is None:
raise NotFound("No data")
response_args = {
"content_type": result.get("content_type", "text/plain"),
"status": result.get("status_code", 200),
}
if type(result.get("body")) == bytes:
response_args["body_bytes"] = result.get("body")
else:
response_args["body"] = result.get("body")
r = response.HTTPResponse(**response_args)
r = Response(
body=result.get("body"),
status=result.get("status_code", 200),
content_type=result.get("content_type", "text/plain"),
)
else:
extras = {}
if callable(extra_template_data):

Wyświetl plik

@ -1,7 +1,5 @@
import os
from sanic import response
from datasette.utils import to_css_class, validate_sql_select
from datasette.utils.asgi import AsgiFileDownload

Wyświetl plik

@ -1,9 +1,8 @@
import hashlib
import json
from sanic import response
from datasette.utils import CustomJSONEncoder
from datasette.utils.asgi import Response
from datasette.version import __version__
from .base import BaseView
@ -104,7 +103,7 @@ class IndexView(BaseView):
headers = {}
if self.ds.cors:
headers["Access-Control-Allow-Origin"] = "*"
return response.HTTPResponse(
return Response(
json.dumps({db["name"]: db for db in databases}, cls=CustomJSONEncoder),
content_type="application/json; charset=utf-8",
headers=headers,

Wyświetl plik

@ -1,5 +1,5 @@
import json
from sanic import response
from datasette.utils.asgi import Response
from .base import BaseView
@ -17,7 +17,7 @@ class JsonDataView(BaseView):
headers = {}
if self.ds.cors:
headers["Access-Control-Allow-Origin"] = "*"
return response.HTTPResponse(
return Response(
json.dumps(data),
content_type="application/json; charset=utf-8",
headers=headers,

Wyświetl plik

@ -43,7 +43,6 @@ setup(
install_requires=[
"click>=6.7",
"click-default-group==1.2",
"Sanic==0.7.0",
"Jinja2==2.10.1",
"hupper==1.0",
"pint==0.8.1",