2023-07-22 12:04:31 -07:00
.. _plugins:
=========
Plugins
=========
`` sqlite-utils `` supports plugins, which can be used to add extra features to the software.
Plugins can add new commands, for example `` sqlite-utils some-command ... ``
Plugins can be installed using the `` sqlite-utils install `` command:
.. code-block :: bash
sqlite-utils install sqlite-utils-name-of-plugin
You can see a JSON list of plugins that have been installed by running this:
.. code-block :: bash
sqlite-utils plugins
2023-07-22 16:06:11 -07:00
Plugin hooks such as :ref: `plugins_hooks_prepare_connection` affect each instance of the `` Database `` class. You can opt-out of these plugins by creating that class instance like so:
.. code-block :: python
db = Database(memory=True, execute_plugins=False)
2023-07-22 12:04:31 -07:00
.. _plugins_building:
Building a plugin
-----------------
Plugins are created in a directory named after the plugin. To create a "hello world" plugin, first create a `` hello-world `` directory:
.. code-block :: bash
mkdir hello-world
cd hello-world
In that folder create two files. The first is a `` pyproject.toml `` file describing the plugin:
.. code-block :: toml
[project]
name = "sqlite-utils-hello-world"
version = "0.1"
[project.entry-points.sqlite_utils]
hello_world = "sqlite_utils_hello_world"
2023-11-03 20:55:19 -07:00
The `` [project.entry-points.sqlite_utils] `` section tells `` sqlite-utils `` which module to load when executing the plugin.
2023-07-22 12:04:31 -07:00
Then create `` sqlite_utils_hello_world.py `` with the following content:
.. code-block :: python
import click
import sqlite_utils
@sqlite_utils.hookimpl
def register_commands(cli):
@cli.command()
def hello_world():
"Say hello world"
click.echo("Hello world!")
Install the plugin in "editable" mode - so you can make changes to the code and have them picked up instantly by `` sqlite-utils `` - like this:
.. code-block :: bash
sqlite-utils install -e .
Or pass the path to your plugin directory:
.. code-block :: bash
2023-11-03 20:55:19 -07:00
sqlite-utils install -e /dev/sqlite-utils-hello-world
2023-07-22 12:04:31 -07:00
Now, running this should execute your new command:
.. code-block :: bash
sqlite-utils hello-world
Your command will also be listed in the output of `` sqlite-utils --help `` .
2023-07-22 15:45:23 -07:00
See the `LLM plugin documentation <https://llm.datasette.io/en/stable/plugins/tutorial-model-plugin.html#distributing-your-plugin> `__ for tips on distributing your plugin.
2023-07-22 12:04:31 -07:00
.. _plugins_hooks:
Plugin hooks
------------
2023-07-22 15:59:08 -07:00
Plugin hooks allow `` sqlite-utils `` to be customized.
2023-07-22 12:04:31 -07:00
.. _plugins_hooks_register_commands:
register_commands(cli)
~~~~~~~~~~~~~~~~~~~~~~
This hook can be used to register additional commands with the `` sqlite-utils `` CLI. It is called with the `` cli `` object, which is a `` click.Group `` instance.
Example implementation:
.. code-block :: python
import click
import sqlite_utils
@sqlite_utils.hookimpl
def register_commands(cli):
@cli.command()
def hello_world():
"Say hello world"
click.echo("Hello world!")
2024-11-08 11:16:57 -08:00
New commands implemented by plugins can invoke existing commands using the `context.invoke <https://click.palletsprojects.com/en/stable/api/#click.Context.invoke> `__ mechanism.
2024-11-08 12:11:17 -08:00
As a special niche feature, if your plugin needs to import some files and then act against an in-memory database containing those files you can forward to the :ref: `sqlite-utils memory command <cli_memory>` and pass it `` return_db=True `` :
2024-11-08 11:16:57 -08:00
.. code-block :: python
@cli.command()
@click.pass_context
@click.argument(
"paths",
type=click.Path(file_okay=True, dir_okay=False, allow_dash=True),
required=False,
nargs=-1,
)
def show_schema_for_files(ctx, paths):
from sqlite_utils.cli import memory
2024-11-08 12:13:05 -08:00
db = ctx.invoke(memory, paths=paths, return_db=True)
2024-11-08 11:16:57 -08:00
# Now do something with that database
click.echo(db.schema)
2023-07-22 15:59:08 -07:00
.. _plugins_hooks_prepare_connection:
prepare_connection(conn)
~~~~~~~~~~~~~~~~~~~~~~~~
This hook is called when a new SQLite database connection is created. You can
use it to `register custom SQL functions <https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.create_function> `_ ,
aggregates and collations. For example:
.. code-block :: python
import sqlite_utils
@sqlite_utils.hookimpl
def prepare_connection(conn):
conn.create_function(
2023-07-22 16:13:46 -07:00
"hello", 1, lambda name: f"Hello, {name}!"
2023-07-22 15:59:08 -07:00
)
This registers a SQL function called `` hello `` which takes a single
argument and can be called like this:
.. code-block :: sql
select hello("world"); -- "Hello, world!"