-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
11 changed files
with
224 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ Contents | |
installation | ||
cli | ||
python-api | ||
plugins | ||
reference | ||
cli-reference | ||
contributing | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
.. _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 | ||
.. _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" | ||
The ```[project.entry-points.sqlite_utils]`` section tells ``sqlite-tils`` which module to load when executing the plugin. | ||
|
||
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 | ||
sqlite-utils install -e `/dev/sqlite-utils-hello-world | ||
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``. | ||
.. _plugins_hooks: | ||
Plugin hooks | ||
------------ | ||
Plugin hooks allow ``sqlite-utils`` to be customized. There is currently one hook. | ||
.. _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!") | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
from .db import Database | ||
from .utils import suggest_column_types | ||
from .hookspecs import hookimpl | ||
from .hookspecs import hookspec | ||
|
||
__all__ = ["Database", "suggest_column_types"] | ||
__all__ = ["Database", "suggest_column_types", "hookimpl", "hookspec"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from pluggy import HookimplMarker | ||
from pluggy import HookspecMarker | ||
|
||
hookspec = HookspecMarker("sqlite_utils") | ||
hookimpl = HookimplMarker("sqlite_utils") | ||
|
||
|
||
@hookspec | ||
def register_commands(cli): | ||
"""Register additional CLI commands, e.g. 'sqlite-utils mycommand ...'""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import pluggy | ||
import sys | ||
from . import hookspecs | ||
|
||
pm = pluggy.PluginManager("sqlite_utils") | ||
pm.add_hookspecs(hookspecs) | ||
|
||
if not hasattr(sys, "_called_from_test"): | ||
# Only load plugins if not running tests | ||
pm.load_setuptools_entrypoints("sqlite_utils") | ||
|
||
|
||
def get_plugins(): | ||
plugins = [] | ||
plugin_to_distinfo = dict(pm.list_plugin_distinfo()) | ||
for plugin in pm.get_plugins(): | ||
plugin_info = { | ||
"name": plugin.__name__, | ||
"hooks": [h.name for h in pm.get_hookcallers(plugin)], | ||
} | ||
distinfo = plugin_to_distinfo.get(plugin) | ||
if distinfo: | ||
plugin_info["version"] = distinfo.version | ||
plugin_info["name"] = distinfo.project_name | ||
plugins.append(plugin_info) | ||
return plugins |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from click.testing import CliRunner | ||
import click | ||
import importlib | ||
from sqlite_utils import cli, hookimpl, plugins | ||
|
||
|
||
def test_register_commands(): | ||
importlib.reload(cli) | ||
assert plugins.get_plugins() == [] | ||
|
||
class HelloWorldPlugin: | ||
__name__ = "HelloWorldPlugin" | ||
|
||
@hookimpl | ||
def register_commands(self, cli): | ||
@cli.command(name="hello-world") | ||
def hello_world(): | ||
"Print hello world" | ||
click.echo("Hello world!") | ||
|
||
try: | ||
plugins.pm.register(HelloWorldPlugin(), name="HelloWorldPlugin") | ||
importlib.reload(cli) | ||
|
||
assert plugins.get_plugins() == [ | ||
{"name": "HelloWorldPlugin", "hooks": ["register_commands"]} | ||
] | ||
|
||
runner = CliRunner() | ||
result = runner.invoke(cli.cli, ["hello-world"]) | ||
assert result.exit_code == 0 | ||
assert result.output == "Hello world!\n" | ||
|
||
finally: | ||
plugins.pm.unregister(name="HelloWorldPlugin") | ||
importlib.reload(cli) | ||
assert plugins.get_plugins() == [] |