Compare commits

..

3 commits

Author SHA1 Message Date
Simon Willison
bdc9731740
check-latest: true, add 3.15 to test matrix, to test RCs (#2895)
See https://simonwillison.net/2026/Sep/1/python-315-rc-2/
2026-09-01 13:37:15 -07:00
Alex Garcia
3e018bb1b5
Run startup via ASGI lifespan instead of waiting for the first request (#2887)
* Run startup via ASGI lifespan instead of waiting for the first request
* Ensure immutable table counts still precompute when startup ran first
2026-09-01 09:39:25 -07:00
Alex Garcia
e78b8a2e6a
Run datasette serve startup and uvicorn on a single event loop (#2886)
* Run datasette serve startup and uvicorn on a single event loop
* Move the serve-subprocess test plumbing into a conftest fixture
* Fix datasette-litestream URL and trim marker-task test comments
* Explain why serve_with_plugins needs a subprocess and plugin files
* Apply ruff 0.16 and black fixes
* Tweaked some comments
2026-09-01 09:32:37 -07:00
3 changed files with 5 additions and 12 deletions

View file

@ -11,16 +11,17 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
steps:
- uses: actions/checkout@v7
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
cache: pip
cache-dependency-path: pyproject.toml
check-latest: true
- name: Build extension for --load-extension test
run: |-
(cd tests && gcc ext.c -fPIC -shared -o ext.so)

View file

@ -670,11 +670,9 @@ def serve(
raise click.ClickException("--token can only be used with --get")
if get:
# Run async soundness checks before startup hooks, since invoke_startup
# now populates internal tables which requires querying each database
# --get means we don't run Uvicorn at all
run_sync(lambda: check_databases(ds))
# Run the "startup" plugin hooks
try:
run_sync(ds.invoke_startup)
except StartupError as e:
@ -709,8 +707,7 @@ def serve(
# on the loop (asyncio.create_task, Lock/Queue/Event objects, ...) is
# still alive when the server starts handling requests.
async def _serve_async():
# Run async soundness checks before startup hooks, since invoke_startup
# now populates internal tables which requires querying each database
# Populate internal catalog tables before invoke_startup
await check_databases(ds)
# Run the full startup sequence (immutable-database table-count

View file

@ -127,11 +127,6 @@ def test_startup_error_fails_fast_before_port_binds(serve_with_plugins):
A "startup" plugin hook that raises StartupError must fail fast: print
the message, exit non-zero, and never accept a connection on the port -
the failure must happen before uvicorn.Server binds the socket.
Note this is a characterization test, not a regression test: it also
passes on unmodified main, where startup already ran ahead of
uvicorn.run(). It earns its keep once startup moves into the ASGI
lifespan, where fail-fast is genuinely at risk.
"""
proc, port = serve_with_plugins(
{"startup_error_plugin": STARTUP_ERROR_PLUGIN}, wait_for_startup=False