chore(deps): raise Django floor to 6.1, refresh Cargo.lock

Summary

Routine dependency update, plus a support-floor decision that came out of it.

Django floor is now 6.1. 5.2 and 6.0 are dropped. The async extra moves to django-async-backend >= 6.1.1 — the release whose SQLCompiler fork learned compiler.quote_name and can therefore actually drive Django 6.1. Before it, every async ORM query on 6.1 raised AttributeError.

Cargo.lock refreshed — 32 packages, latest semver-compatible (pyo3 0.29.2, rustls 0.23.43, futures 0.3.34, aws-lc-rs 1.18.0, ...). No manifest floors moved: deadpool stays 0.12 and fallible-iterator stays 0.2 because deadpool-postgres and postgres-protocol require those majors, and bumping either would put two copies of the same trait in the graph. Upstream tokio-postgres is still 0.7.18, so the vendored buffer-cap patch is current.

CI. The async job's Django pin moves 6.0 → 6.1 rather than disappearing: it can only ever run the minor django-async-backend's fork supports, and that package's metadata (django>=6.1, unbounded) won't stop pip pairing it with a Django it can't drive — unpinned, the next Django release would turn that job red on every branch with no repo change. python-tests-no-async carries the "newest Django still works" claim instead, and now runs a two-entry matrix (latest + the declared floor) so both ends of django>=6.1 stay exercised.

The async job also gains a no-skip guard (scripts/ci_orm_no_skip.sh). tests/test_orm_live.py self-skips when the environment can't support it — right on a contributor's machine, and wrong in the one job whose purpose is running the async ORM against real PostgreSQL, where it used to mean a green pipeline that had quietly tested nothing. Each cause now fails loudly and names itself.

uv for the publish job goes 0.11.32 → 0.12.3. Please sanity-check this one — see the note at the bottom.

Testing

Live PostgreSQL 18 throughout (VPG_TEST_DSN), extension rebuilt with the new lockfile:

  • Django 6.1 + django-async-backend 6.1.1: 346 passed, 0 skipped — including the 18 async ORM tests in test_orm_live.py that were skipping on 6.1 before.
  • Django 6.1, no async extra: 313 passed, 25 skipped; the sync-only degrade contract (AsyncDatabaseWrapper is None) still holds.
  • scripts/check.sh green: fmt, clippy -D warnings, vpg-core tests, the vendored buffer-cap tests, ruff. mkdocs build --strict clean.
  • Guard script exercised in all three paths against a live database: healthy run exits 0; a fork that can't drive Django and a missing DSN each exit 1 naming their own cause.
  • The hardened version probe verified by simulating a future Django that deletes a symbol the fork imports at module scope — 7 passed / 18 skipped, instead of the collection error the previous version produced.

Performance sniff (AI-assisted, see disclosure)

A/B of the driver microbench (benchmarks/driver/ab.py, workloads jsonb_read / fetch_models / batch, 1000 rounds, 2 reps per variant) built from the old vs new lockfile on the same 12-thread box and the same PostgreSQL.

No regression. 23 of 24 (cell, metric) pairs land inside the run-to-run noise floor. The one that doesn't — batch/vpg CPU, +10.7% against a 7.9% noise floor — is environmental drift, not vpg: the batch/psycopg control cell, which cannot be affected by a Rust dependency bump, moved +9.7% in the same direction over the same window, and batch/vpg_query_many moved −1.3%. Headline ratios intact (jsonb_read vpg 46 µs CPU/op vs psycopg 201 µs; fetch_models fused 150 µs vs 446 µs).

AI disclosure: Claude Code — dependency bump, CI/doc edits, changelog and this description drafted with AI; the benchmark A/B and a two-reviewer adversarial pass over the diff were designed and run by AI on my hardware. All test and pipeline results quoted above are real runs, not claimed. Reviewed by me before opening.


Reviewer, two things worth your judgement. (1) The uv bump crosses 0.12.0, where uv publish began silently skipping distributions with non-normalized filenames — our artifacts are normalized and the sdist tag guard enforces that shape, and there are no OIDC changes in the range, but the new failure mode is a partial upload that exits 0, on the one job that burns a version number. Reverting that single line is zero-cost if you'd rather not find out during a release. (2) The floor bump is breaking for downstream pins: glitchtip-backend carries django-vpg>=0.4.0,<0.5; if it is still on Django 6.0, the next vpg release becomes uninstallable there. The next tag also needs to be ≥ 0.5.0, since published 0.4.0 declares django>=5.2.

Edited by David Burke

Merge request reports

Loading
Loading