Skip to content

feat: bump FastAPI to 0.136.3 and Starlette to 1.2.1#379

Merged
allison-truhlar merged 7 commits into
mainfrom
bump-fastapi
Jun 5, 2026
Merged

feat: bump FastAPI to 0.136.3 and Starlette to 1.2.1#379
allison-truhlar merged 7 commits into
mainfrom
bump-fastapi

Conversation

@mkitti

@mkitti mkitti commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Bump FastAPI to 0.136.3 and Starlette to 1.2.1

Follow-up to #378 (stacked on sync-dep-bounds; this PR will retarget to main once #378 merges). #378 deferred the FastAPI/Starlette upgrade to keep the bounds-sync change behavior-free — this PR is that upgrade.

Why

FastAPI was pinned >=0.119.1,<0.120, and fastapi-core 0.119.1 capped Starlette at <0.49.0, so Starlette was stuck at 0.48.0 even though conda-forge has it through 1.2.1. Newer FastAPI (fastapi-core 0.136.3) drops that cap (starlette >=0.46.0, no upper bound), which unblocks Starlette 1.x.

Changes

  • fastapi: >=0.119.1,<0.120>=0.136.3,<0.137 in both the PyPI and pixi blocks.
  • starlette: 0.48.01.2.1 (via pixi update starlette; pulled in transitively, not declared directly).
  • Added httpx2 >=2.2.0,<3 as a test dependency (see httpx note below).
  • Removed the redundant explicit httpx runtime dependency (unused by our code; still provided transitively by the fastapi standard meta-package).
  • pixi.lock regenerated.

FastAPI 0.120 → 0.136 breaking-change review

Reviewed every flagged breaking change in the range against this codebase:

Change Version Impact here
Security classes raise 401 not 403 0.122 None — no fastapi.security usage
Drop Python 3.8 / 3.9 0.125 / 0.129 None — we require ≥3.12
Drop pydantic.v1 0.126–0.128 None — Pydantic v2
Deprecate ORJSONResponse/UJSONResponse 0.131 None — not used
strict_content_type (default on) 0.132 Applies — see below
Underscore headers rejected 0.136.3 None — no Header params
SSE field validation 0.136.2 None — no event-stream endpoints
Starlette → 1.0 0.136.0 Applies — middleware/StaticFiles stack

The two that touch us — strict_content_type and the Starlette 1.0 major bump — are both validated by the full suite (318 passing). For strict_content_type specifically, added a regression test (test_set_preference_requires_json_content_type) asserting that a JSON body sent without application/json is now rejected (mapped to 400 by the app's validation_exception_handler) rather than silently parsed.

httpx → httpx2 note

Starlette 1.x deprecates using httpx with its TestClient and prefers httpx2. fileglancer has no direct httpx usage — it's consumed only by the TestClient at test time — so this is not a code migration. Adding httpx2 as a test dependency makes the TestClient prefer it and silences the StarletteDeprecationWarning. The runtime httpx pin was redundant (FastAPI's standard meta-package guarantees httpx anyway), so it was removed.

Verification

pixi run -e test pytest318 passed, no warnings with fastapi 0.136.3 + starlette 1.2.1 + httpx2 2.3.0 on Python 3.14.

🤖 Generated with Claude Code

mkitti and others added 4 commits June 2, 2026 18:30
Move fastapi from >=0.119.1,<0.120 to >=0.136.3,<0.137 in both the PyPI
and pixi dependency blocks. Newer fastapi dropped its starlette <0.49
upper bound (fastapi-core 0.136.3 requires starlette >=0.46.0), which
unblocks starlette; pixi update pulled starlette 0.48.0 -> 1.2.1.

Reviewed fastapi 0.120->0.136 breaking changes; the only ones touching
this codebase are 0.132 strict_content_type (JSON body endpoints) and
the starlette 1.0 major bump under the middleware/StaticFiles stack.

NOTE: test suite still needs to be re-run against starlette 1.2.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a regression test asserting that a JSON body sent without an
application/json Content-Type is rejected (mapped to 400 by the app's
validation_exception_handler) rather than silently parsed as it was
pre-fastapi-0.132. Guards the strict_content_type default introduced
by the fastapi 0.136.3 bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Starlette 1.x deprecates using httpx with its TestClient and prefers
httpx2. fileglancer has no direct httpx usage (only the test client
consumes it), so add httpx2 >=2.2.0,<3 as a test dependency in both the
pixi test feature and the PyPI test extra. This silences the
StarletteDeprecationWarning; the runtime httpx dependency is left as-is.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fileglancer's code never imports httpx directly; it is only consumed by
starlette's TestClient at test time. httpx is also guaranteed by the
fastapi (standard) meta-package, which depends on httpx as part of its
standard bundle, so removing the explicit pin does not drop httpx from
the environment. Remove the redundant declaration from both the PyPI and
pixi runtime dependency blocks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mkitti

mkitti commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

How this compares to #377

Both this PR and #377 land at the same resolved versions in the dev env (fastapi 0.136.3, starlette 1.2.1, httpx2), so they're not opposed in outcome — but they get there differently, and the difference matters for review and for preventing the drift from recurring.

1. Capping vs. uncapping. #377 reaches 0.136.3 implicitly: it removes the upper caps from [tool.pixi.dependencies] (e.g. fastapi >=0.119.1, uncapped) so the solver is free to float the dev lock up to whatever's current. This unblocks Starlette as a side effect, but it also re-opens the door to silent major bumps — the next solve can move fastapi/starlette/etc. again with no PR. This PR (stacked on #378) does the opposite: it pins fastapi >=0.136.3,<0.137 explicitly on both surfaces, so the upgrade is a deliberate, reviewed change and the bound still protects against the next breaking minor.

2. httpx2 as runtime vs. test dep. #377 swaps httpx >=0.28.1,<0.29httpx2 >=2.2.0,<3 in the runtime dependencies. fileglancer has no direct httpx/httpx2 usage in application code — it's consumed only by Starlette's TestClient at test time, and fastapi's standard meta-package already guarantees an httpx at runtime. So this PR instead adds httpx2 as a test dependency and removes the runtime httpx pin entirely, which is where the dependency actually belongs.

3. Verification of the behavioral changes. Jumping 0.119 → 0.136 crosses two changes that touch this codebase — FastAPI 0.132's strict_content_type (JSON bodies without an application/json Content-Type are now rejected) and the Starlette 1.0 major bump. This PR includes a breaking-change review of the full 0.120 → 0.136 range against the code (see the PR description) and adds a regression test (test_set_preference_requires_json_content_type) covering the strict-Content-Type behavior. #377 doesn't add coverage for either.

4. Reviewability. #377 bundles cap-loosening + the httpx→httpx2 swap + the implicit fastapi/starlette jump into one PR with a ~9k-line lock diff. The #378#379 split separates the behavior-free bounds sync (#378) from the isolated, reviewed FastAPI/Starlette upgrade (this PR), so each can be evaluated on its own.

In short: same destination, but this PR makes the upgrade explicit and pinned, keeps httpx2 scoped to tests, and verifies the two behavioral changes the version jump introduces.

Base automatically changed from sync-dep-bounds to main June 3, 2026 21:26
mkitti and others added 3 commits June 3, 2026 18:15
_file_info_from_direntry and _file_info computed rel_path via
os.path.realpath(full_path), which follows the final component. For a
broken symlink with an absolute target (e.g. "/nonexistent/path"), this
resolves to the nonexistent target. On Windows that target lands on a
different drive than the chroot, so os.path.relpath raised
ValueError ("path is on mount 'D:', start on mount 'C:'"), failing four
symlink tests on windows-latest.

Resolve only the parent directory and append the entry name, so a
symlink reports its own location relative to root rather than its
(possibly broken or cross-drive) target. name is unaffected since it
derives from basename(absolute_path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@allison-truhlar allison-truhlar merged commit 5edbcda into main Jun 5, 2026
5 checks passed
@allison-truhlar allison-truhlar deleted the bump-fastapi branch June 5, 2026 13:56
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.

2 participants