Commit graph

7 commits

Author SHA1 Message Date
Simon Willison
3110faa0ba
Replace Janus queue with asyncio.Future
Closes #1752

AI generated patch explanation: https://gisthost.github.io/?e2b8d9c7666e988b5c003ff5e5ef3098
2026-05-16 11:45:43 -07:00
Simon Willison
d23b32c3e5 Call ds.close() in more places in tests
Refs #2692
2026-04-16 20:25:58 -07:00
Simon Willison
312f41b0c2
RenameTableEvent, plus write connection track_event() mechanism (#2682)
* Add track_event callback to execute_write_fn and write_wrapper

Allows write functions and write_wrapper generators to queue events
during a write operation that are dispatched after successful commit.
The fn or wrapper can optionally accept a `track_event` parameter
(detected via call_with_supported_arguments). Events are discarded
if the write raises an exception.

Does not yet handle the block=False (non-blocking) case - events
queued during non-blocking writes are currently silently discarded.

Refs https://github.com/simonw/datasette/issues/2681

* Dispatch track_event events for non-blocking (block=False) writes

Spawns a background asyncio task that awaits the write thread's reply
queue and dispatches pending events after a successful non-blocking
write. Events are still discarded if the write raises an exception.

Refs https://github.com/simonw/datasette/issues/2681

* Warn that events won't fire for other processes

Refs https://github.com/simonw/datasette/issues/2681#issuecomment-4157118662
2026-03-30 11:20:46 -07:00
Simon Willison
1c6c6d2e68 Fix test_write_wrapper_set_authorizer: use permissive callback instead of None
conn.set_authorizer(None) does not clear the authorizer - SQLite treats
None as an invalid callback. The denied state persists on the shared
write connection, causing subsequent non-deny test cases to fail.

Fixes test added in 8a315f3d.
2026-02-17 13:30:46 -08:00
Simon Willison
5c3137d148 Black formatting 2026-02-17 13:30:24 -08:00
Simon Willison
8a315f3d7d Added a test to exercise the write_wrapper example
This example in the docs is now dulicated in a test:

80b7f987ca/docs/plugin_hooks.rst (write-wrapper-datasette-database-request-transaction)

Refs #2637
2026-02-09 13:27:23 -08:00
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