datasette/datasette
Simon Willison 80b7f987ca
write_wrapper plugin hook for intercepting write operations (#2636)
* Implement write_wrapper plugin hook for intercepting database writes

Add a new `write_wrapper` plugin hook that lets plugins wrap write
operations with before/after logic using a generator-based context
manager pattern. The hook receives (datasette, database, request,
transaction) and returns a generator function that takes a conn,
yields once to let the write execute, and can run cleanup after.

The write result is sent back via `generator.send()` and exceptions
are thrown via `generator.throw()`, giving plugins full visibility.

Also adds `request=None` parameter to execute_write, execute_write_fn,
execute_write_script, and execute_write_many, and threads request
through all view-layer call sites (insert, upsert, update, delete,
drop, create table, canned queries).

* Add documentation for wrap_write hook, fix lint issues

Document the wrap_write plugin hook in plugin_hooks.rst with
parameter descriptions and two examples: a simple logging wrapper
and an advanced SQLite authorizer-based table protection pattern.

Also fix black formatting and remove unused variable flagged by ruff.

* Rename wrap_write hook to write_wrapper for consistency with asgi_wrapper
* Move write_wrapper docs to just below prepare_connection
* Refactor write_wrapper tests to use pytest.parametrize

Consolidate duplicate test cases: merge before/after tests for
execute_write_fn and execute_write into one parametrized test, and
merge three parameter-passing tests into one parametrized test.

Claude Code transcript: https://gisthost.github.io/?c4c12079434e69677e4aa8ac664b21b8/index.html
2026-02-09 13:20:33 -08:00
..
default_permissions Switch to ruff and fix all lint errors, refs #2630 2026-01-23 20:43:16 -08:00
publish Get publish cloudrun working with latest Cloud Run (#2581) 2025-11-05 09:28:41 -08:00
static Fix filter-input and search-input zoom on iOS Safari 2026-01-28 18:41:58 -08:00
templates Fix for text None shown on /-/actions, closes #2599 2025-11-26 17:12:52 -08:00
utils Add request.form() for multipart form data and file uploads 2026-01-28 18:41:03 -08:00
views write_wrapper plugin hook for intercepting write operations (#2636) 2026-02-09 13:20:33 -08:00
__init__.py track_event() mechanism for analytics and plugins 2024-01-31 15:21:40 -08:00
__main__.py Add support for running datasette as a module (#556) 2019-07-11 09:07:44 -07:00
actor_auth_cookie.py Remove python-baseconv dependency, refs #1733, closes #1734 2022-05-02 12:39:06 -07:00
app.py Throttle schema refreshes to at most once per second, refs #2629 2026-01-23 21:03:16 -08:00
blob_renderer.py Rename route match groups for consistency, refs #1667, #1660 2022-03-19 09:52:08 -07:00
cli.py datasette.utils.StartupError() now becomes a click exception, closes #2624 2026-01-06 07:58:48 -08:00
database.py write_wrapper plugin hook for intercepting write operations (#2636) 2026-02-09 13:20:33 -08:00
default_actions.py Move takes_child/takes_parent information from Action to Resource (#2567) 2025-11-01 11:35:08 -07:00
default_magic_parameters.py Fix datetime.utcnow deprecation warning 2024-03-15 15:32:12 -07:00
default_menu_links.py Update permission hooks to include source_plugin column and simplify menu_links 2025-10-25 15:38:07 -07:00
events.py Fix type annotation bugs and remove unused imports 2025-10-26 16:03:13 -07:00
facets.py Fix huge performance bug in DateFacet, refs #2407 2024-08-21 14:38:11 -07:00
filters.py Fix type annotation bugs and remove unused imports 2025-10-26 16:03:13 -07:00
forbidden.py Fixed a bunch of unused imports spotted with ruff 2024-02-06 17:27:20 -08:00
handle_exception.py debugger: load 'ipdb' if present 2024-08-20 20:02:35 -07:00
hookspecs.py write_wrapper plugin hook for intercepting write operations (#2636) 2026-02-09 13:20:33 -08:00
inspect.py Modernize code to Python 3.6+ (#1158) 2020-12-23 09:04:32 -08:00
permissions.py datasette.client.get(..., skip_permission_checks=True) 2025-11-05 13:38:01 -08:00
plugins.py datasette.pm property, closes #2595 2025-11-13 10:31:03 -08:00
renderer.py Fix type annotation bugs and remove unused imports 2025-10-26 16:03:13 -07:00
resources.py Move takes_child/takes_parent information from Action to Resource (#2567) 2025-11-01 11:35:08 -07:00
sql_functions.py _search= queries now correctly escaped, fixes #651 2019-12-29 18:48:30 +00:00
tracer.py Tracer now catches errors, closes #2405 2024-08-21 12:19:18 -07:00
url_builder.py count all rows button on table page, refs #2408 2024-08-21 19:09:25 -07:00
version.py Release 1.0a24 2026-01-29 09:00:22 -08:00