Repository navigation
Switch to uv, update the tooling and bundled UIs, and honour the root_path - #12
Merged
Merged
Conversation
joakimnordling
force-pushed
the
feature/updates
branch
2 times, most recently
from
September 27, 2026 02:46
5373560 to
651c220
Compare
Packaging is now PEP 621 with the uv_build backend. The package stays in the repository root (module-root = ""), and the built wheel contains the same files as before, including the bundled static files. - poetry.lock -> uv.lock, and .python-version pins the lowest supported Python for local development - ruff replaces black, isort and flake8; setup.cfg is gone, with the pytest and mypy configuration moved into pyproject.toml - skjold could only read poetry.lock, so `uv audit` took over the vulnerability scan in `invoke test` - the workflows use astral-sh/setup-uv; pre-commit is a dev dependency now, so CI no longer installs it separately - `invoke release` reads the version with `uv version` instead of a regex - tests/conftests.py -> tests/conftest.py, which is the name pytest looks for Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Poetry build included them (they're in the 0.2.0 wheel on PyPI), and so did the uv_build default, since they live inside the package directory. There's no reason to install them into a user's environment. They stay in the sdist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
With a src layout the tests can only import the installed package, never the source tree via the current directory, so they exercise what actually ships: a missing static file in the wheel now fails the suite instead of passing locally. The build backend needs no layout configuration any more; excluding the tests from the wheel happens by itself, and the sdist keeps them via source-include. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
actions/checkout v4.2.2 -> v7.0.1, astral-sh/setup-uv v10.1.0 -> v10.2.0, actions/upload-artifact v5.0.0 -> v7.0.1, actions/download-artifact v6.0.0 -> v8.0.1 and pypa/gh-action-pypi-publish v1.13.0 -> v1.14.2. The major bumps are mostly the move to the Node 24 runtime, which the hosted runners have. Two behaviour changes that don't affect these workflows: checkout now refuses to check out the PR head on pull_request_target without allow-unsafe-pr-checkout (neither workflow uses that trigger), and download-artifact fails on a digest mismatch instead of warning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pre-commit-hooks v5.0.0 -> v6.0.0, ruff-pre-commit v0.16.8 -> v0.16.9 (with the ruff pin in pyproject.toml) and uv-pre-commit 0.12.16 -> 0.12.19. Prettier stays on mirrors-prettier v2.7.1: `pre-commit autoupdate` wants to move it to a prettier 4 alpha, which isn't worth taking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
starlette 1.7 deprecates plain httpx in its test client, which is what fastapi.testclient.TestClient is built on, and the tests warned about it on every run. Nothing in the library itself uses httpx. The test client only understands httpx2 from starlette 1.2 onwards, and FastAPI capped starlette below that until 0.133.0, the first release without an upper bound on it. That is also the lowest FastAPI that allows a starlette with the CVE-2026-54283 fix (1.3.1); every earlier one pins starlette below 1.0. Verified against fastapi 0.133.0: the tests pass with the starlette that a fresh install resolves to, and the library itself works with starlette 0.40.0, the lowest FastAPI still allows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The floors were the constraints Poetry had, most of them a major version behind what the lock resolves to, so they documented versions that were never tested. They now match what `uv sync` installs. The ruff pin stays exact, as it tracks the ruff-pre-commit rev rather than the lock. The upgrade moves three of pre-commit's dependencies: filelock 4.0.3 -> 4.0.4, nodeenv 1.10.0 -> 1.11.0 and platformdirs 4.11.15 -> 4.12.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
swagger-ui-dist 5.19.0 -> 5.33.0 and redoc 2.4.0 -> 2.5.4, fetched with `uv run update-fastapi-standalone-docs`. FastAPI's own docs.py points at swagger-ui-dist@5 and redoc@2, so these are the versions it serves from the CDNs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An app mounted inside another app is served under a prefix it has no way of knowing: mount() doesn't touch its root_path, and the prefix only arrives with each request, in the ASGI scope. The asset URLs were built without it, so the docs of a mounted app asked the outer app for swagger-ui.css and got a 404. The functions this library patches don't get the request. FastAPI does build the openapi_url it passes them out of the request's root_path and the app's own openapi_url, though, so removing the latter leaves the prefix to build the URLs with. Being per request, this also covers a proxy that varies the root_path. An app given an explicit root_path was affected as well and is fixed by the same change. Using StandaloneDocs on both a main app and an app mounted inside it now works too, as long as they agree on the settings the README lists. A favicon URL passed by the caller is still used as-is, as it may point anywhere. Fixes ioxiocom#11 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A minor bump rather than a patch: the lowest supported FastAPI moved from 0.109.1 to 0.133.0, so this drops users of the versions in between. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
joakimnordling
force-pushed
the
feature/updates
branch
from
September 27, 2026 03:02
651c220 to
8caaf97
Compare
The default is to persist the token for the later steps of the job to use, in a file under $RUNNER_TEMP as of checkout v6. Neither workflow runs git operations that need it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
joakimnordling
force-pushed
the
feature/updates
branch
from
September 27, 2026 03:21
8caaf97 to
1dbff1c
Compare
joakimnordling
marked this pull request as ready for review
September 27, 2026 03:25
ruff-pre-commit v0.16.9 -> v0.16.10, with the ruff pin that tracks it, and uv-pre-commit 0.12.19 -> 0.12.23. pre-commit-hooks and all the pinned GitHub Actions are already at their newest releases. The lock moves fastapi 0.141.1 -> 0.142.2 and mypy 2.3.1 -> 2.4.0, with mypy's floor following it, plus transitive updates. pydantic-core stays at 2.46.5, which is what pydantic pins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
It reached its end of life on 2026-10-01. The floor moves to 3.11 in requires-python, in the classifiers, in the CI matrix and in .python-version, which pins the lowest supported version for local development. Dropping it also lets the lock go without the exceptiongroup and tomli backports. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A fix for the schema and operation virtualization that 5.33.0 introduced, with path item references. Only the bundle changed; the stylesheet and the license are the same as in 5.33.0, and ReDoc is still on 2.5.4, its newest 2.x. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Python 3.15: the trove classifier, and a 3.15 job in the test matrix. The tests and mypy pass on it. - uv 0.13.0 knows Python 3.15.0. required-version is >=0.13, and [build-system] allows its build backend, uv_build 0.13 (no configuration changes). The uv-lock pre-commit hook is on 0.13.0. - ruff-pre-commit v0.16.10 -> v0.17.0, with the ruff pin that tracks it. No new findings. pre-commit-hooks is already at its newest release, and prettier stays on mirrors-prettier v2.7.1. - setup-uv 10.2.0 -> 10.3.0 (checksums for uv up to 0.13.0), upload-artifact 7.0.1 -> 7.0.2 and download-artifact 8.0.1 -> 8.0.2 (retries when rate-limited). checkout and gh-action-pypi-publish are already the newest. - The lock moves fastapi 0.142.2 -> 0.143.0, pydantic 2.13.5 -> 2.14.0 (with pydantic-core 2.50.0) and ruff, plus transitive updates. The other dev dependency floors already match the locked versions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Switches the project from Poetry to uv, brings the tooling and the bundled docs UIs up
to date, and fixes the asset URLs of an app that is served under a prefix.
The commits are each self-contained and worth reading on their own.
Packaging
pyproject.tomlis now PEP 621 with theuv_buildbackend,poetry.lockbecomesuv.lock, and.python-versionpins 3.11, the lowest supportedversion, for local development.
skjoldcould only readpoetry.lock, souv audittook over the vulnerability scan in
invoke test.setup.cfgis gone, with the pytest and mypyconfiguration moved into
pyproject.toml. The reformatting was almost a no-op; theonly code changes were
Optional[str]->str | NoneandList->list.uv_buildpublishes only whatpyproject.tomllists.src/layout, tests outside the package. The tests can now only import theinstalled package, never the source tree via the current directory, so they exercise
what actually ships: a static file missing from the wheel fails the suite instead of
passing locally. The wheel no longer contains the tests, which the Poetry build did
ship (they are in the 0.2.0 wheel on PyPI); the sdist keeps them.
Verified that the built wheel still carries all eight static files, and that the test
suite passes against the wheel installed in an isolated environment, from outside the
repository.
Dependencies and tooling
fastapi.testclient.TestClientis what needs httpx here,and starlette 1.7 deprecates plain httpx in its test client, which warned on every
test run. The test client only understands httpx2 from starlette 1.2, and FastAPI
capped starlette below that until 0.133.0, so the lowest supported FastAPI moves
from 0.109.1 to 0.133.0. That is also the lowest FastAPI that allows a starlette
with the CVE-2026-54283 fix (1.3.1); every earlier one pins starlette below 1.0.
the floor is now 3.11, in
requires-python, the classifiers, the CI matrix and.python-version. The lock no longer needs theexceptiongroupandtomlibackports.
required-versionis>=0.13, and[build-system]allowsuv_build0.13 (noconfiguration changes).
also stop persisting the GitHub token for the later steps of the job, which neither
workflow needs.
pre-commit-hooksv6.0.0,ruff-pre-commitv0.17.0,uv-pre-commit0.13.0. Prettier stays onmirrors-prettierv2.7.1 deliberately:pre-commit autoupdatewants to move it to a prettier 4 alpha.constraints they were, most of which were a major version behind.
uv run update-fastapi-standalone-docs. FastAPI's owndocs.pypoints atswagger-ui-dist@5andredoc@2, so these are the versions it serves from the CDNs.Checked the files byte-for-byte against those pinned versions, and confirmed the ReDoc
logo patch still applies: the bundle has no reference left to
cdn.redoc.ly.Fixes #11
An app mounted inside another app is served under a prefix it has no way of knowing:
mount()doesn't touch itsroot_path, and the prefix only arrives with each request,in the ASGI scope. The asset URLs were built without it, so the docs of a mounted app
asked the outer app for
swagger-ui.cssand got a 404.The functions this library patches don't get the request. FastAPI does build the
openapi_urlit passes them out of the request'sroot_pathand the app's ownopenapi_url, though, so removing the latter leaves the prefix to build the URLs with.Being per request, this also covers a proxy that varies the
root_path.Note that the fix suggested in the issue,
self.app.root_path, does not cover the casethe issue describes:
mount()never sets that attribute, so it stays empty for a mountedapp. It does cover an app given an explicit
root_path, which was broken too and isfixed by the same change here.
Five new tests: the mounted app for both UIs, an explicit
root_path, a caller-suppliedfavicon URL (used as-is, as it may point anywhere), and StandaloneDocs on both a main app
and an app mounted inside it, which now works as long as they agree on their settings.
The README's disclaimer says what "agree" means, which it did not spell out before:
docs_url,redoc_urlandopenapi_urlare FastAPI settings, so the old wording couldbe satisfied and still break.
Version
Bumped to 0.3.0 rather than a patch release: raising the FastAPI floor and dropping
Python 3.10 both leave users behind.
Checked
uv run invoke testis green on all counts: every pre-commit hook, mypy, 15 tests, anduv audit. The tests and mypy also pass on Python 3.15. Both UIs were also opened in abrowser, with and without
with_google_fonts, and with the app mounted under a prefix:every request goes to localhost, and the only external reference anywhere is the Google
Fonts stylesheet that
with_google_fonts=Trueis meant to add.🤖 Generated with Claude Code