kopia lustrzana https://github.com/simonw/datasette
Replaced sanic.response and finished removing Sanic entirely in favour of ASGI
rodzic
eba15fb5a8
commit
b794554a26
|
@ -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"
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
1
setup.py
1
setup.py
|
@ -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",
|
||||
|
|
Ładowanie…
Reference in New Issue