mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1c3cc362d |
||
|
|
2302b76a2e |
||
|
|
563fab27cc |
||
|
|
13ed3069f2 |
4 changed files with 95 additions and 3 deletions
|
|
@ -430,8 +430,46 @@ class Datasette:
|
|||
self.executor, sql_operation_in_thread
|
||||
)
|
||||
|
||||
def app(self):
|
||||
app = Sanic(__name__)
|
||||
def asgi_app(self):
|
||||
self.configure_jinja()
|
||||
from starlette.routing import Router, Path, PathPrefix
|
||||
from starlette.staticfiles import StaticFile, StaticFiles
|
||||
return Router([
|
||||
Path(
|
||||
'/(?P<as_format>\.jsono?)?$',
|
||||
app=IndexView(self).asgi_app(),
|
||||
methods=['GET']
|
||||
),
|
||||
Path(
|
||||
'/favicon.ico',
|
||||
app=StaticFile(
|
||||
path=str(app_root / "datasette" / "static" / "favicon.ico")
|
||||
)
|
||||
),
|
||||
PathPrefix(
|
||||
'/-/static/',
|
||||
app=StaticFiles(
|
||||
directory=str(app_root / "datasette" / "static")
|
||||
)
|
||||
),
|
||||
Path(
|
||||
"/(?P<db_name>[^/]+?)(?P<as_format>(\.jsono?|\.csv))?$",
|
||||
app=DatabaseView(self).asgi_app(),
|
||||
),
|
||||
Path(
|
||||
"/(?P<db_name>[^/]+?)/(?P<table_and_format>[^/]+?)$",
|
||||
app=TableView(self).asgi_app(),
|
||||
),
|
||||
])
|
||||
# app.add_route(
|
||||
# DatabaseView.as_view(self), "/<db_name:[^/]+?><as_format:(\.jsono?|\.csv)?$>"
|
||||
# )
|
||||
# app.add_route(
|
||||
# TableView.as_view(self),
|
||||
# "/<db_name:[^/]+>/<table_and_format:[^/]+?$>",
|
||||
# )
|
||||
|
||||
def configure_jinja(self):
|
||||
default_templates = str(app_root / "datasette" / "templates")
|
||||
template_paths = []
|
||||
if self.template_dir:
|
||||
|
|
@ -459,6 +497,10 @@ class Datasette:
|
|||
self.jinja_env.filters["escape_sqlite"] = escape_sqlite
|
||||
self.jinja_env.filters["to_css_class"] = to_css_class
|
||||
pm.hook.prepare_jinja2_environment(env=self.jinja_env)
|
||||
|
||||
def app(self):
|
||||
app = Sanic(__name__)
|
||||
self.configure_jinja()
|
||||
app.add_route(IndexView.as_view(self), "/<as_format:(\.jsono?)?$>")
|
||||
# TODO: /favicon.ico and /-/static/ deserve far-future cache expires
|
||||
app.add_route(favicon, "/favicon.ico")
|
||||
|
|
|
|||
|
|
@ -256,6 +256,9 @@ def package(
|
|||
"-h", "--host", default="127.0.0.1", help="host for server, defaults to 127.0.0.1"
|
||||
)
|
||||
@click.option("-p", "--port", default=8001, help="port for server, defaults to 8001")
|
||||
@click.option(
|
||||
"--asgi", is_flag=True, help="Run in ASGI mode"
|
||||
)
|
||||
@click.option(
|
||||
"--debug", is_flag=True, help="Enable debug mode - useful for development"
|
||||
)
|
||||
|
|
@ -316,6 +319,7 @@ def serve(
|
|||
files,
|
||||
host,
|
||||
port,
|
||||
asgi,
|
||||
debug,
|
||||
reload,
|
||||
cors,
|
||||
|
|
@ -372,4 +376,9 @@ def serve(
|
|||
)
|
||||
# Force initial hashing/table counting
|
||||
ds.inspect()
|
||||
ds.app().run(host=host, port=port, debug=debug)
|
||||
if asgi:
|
||||
import uvicorn
|
||||
app = ds.asgi_app()
|
||||
uvicorn.run(app, host, port, log_level="info")
|
||||
else:
|
||||
ds.app().run(host=host, port=port, debug=debug)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ from sanic import response
|
|||
from sanic.exceptions import NotFound
|
||||
from sanic.views import HTTPMethodView
|
||||
|
||||
from starlette import asgi_application, Response
|
||||
|
||||
from datasette import __version__
|
||||
from datasette.utils import (
|
||||
CustomJSONEncoder,
|
||||
|
|
@ -43,8 +45,45 @@ class DatasetteError(Exception):
|
|||
self.messagge_is_html = messagge_is_html
|
||||
|
||||
|
||||
class RequestWrapper:
|
||||
# Implements the subset of the Sanic request that my code uses
|
||||
def __init__(self, starlette_request):
|
||||
self._request = starlette_request
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._request.url.path
|
||||
|
||||
@property
|
||||
def query_string(self):
|
||||
return str(self._request._scope["query_string"])
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
# Key/list-of-values
|
||||
# There's probably a better way to do this:
|
||||
d = {}
|
||||
for key, value in self._request.query_params:
|
||||
d.setdefault(key, []).append(value)
|
||||
return d
|
||||
|
||||
@property
|
||||
def raw_args(self):
|
||||
# Flat key/first-value dictionary
|
||||
return dict(self.args)
|
||||
|
||||
|
||||
class RenderMixin(HTTPMethodView):
|
||||
|
||||
def asgi_app(self):
|
||||
@asgi_application
|
||||
async def app(request):
|
||||
sanic_response = await self.get(
|
||||
RequestWrapper(request), **request["kwargs"]
|
||||
)
|
||||
return Response(sanic_response.body)
|
||||
return app
|
||||
|
||||
def render(self, templates, **context):
|
||||
template = self.ds.jinja_env.select_template(templates)
|
||||
select_templates = [
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -41,6 +41,8 @@ setup(
|
|||
'hupper==1.0',
|
||||
'pint==0.8.1',
|
||||
'pluggy>=0.1.0,<1.0',
|
||||
'starlette==0.1.15',
|
||||
'uvicorn==0.2.21',
|
||||
],
|
||||
entry_points='''
|
||||
[console_scripts]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue