Skip to content

Commit

Permalink
DATASETTE_LOAD_PLUGINS environment variable for loading specific plugins
Browse files Browse the repository at this point in the history
Closes #2164

* Load only specified plugins for DATASETTE_LOAD_PLUGINS=datasette-one,datasette-two
* Load no plugins if DATASETTE_LOAD_PLUGINS=''
* Automated tests in a Bash script for DATASETTE_LOAD_PLUGINS
  • Loading branch information
simonw authored Aug 30, 2023
1 parent 30b28c8 commit 6bfe104
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ jobs:
run: |
# This fails on syntax errors, or a diff was applied
blacken-docs -l 60 docs/*.rst
- name: Test DATASETTE_LOAD_PLUGINS
run: |
pip install datasette-init datasette-json-html
tests/test-datasette-load-plugins.sh
23 changes: 22 additions & 1 deletion datasette/plugins.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import importlib
import os
import pluggy
import pkg_resources
import sys
Expand All @@ -22,10 +23,30 @@
pm = pluggy.PluginManager("datasette")
pm.add_hookspecs(hookspecs)

if not hasattr(sys, "_called_from_test"):
DATASETTE_LOAD_PLUGINS = os.environ.get("DATASETTE_LOAD_PLUGINS", None)

if not hasattr(sys, "_called_from_test") and DATASETTE_LOAD_PLUGINS is None:
# Only load plugins if not running tests
pm.load_setuptools_entrypoints("datasette")

# Load any plugins specified in DATASETTE_LOAD_PLUGINS")
if DATASETTE_LOAD_PLUGINS is not None:
for package_name in [
name for name in DATASETTE_LOAD_PLUGINS.split(",") if name.strip()
]:
try:
distribution = pkg_resources.get_distribution(package_name)
entry_map = distribution.get_entry_map()
if "datasette" in entry_map:
for plugin_name, entry_point in entry_map["datasette"].items():
mod = entry_point.load()
pm.register(mod, name=entry_point.name)
# Ensure name can be found in plugin_to_distinfo later:
pm._plugin_distinfo.append((mod, distribution))
except pkg_resources.DistributionNotFound:
sys.stderr.write("Plugin {} could not be found\n".format(package_name))


# Load default plugins
for plugin in DEFAULT_PLUGINS:
mod = importlib.import_module(plugin)
Expand Down
54 changes: 54 additions & 0 deletions docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,60 @@ You can use the name of a package on PyPI or any of the other valid arguments to
datasette publish cloudrun mydb.db \
--install=https://url-to-my-package.zip


.. _plugins_datasette_load_plugins:

Controlling which plugins are loaded
------------------------------------

Datasette defaults to loading every plugin that is installed in the same virtual environment as Datasette itself.

You can set the ``DATASETTE_LOAD_PLUGINS`` environment variable to a comma-separated list of plugin names to load a controlled subset of plugins instead.

For example, to load just the ``datasette-vega`` and ``datasette-cluster-map`` plugins, set ``DATASETTE_LOAD_PLUGINS`` to ``datasette-vega,datasette-cluster-map``:

.. code-block:: bash
export DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map'
datasette mydb.db
Or:

.. code-block:: bash
DATASETTE_LOAD_PLUGINS='datasette-vega,datasette-cluster-map' \
datasette mydb.db
To disable the loading of all additional plugins, set ``DATASETTE_LOAD_PLUGINS`` to an empty string:

.. code-block:: bash
export DATASETTE_LOAD_PLUGINS=''
datasette mydb.db
A quick way to test this setting is to use it with the ``datasette plugins`` command:

.. code-block:: bash
DATASETTE_LOAD_PLUGINS='datasette-vega' datasette plugins
This should output the following:

.. code-block:: json
[
{
"name": "datasette-vega",
"static": true,
"templates": false,
"version": "0.6.2",
"hooks": [
"extra_css_urls",
"extra_js_urls"
]
}
]
.. _plugins_installed:

Seeing what plugins are installed
Expand Down
29 changes: 29 additions & 0 deletions tests/test-datasette-load-plugins.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
# This should only run in environemnts where both
# datasette-init and datasette-json-html are installed

PLUGINS=$(datasette plugins)
echo "$PLUGINS" | jq 'any(.[]; .name == "datasette-json-html")' | \
grep -q true || ( \
echo "Test failed: datasette-json-html not found" && \
exit 1 \
)
# With the DATASETTE_LOAD_PLUGINS we should not see that
PLUGINS2=$(DATASETTE_LOAD_PLUGINS=datasette-init datasette plugins)
echo "$PLUGINS2" | jq 'any(.[]; .name == "datasette-json-html")' | \
grep -q false || ( \
echo "Test failed: datasette-json-html should not have been loaded" && \
exit 1 \
)
echo "$PLUGINS2" | jq 'any(.[]; .name == "datasette-init")' | \
grep -q true || ( \
echo "Test failed: datasette-init should have been loaded" && \
exit 1 \
)
# With DATASETTE_LOAD_PLUGINS='' we should see no plugins
PLUGINS3=$(DATASETTE_LOAD_PLUGINS='' datasette plugins)
echo "$PLUGINS3"| \
grep -q '\[\]' || ( \
echo "Test failed: datasette plugins should have returned []" && \
exit 1 \
)

0 comments on commit 6bfe104

Please sign in to comment.