New handle_exception plugin hook, refs #1770

Also refs:
- https://github.com/simonw/datasette-sentry/issues/1
- https://github.com/simonw/datasette-show-errors/issues/2
This commit is contained in:
Simon Willison 2022-07-17 16:24:39 -07:00
commit c09c53f345
10 changed files with 216 additions and 96 deletions

View file

@ -68,6 +68,7 @@ EXPECTED_PLUGINS = [
"canned_queries",
"extra_js_urls",
"extra_template_vars",
"handle_exception",
"menu_links",
"permission_allowed",
"register_routes",

View file

@ -185,3 +185,21 @@ def register_routes(datasette):
# Also serves to demonstrate over-ride of default paths:
(r"/(?P<db_name>[^/]+)/(?P<table_and_format>[^/]+?$)", new_table),
]
@hookimpl
def handle_exception(datasette, request, exception):
datasette._exception_hook_fired = (request, exception)
if request.args.get("_custom_error"):
return Response.text("_custom_error")
elif request.args.get("_custom_error_async"):
async def inner():
return Response.text("_custom_error_async")
return inner
@hookimpl(specname="register_routes")
def register_triger_error():
return ((r"/trigger-error", lambda: 1 / 0),)

View file

@ -332,6 +332,7 @@ def test_permissions_debug(app_client):
assert checks == [
{"action": "permissions-debug", "result": True, "used_default": False},
{"action": "view-instance", "result": None, "used_default": True},
{"action": "debug-menu", "result": False, "used_default": True},
{"action": "permissions-debug", "result": False, "used_default": True},
{"action": "view-instance", "result": None, "used_default": True},
]

View file

@ -824,6 +824,20 @@ def test_hook_forbidden(restore_working_directory):
assert "view-database" == client.ds._last_forbidden_message
def test_hook_handle_exception(app_client):
app_client.get("/trigger-error?x=123")
assert hasattr(app_client.ds, "_exception_hook_fired")
request, exception = app_client.ds._exception_hook_fired
assert request.url == "http://localhost/trigger-error?x=123"
assert isinstance(exception, ZeroDivisionError)
@pytest.mark.parametrize("param", ("_custom_error", "_custom_error_async"))
def test_hook_handle_exception_custom_response(app_client, param):
response = app_client.get("/trigger-error?{}=1".format(param))
assert response.text == param
def test_hook_menu_links(app_client):
def get_menu_links(html):
soup = Soup(html, "html.parser")