Commit graph

3,004 commits

Author SHA1 Message Date
Simon Willison
d3330695fa Always show 'Jump to...' menu item, closes #2725 2026-05-20 13:23:05 -07:00
Simon Willison
54b272baf6 Remove existing stale catalog_ tables, refs #2723
Now if there are any existing stale records in internal.db
those will be removed as well.
2026-05-20 12:39:54 -07:00
Simon Willison
bbbc1cd596 Remove height: 100% to fix Safari bug, closes #2724 2026-05-20 12:34:12 -07:00
Simon Willison
5d6de0154d Bump Black to black==26.3.1
Refs https://github.com/advisories/GHSA-3936-cmfr-pm3m
2026-05-20 12:18:01 -07:00
Simon Willison
7a914f8c65 Clear stale tables/other resources when DB removed, closes #2723 2026-05-20 12:16:23 -07:00
Simon Willison
40e78e0927
Change pull_request_target to pull_request event 2026-05-16 16:48:10 -07:00
Simon Willison
c1b3081863 Removed obsolete workflow 2026-05-16 16:44:28 -07:00
Simon Willison
10a1caac53 Upgrade a whole lot of GitHum Actions references 2026-05-16 16:38:49 -07:00
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
46d90a0b88 Bump to actions/checkout@v6 2026-05-12 16:46:56 -07:00
Simon Willison
036aa6aa2e Removed a rogue hyphen 1.0a29 2026-05-12 16:39:46 -07:00
Simon Willison
db16003865 Release 1.0a29
Refs #2695, #2701, #2708, #2709
2026-05-12 16:39:06 -07:00
Simon Willison
345f910043
Fix for Database.close()/Datasette.close() order (#2710)
Closes:
- #2709

The key behavior change: after close() starts, no new execute work can be submitted, but already-running execute work is allowed to finish before SQLite connections are closed.
2026-05-12 16:31:36 -07:00
Simon Willison
aa84fe008d Fix for column actions on Mobile Safari, closes #2708 2026-05-05 16:05:12 -07:00
Simon Willison
0dc7bb19d9 Table headers and column options visible for 0 rows
Closes #2701
2026-04-22 22:23:02 -07:00
Simon Willison
b15ce18ddc
TokenRestrictions.abbreviated(datasette) utility method for creating _r dicts (#2696)
Closes #2695
Refs https://github.com/simonw/datasette-auth-tokens/pull/42
2026-04-17 08:44:43 -07:00
Simon Willison
a6031c9847 Release 1.0a28 1.0a28
Refs #2691, #2692, #2693
2026-04-16 21:01:18 -07:00
Simon Willison
1cd53e1fc3
Datasette.close() method, plus pytest plugin to automatically call it during tests
Refs #2693, #2692
2026-04-16 20:50:51 -07:00
Simon Willison
630e557cdb Ran black 2026-04-16 20:44:21 -07:00
Simon Willison
b3001c1e5a Drop redundant _ds_client global now that ds_client is session-scoped
Session-scoped fixtures are cached per worker by pytest itself, so the
manual _ds_client module global is no longer needed.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:41:58 -07:00
Simon Willison
c9a7dc9be2 Declare ds_client as session-scoped so auto-close plugin spares it
ds_client already caches a single Datasette for the whole session via a
module-level _ds_client global, so the declared fixture scope should
match. With function scope the auto-close plugin correctly closes it
after the first test that uses it, which then breaks every subsequent
test that reuses the cached (now-closed) instance — as seen in the CI
coverage job, which runs serially rather than under pytest-xdist.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:40:51 -07:00
Simon Willison
03eeeb9d92 Docs: auto-close plugin now handles function-scoped fixtures
Describe the updated scoping rule: instances from test bodies and
function-scoped fixtures are closed automatically; session-, module-,
class- and package-scoped fixtures are exempt.

Refs #2692
2026-04-16 20:38:08 -07:00
Simon Willison
ede942a32e Fix ruff lints in close-related tests
Drop unused `bad = ...` assignment and unused `import pytest`.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:34:48 -07:00
Simon Willison
df96e12737 Auto-close Datasette instances from function-scoped fixtures too
The plugin now tracks instances across the full test protocol (setup,
call, teardown) and closes all of them at the end — including ones
created inside function-scoped pytest fixtures. Session-, module-,
class- and package-scoped fixtures are still exempted by subtracting
any instances their setup adds from the tracking list.

This makes downstream projects like datasette-alerts work at low FD
limits without every fixture needing an explicit ds.close() call.

Refs #2692
See https://github.com/simonw/datasette/issues/2692#issuecomment-4265072230

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:32:19 -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
c0153386ef FD-leak regression test for Datasette.close()
Creates and disposes 50 Datasette instances in a loop and asserts that
the number of open file descriptors and live threads does not grow,
exercising the full close() path end to end.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:18:05 -07:00
Simon Willison
34cc320eab Pytest auto-close plugin for Datasette instances
Installs a pytest11 entry point so that every Datasette() constructed
inside a pytest_runtest_call phase is auto-closed at the end of the test.
Fixture-scoped instances are untouched. Opt out via the
datasette_autoclose = false ini option.

This gives large test suites a safety net against FD exhaustion and leaked
write threads from the now-default temp-disk internal database without
requiring every existing test to be rewritten.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:15:50 -07:00
Simon Willison
d72dd35378 Wire Datasette.close into ASGI lifespan shutdown
AsgiLifespan now receives an on_shutdown callback that invokes
Datasette.close(), so resources are released cleanly when the ASGI server
delivers a lifespan.shutdown message (SIGTERM / SIGINT for uvicorn).

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:11:02 -07:00
Simon Willison
290f27158f Datasette.close() closes databases, shuts down executor, unlinks temp file
Datasette.close() iterates over every attached Database (including the
internal database), calls Database.close() on each, then shuts down the
ThreadPoolExecutor. Exceptions raised by one Database don't prevent the
others from being closed; the first exception is re-raised afterwards.
Idempotent.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:10:18 -07:00
Simon Willison
dabf8e4199 Database.close() shuts down write thread and raises DatasetteClosedError
After this commit, Database.close() sends a sentinel to the write queue so
the background write thread exits cleanly, closes cached read/write
connections, and marks the instance closed. Subsequent calls to execute*()
raise DatasetteClosedError. close() remains idempotent and one-way.

Refs #2692

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:09:47 -07:00
Simon Willison
ade0ef8a60 Restore compatibility with existing execute_write_fn() callbacks
Closes #2691
2026-04-16 19:14:32 -07:00
Simon Willison
2638200d26
Link to datasette.io preview tool 2026-04-15 17:19:43 -07:00
Simon Willison
1f99d5dd20 Release 1.0a27 1.0a27
Refs #1936, #2678, #2681, #2682, #2683, #2684, #2688, #2689
2026-04-15 16:11:54 -07:00
Simon Willison
67349e0e02 New :pr:ID shortcut for docs 2026-04-15 16:04:17 -07:00
Simon Willison
1a7030d668 API explorer special case for rowid in /-/upsert
Refs #1936
2026-04-15 15:47:48 -07:00
Simon Willison
5f39036b9b ok: true in /db.json for consistency 2026-04-15 15:44:06 -07:00
Simon Willison
73f338b9f3 Better example in API explorer for /-/upsert, closes #1936 2026-04-15 15:29:59 -07:00
Simon Willison
4922fc2e39 Disallow null primary keys in upsert
Refs https://github.com/simonw/datasette/issues/1936#issuecomment-1341849496
2026-04-15 15:11:33 -07:00
Simon Willison
a973e3ffa1 Normalize headers in CSRF checks, refs #2689 2026-04-14 19:24:38 -07:00
Simon Willison
028cc2446f Don't allow cookies with Authorization: Bearer to bypass CSRF
Refs #2689
2026-04-14 19:23:21 -07:00
Simon Willison
f02484c3de From 409 warnings down to 52 warnings.
By closing unclosed database connections.

Refs #2614
2026-04-14 18:46:47 -07:00
Simon Willison
9c164572d3
Add actor= parameter to datasette.client methods (#2688)
`datasette.client.get(path, actor={"id": "root"}` now makes the internal request with that actor as `request.actor` - same for the other HTTP verb methods on `datasette.client`.

Upgraded relevant tests to use the new `actor=` mechanism.
2026-04-14 18:31:57 -07:00
Simon Willison
0b639a8122
Replace token-based CSRF with Sec-Fetch-Site header protection (#2689)
- New CSRF protection middleware inspired by Go 1.25 and research by Filippo Valsorda - https://words.filippo.io/csrf/ - this replaces the old CSRF token based protection.
- Removes all instances of `<input type="hidden" name="csrftoken" value="{{ csrftoken() }}">` in the templates - they are no longer needed.
- Removes the `def skip_csrf(datasette, scope):` plugin hook defined in `datasette/hookspecs.py` and its documentation and tests.
- Updated CSRF protection documentation to describe the new approach.
- Upgrade guide now describes the CSRF change.
2026-04-14 17:11:36 -07:00
Simon Willison
fc1794719a
Database(is_temp_disk=True) option, used for internal database (#2684)
Closes #2683

* Add is_temp_disk option to Database for temp file-backed databases

Replace the default in-memory internal database with a temporary
file-backed database using WAL mode. This fixes concurrent read/write
locking errors that occur with named in-memory SQLite databases.

The new is_temp_disk parameter on Database creates a temp file via
tempfile.mkstemp, connects to it as a regular file-based database
with WAL mode enabled, and cleans it up on close() and via atexit.

https://claude.ai/code/session_01TteLrUjpDcARjnP1GMRqz2
2026-03-30 21:03:21 -07:00
Simon Willison
94d14e3d37 Warning note about VACUUM and RenameTableEvent
I noticed that VACUUM can update the rootpage for tables in a way that
could confuse our rename table detection logic - but using the
execute_isolated_fn() method to run VACUUM avoids this problem.

Refs #2681
2026-03-30 16:11:06 -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
dependabot[bot]
9b5cb1347c
Bump rollup from 3.29.5 to 3.30.0 (#2651)
Bumps [rollup](https://github.com/rollup/rollup) from 3.29.5 to 3.30.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/v3.30.0/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v3.29.5...v3.30.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 3.30.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 10:54:48 -07:00
dependabot[bot]
1a64d5e55e
Bump picomatch from 2.3.1 to 2.3.2 (#2679)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 10:54:34 -07:00
Simon Willison
c479e7dec9
Document call_with_supported_arguments as a supported public API (#2678)
* Document call_with_supported_arguments as a supported public API

Mark both call_with_supported_arguments and async_call_with_supported_arguments
with the @documented decorator and add documentation to docs/internals.rst
so plugin authors can use these dependency injection utilities in their own code.

https://claude.ai/code/session_01DKogZpHwzCTrbeG4XjXmNc
2026-03-30 10:44:10 -07:00
Simon Willison
4fcf474088 Release 1.0a26 1.0a26
Refs #1592, #2661, #2664, #2666, #2669, #2670, #2671, #2672
2026-03-18 15:13:37 -07:00