Skip to content

build(deps): declare lower bounds and test them with a lowest-direct resolution - #284

Merged
allen0099 merged 1 commit into
masterfrom
build/dependency-lower-bounds-194
Sep 27, 2026
Merged

allen0099 merged 1 commit into
masterfrom
build/dependency-lower-bounds-194

Conversation

@allen0099

@allen0099 allen0099 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

Closes #194

Part of #124.

Floors

Package Before Now Lowest that fails, and why
fastapi none >=0.133.0 0.132.x and older cap Starlette below 1.0 (see starlette)
starlette not declared >=1.0.0 0.52.1 / 1.0.0rc1: ImportError: cannot import name 'Session' from 'starlette.middleware.sessions'
pydantic none >=2.7.0 FastAPI 0.133.0 itself requires pydantic>=2.7.0; 2.7.0 passes
itsdangerous none >=1.1.0 0.24: No module named 'itsdangerous.exc' when Starlette's session module imports it
pymemcache (memcached, memcache) none >=4.0.0 3.3.0 and older: from pymemcache import HashClient fails. 3.4–3.5 construct the backend but were never run against a server, so the floor is the version all live testing has used
orjson (redis) none >=3.4.7 older 3.x releases have no Python 3.10 wheel; the codec uses only dumps/loads
redis[hiredis] >=5.3.0 unchanged
PyJWT >=2.9.0 unchanged

starlette is now declared directly because the package imports it in several modules, and the floor that matters is Starlette's own. fastapi>=0.133.0 is the first FastAPI that allows Starlette 1.x.

This matches reality rather than changing it. from starlette.middleware.sessions import Session has been there since 0.3.1, so an environment with an older FastAPI (and therefore Starlette < 1.0) could install fastapi-cachex and then fail at import. Annotated dependencies (AppCache, SessionDep, ...) work at every floor; the suite exercises them.

Checking the floors

  • New tox env lowest:
    • uses uv-venv-runner with uv_resolution = lowest-direct on Python 3.10, with the redis, memcached and jwt extras;
    • pytest, pytest-asyncio and httpx are direct requirements there too, so they resolve to their floors. Starlette 1.0's TestClient imports httpx; newer releases use httpx2.
  • lowest is not in env_list, so a plain uv run tox is unchanged.
  • New workflow .github/workflows/lowest.yml ("Lowest dependencies"):
  • docs/DEVELOPMENT.md describes the env (no zh-TW copy), and CLAUDE.md lists the command.

Verification

  • uv run tox -e lowest locally (live servers skipped): 841 passed, 190 skipped on Python 3.10.20 with fastapi 0.133.0, starlette 1.0.0, pydantic 2.7.0, itsdangerous 1.1.0, orjson 3.4.7, pymemcache 4.0.0, redis 5.3.0, PyJWT 2.9.0, httpx 0.27.0, pytest 8.3.5, pytest-asyncio 0.26.0.
  • Each "fails" entry above comes from the same suite, or an import, in a throwaway Python 3.10 venv with only that package moved below its floor. The pymemcache and orjson checks constructed a MemcachedBackend and ran tests/backends/test_codec.py.
  • uv run pytest on the locked versions: 841 passed, 190 skipped.
  • uv lock --check passes. The lock changes only in the recorded specifiers.
  • pre-commit ran on the commit, and both strict docs builds (EN and zh-TW) pass.
  • The live Redis/Memcached part of lowest runs in the new workflow; I did not run it locally.

CHANGELOG

Changed

  • Runtime dependencies declare minimum versions. fastapi>=0.133.0,
    starlette>=1.0.0 (now declared directly; the session middleware needs
    Starlette 1.0), pydantic>=2.7.0 and itsdangerous>=1.1.0; the extras
    require pymemcache>=4.0.0 and orjson>=3.4.7. Older versions could be
    installed before but failed at import. A lowest tox env and CI workflow
    test every floor. (#194)

…resolution

fastapi, itsdangerous and pydantic had no lower bounds, and starlette,
imported directly, was not declared at all. The session middleware needs
starlette.middleware.sessions.Session, which is new in Starlette 1.0, so an
unbounded install could resolve a FastAPI whose Starlette cap made the
package fail at import.

The new floors are the lowest versions the suite passes with on Python
3.10. A lowest tox env resolves every direct dependency, extras included,
to its floor, and a Lowest dependencies workflow runs it with live servers.
@allen0099
allen0099 merged commit 44ba6df into master Sep 27, 2026
12 checks passed
@allen0099
allen0099 deleted the build/dependency-lower-bounds-194 branch September 27, 2026 10:31
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
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.

Declare lower bounds for runtime dependencies

1 participant