Skip to content

build: support Python 3.14 and Django 5.2; migrate to zuban#62

Merged
mvaled merged 2 commits into
masterfrom
build/zuban-migration
Jun 24, 2026
Merged

build: support Python 3.14 and Django 5.2; migrate to zuban#62
mvaled merged 2 commits into
masterfrom
build/zuban-migration

Conversation

@mvaled

@mvaled mvaled commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Splits the environmental / baseline changes out of #61 (djhtmx 2.0) so they can land first, independently of the async pipeline feature.

What this does

  • Require Django >= 5.2 (was >= 4.1). Django < 5.2 is end-of-life upstream and was neither tested nor supported; 5.2 is the LTS line the downstream app ships and the first to support Python 3.14. This fixes the Python 3.14 test crash (Django 5.1's template Context.__copy__ under CPython 3.14).
  • Python 3.13 + 3.14 test matrix. On 3.14 the dependency floors rise to the first releases shipping 3.14 wheels (pydantic>=2.13, orjson>=3.11, lxml>=6); 3.13 is unaffected. uv.lock is pinned to the Django 5.2 LTS line via a dev-only [tool.uv] constraint, leaving the public floor open (the lock isn't part of the published package).
  • Migrate basedpyright → zuban (reads mypy-format config, runs its pyright-style default mode). The type-check job stays advisory (non-blocking) until zuban is green on the async refactor that djhtmx 2.0: async views, synchronous dispatch on a bounded pool #61 brings.
  • CI: pin setup-uv to 0.10.10 (matches REQUIRED_UV_VERSION).

Validation

  • make lint
  • make test on Python 3.13 and 3.14 (Django 5.2.15): ✅ 137 tests each
  • make typecheck (zuban): advisory — 16 errors remain in files the djhtmx 2.0: async views, synchronous dispatch on a bounded pool #61 async refactor rewrites (repo.py, command_queue.py, urls.py, sse_executor.py, testing.py); they clear once that lands, at which point the type-check can be made blocking.

Follow-up

#61 rebases on top of this to carry the async pipeline, its tests/docs, and the flip of the type-check to blocking.

🤖 Generated with Claude Code

mvaled and others added 2 commits June 24, 2026 05:41
Modernise the runtime and tooling baseline so the async 2.0 work lands on a
supported stack, split out of the larger 2.0 branch as its own change.

- Require Django >= 5.2 (was >= 4.1).  Django < 5.2 is end-of-life upstream and
  was neither tested nor supported; 5.2 is the LTS line the downstream app ships
  and the first to support Python 3.14.  This also fixes the test crash under
  CPython 3.14, which was Django 5.1's template Context.__copy__.
- Run tests on a Python 3.13 + 3.14 matrix.  On 3.14 the dependency floors rise
  to the first releases shipping 3.14 wheels (pydantic >= 2.13, orjson >= 3.11,
  lxml >= 6); 3.13 installs are unaffected.  uv.lock is pinned to the Django 5.2
  LTS line through a dev-only [tool.uv] constraint, leaving the public floor open
  (the lock is not part of the published package).
- Migrate the type checker from basedpyright to zuban (reads mypy-format config,
  runs its pyright-style default mode).  The type-check job stays advisory
  (non-blocking) until zuban is green on the async refactor.

CI also pins setup-uv to 0.10.10 to match REQUIRED_UV_VERSION.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Run zuban in mypy mode instead of the pyright-style default and get the codebase
to a clean type-check without the previous blanket disable list, so the checker
keeps its value.

- Switch the Makefile to `--mode mypy` via an overridable ZUBAN_MODE.
- Install the optional sentry-sdk / logfire backends in the typing group so
  tracing.py is type-checked for real instead of skipped as missing imports.
- Replace the eight-code blanket disable_error_code with just two: var-annotated
  (prefer inference over forced annotations) and the annotation-unchecked note.
- Fix the remaining reports in code rather than ignoring them: give HtmxComponent
  a TYPE_CHECKING __init__, make _Model generic over the model type, add explicit
  returns, drop a redundant re-annotation, and a few targeted `# type: ignore`
  for genuine framework/stub limitations (Channels override, is_usable stub,
  optional-import fallbacks).

The type-check job stays advisory; it can flip to blocking once the async PR,
which rewrites most of these files, is validated against this config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mvaled mvaled merged commit 5724ac2 into master Jun 24, 2026
4 checks passed
@mvaled mvaled deleted the build/zuban-migration branch June 24, 2026 04:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant