From 4728a730bc60d115d7b26667f9878ae2f2df7f42 Mon Sep 17 00:00:00 2001 From: Rami Abdelrazzaq Date: Fri, 6 Mar 2026 17:52:36 -0600 Subject: [PATCH] docs: use pyproject.toml in plugin packaging guide --- docs/writing_plugins.rst | 71 ++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/docs/writing_plugins.rst b/docs/writing_plugins.rst index cd165a3fbb..26bf04a2f4 100644 --- a/docs/writing_plugins.rst +++ b/docs/writing_plugins.rst @@ -64,7 +64,7 @@ To see the output of your plugin. Starting an installable plugin using cookiecutter ------------------------------------------------- -Plugins that can be installed should be written as Python packages using a ``setup.py`` file. +Plugins that can be installed should be written as Python packages, typically configured using a ``pyproject.toml`` file. The quickest way to start writing one an installable plugin is to use the `datasette-plugin `__ cookiecutter template. This creates a new plugin structure for you complete with an example test and GitHub Actions workflows for testing and publishing your plugin. @@ -79,31 +79,26 @@ Read `a cookiecutter template for writing Datasette plugins =61"] + build-backend = "setuptools.build_meta" + + [project] + name = "datasette-plugin-demos" + version = "0.1" + description = "Examples of plugins for Datasette" + readme = "README.md" + license = {text = "Apache License, Version 2.0"} + dependencies = ["datasette"] + + [project.entry-points.datasette] + plugin_demos = "datasette_plugin_demos" And a Python module file, ``datasette_plugin_demos.py``, that implements the plugin: @@ -126,9 +121,9 @@ And a Python module file, ``datasette_plugin_demos.py``, that implements the plu Having built a plugin in this way you can turn it into an installable package using the following command:: - python3 setup.py sdist + python3 -m build -This will create a ``.tar.gz`` file in the ``dist/`` directory. +This will create a source distribution and wheel in the ``dist/`` directory. You can then install your new plugin into a Datasette virtual environment or Docker container using ``pip``:: @@ -147,17 +142,12 @@ If your plugin has a ``static/`` directory, Datasette will automatically configu Use the ``datasette.urls.static_plugins(plugin_name, path)`` method to generate URLs to that asset that take the ``base_url`` setting into account, see :ref:`internals_datasette_urls`. -To bundle the static assets for a plugin in the package that you publish to PyPI, add the following to the plugin's ``setup.py``: +To bundle static assets for a plugin in the package that you publish to PyPI, add package data configuration to ``pyproject.toml``: -.. code-block:: python +.. code-block:: toml - package_data = ( - { - "datasette_plugin_name": [ - "static/plugin.js", - ], - }, - ) + [tool.setuptools.package-data] + datasette_plugin_name = ["static/plugin.js"] Where ``datasette_plugin_name`` is the name of the plugin package (note that it uses underscores, not hyphens) and ``static/plugin.js`` is the path within that package to the static file. @@ -180,17 +170,12 @@ The priority order for template loading is: See :ref:`customization` for more details on how to write custom templates, including which filenames to use to customize which parts of the Datasette UI. -Templates should be bundled for distribution using the same ``package_data`` mechanism in ``setup.py`` described for static assets above, for example: +Templates should be bundled for distribution using the same package data mechanism in ``pyproject.toml`` described for static assets above, for example: -.. code-block:: python +.. code-block:: toml - package_data = ( - { - "datasette_plugin_name": [ - "templates/my_template.html", - ], - }, - ) + [tool.setuptools.package-data] + datasette_plugin_name = ["templates/my_template.html"] You can also use wildcards here such as ``templates/*.html``. See `datasette-edit-schema `__ for an example of this pattern.