Skip to content

Commit

Permalink
Add inspect and prepare_sanic hooks
Browse files Browse the repository at this point in the history
This adds two new plugin hooks:

The `inspect` hook allows plugins to add data to the inspect
dictionary.

The `prepare_sanic` hook allows plugins to hook into the web
router. I've attached a warning to this hook in the docs in light
of simonw#272 but I want this hook now...

On quick inspection, I don't think it's worthwhile to try and make
this hook independent of the web framework (but it looks like Starlette
would make the hook implementation a bit nicer).

Ref simonw#14
  • Loading branch information
russss committed Apr 29, 2019
1 parent 11b352b commit f33a0a6
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
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"]


0 comments on commit f33a0a6

Please sign in to comment.