Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inspect and prepare_sanic hooks #437

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ def inspect(self):
"views": inspect_views(conn),
"tables": inspect_tables(conn, (self.metadata("databases") or {}).get(name, {}))
}
for result in pm.hook.inspect(database=name, conn=conn, datasette=self):
self._inspect[name].update(result)
except sqlite3.OperationalError as e:
if (e.args[0] == 'no such module: VirtualSpatialIndex'):
raise click.UsageError(
Expand Down Expand Up @@ -716,6 +718,7 @@ async def handle_request(self, request, write_callback, stream_callback):
RowView.as_view(self),
r"/<db_name:[^/]+>/<table:[^/]+?>/<pk_path:[^/]+?><as_format:(\.jsono?)?$>",
)
pm.hook.prepare_sanic(app=app, datasette=self)
self.register_custom_units()

# On 404 with a trailing slash redirect to path without that slash:
Expand Down
10 changes: 10 additions & 0 deletions datasette/hookspecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ def extra_body_script(template, database, table, datasette):
"Extra JavaScript code to be included in <script> at bottom of body"


@hookspec
def inspect(database, conn):
"Inspect the database for plugin-specific information"


@hookspec
def prepare_sanic(app, datasette):
"Add additional web routes"


@hookspec
def publish_subcommand(publish):
"Subcommands for 'datasette publish'"
Expand Down
51 changes: 51 additions & 0 deletions docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,27 @@ You can now use this filter in your custom templates like so::

Table name: {{ table|uppercase }}

.. _plugin_hook_prepare_sanic:

prepare_sanic(app, datasette)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Called at startup to allow plugins to add additional HTTP endpoints to Sanic's web router.

``app`` - Sanic app instance
The instance of the Sanic app.

``datasette`` - Datasette instance
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``

In this hook, you can add new routes using ``app.add_route``::

app.add_route(lambda x: text("Hello World"), r"/test/")

**Warning**: This hook depends on Sanic - an implementation detail which `may change in a later version of Datasette <https://github.com/simonw/datasette/issues/272>`_.

The return value is ignored.

.. _plugin_hook_extra_css_urls:

extra_css_urls(template, database, table, datasette)
Expand Down Expand Up @@ -551,3 +572,33 @@ The ``template``, ``database`` and ``table`` options can be used to return diffe
The ``datasette`` instance is provided primarily so that you can consult any plugin configuration options that may have been set, using the ``datasette.plugin_config(plugin_name)`` method documented above.

The string that you return from this function will be treated as "safe" for inclusion in a ``<script>`` block directly in the page, so it is up to you to apply any necessary escaping.

.. _plugin_hook_inspect:

inspect(database, conn, datasette)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Called at inspect time to allow the plugin to inspect the database and save the inspected data.

``database`` - string
The name of the database being inspected.

``conn`` - Sqlite connection
A sqlite connection object for the database.

``datasette`` - Datasette instance
You can use this to access plugin configuration options via ``datasette.plugin_config(your_plugin_name)``

This is useful if you need to cache any information about the database which might be expensive to collect on every page load.

Return a dictionary which is merged into the inspected data. You should store inspected data within this using a plugin-specific key::

return {
"myplugin": {<data>}
}

The inspected data dictionary can be retrieved later with::

my_data = datasette.inspect()["myplugin"]