Redesigned register_output_renderer plugin hook, closes #581

This commit is contained in:
Simon Willison 2020-05-27 19:21:41 -07:00
commit 52c4387c7d
8 changed files with 202 additions and 20 deletions

View file

@ -0,0 +1,42 @@
from datasette import hookimpl
import json
def render_test_all_parameters(
datasette, columns, rows, sql, query_name, database, table, request, view_name, data
):
headers = {}
for custom_header in request.args.getlist("header") or []:
key, value = custom_header.split(":")
headers[key] = value
return {
"body": json.dumps(
{
"datasette": datasette,
"columns": columns,
"rows": rows,
"sql": sql,
"query_name": query_name,
"database": database,
"table": table,
"request": request,
"view_name": view_name,
},
default=repr,
),
"content_type": request.args.get("content_type", "text/plain"),
"status_code": int(request.args.get("status_code", 200)),
"headers": headers,
}
def render_test_no_parameters():
return {"body": "Hello"}
@hookimpl
def register_output_renderer(datasette):
return [
{"extension": "testall", "render": render_test_all_parameters},
{"extension": "testnone", "callback": render_test_no_parameters},
]

View file

@ -1259,16 +1259,16 @@ def test_threads_json(app_client):
def test_plugins_json(app_client):
response = app_client.get("/-/plugins.json")
assert [
{"name": "my_plugin.py", "static": False, "templates": False, "version": None},
{
"name": "my_plugin_2.py",
"static": False,
"templates": False,
"version": None,
},
{"name": "view_name.py", "static": False, "templates": False, "version": None},
] == sorted(response.json, key=lambda p: p["name"])
expected = [
{"name": name, "static": False, "templates": False, "version": None}
for name in (
"my_plugin.py",
"my_plugin_2.py",
"register_output_renderer.py",
"view_name.py",
)
]
assert expected == sorted(response.json, key=lambda p: p["name"])
def test_versions_json(app_client):

View file

@ -546,6 +546,8 @@ def test_table_csv_json_export_interface(app_client):
actual = [l["href"].split("/")[-1] for l in links]
expected = [
"simple_primary_key.json?id__gt=2",
"simple_primary_key.testall?id__gt=2",
"simple_primary_key.testnone?id__gt=2",
"simple_primary_key.csv?id__gt=2&_size=max",
"#export",
]
@ -582,6 +584,8 @@ def test_csv_json_export_links_include_labels_if_foreign_keys(app_client):
actual = [l["href"].split("/")[-1] for l in links]
expected = [
"facetable.json?_labels=on",
"facetable.testall?_labels=on",
"facetable.testnone?_labels=on",
"facetable.csv?_labels=on&_size=max",
"#export",
]

View file

@ -19,6 +19,8 @@ import textwrap
import pytest
import urllib
at_memory_re = re.compile(r" at 0x\w+")
@pytest.mark.xfail
@pytest.mark.parametrize(
@ -329,3 +331,79 @@ def test_view_names(view_names_client, path, view_name):
response = view_names_client.get(path)
assert response.status == 200
assert "view_name:{}".format(view_name) == response.body.decode("utf8")
def test_register_output_renderer_no_parameters(app_client):
response = app_client.get("/fixtures/facetable.testnone")
assert 200 == response.status
assert b"Hello" == response.body
def test_register_output_renderer_all_parameters(app_client):
response = app_client.get("/fixtures/facetable.testall")
assert 200 == response.status
# Lots of 'at 0x103a4a690' in here - replace those so we can do
# an easy comparison
body = response.body.decode("utf-8")
body = at_memory_re.sub(" at 0xXXX", body)
assert {
"datasette": "<datasette.app.Datasette object at 0xXXX>",
"columns": [
"pk",
"created",
"planet_int",
"on_earth",
"state",
"city_id",
"neighborhood",
"tags",
"complex_array",
"distinct_some_null",
],
"rows": [
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
"<sqlite3.Row object at 0xXXX>",
],
"sql": "select pk, created, planet_int, on_earth, state, city_id, neighborhood, tags, complex_array, distinct_some_null from facetable order by pk limit 51",
"query_name": None,
"database": "fixtures",
"table": "facetable",
"request": "<datasette.utils.asgi.Request object at 0xXXX>",
"view_name": "table",
} == json.loads(body)
# Test that query_name is set correctly
query_response = app_client.get("/fixtures/pragma_cache_size.testall")
assert "pragma_cache_size" == json.loads(query_response.body)["query_name"]
def test_register_output_renderer_custom_status_code(app_client):
response = app_client.get("/fixtures/pragma_cache_size.testall?status_code=202")
assert 202 == response.status
def test_register_output_renderer_custom_content_type(app_client):
response = app_client.get(
"/fixtures/pragma_cache_size.testall?content_type=text/blah"
)
assert "text/blah" == response.headers["content-type"]
def test_register_output_renderer_custom_headers(app_client):
response = app_client.get(
"/fixtures/pragma_cache_size.testall?header=x-wow:1&header=x-gosh:2"
)
assert "1" == response.headers["x-wow"]
assert "2" == response.headers["x-gosh"]