This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
FastAPI-CacheX is a Python library (package: fastapi_cachex) providing HTTP caching and optional session management for FastAPI. It is published to PyPI as fastapi-cachex.
All commands use uv for environment management.
# Install development dependencies
uv sync --group dev
# Run tests
uv run pytest
# Run a single test file
uv run pytest tests/test_cache.py
# Run a specific test
uv run pytest tests/test_cache.py::test_function_name
# Run tests with coverage
uv run pytest --cov=fastapi_cachex --cov-report=term-missing
# Lint and format (ruff)
uv run ruff check fastapi_cachex
uv run ruff format fastapi_cachex
# Type checking
uv run mypy fastapi_cachex
uv run mypy fastapi_cachex --strict
# Run pre-commit on all files
uv run pre-commit run --all-files
# Run tox across all Python versions (3.10–3.14)
uv run tox
tox -e py310 # single versionThe library has four independent subsystems:
1. HTTP Caching (fastapi_cachex/cache.py, proxy.py, backends/)
@cache(...)decorator wraps FastAPI route handlers. It injects aRequestparameter into the handler signature if not already present, so the handler does not need to declare it.- Cache flow: check
no-store→ checkno-cache→ check ETag (If-None-Match) → check TTL-based cache hit → execute handler → store result. - Only GET requests are cached; other methods bypass the cache entirely.
- Cache keys follow the format
method|||host|||path|||query_params(separator defined intypes.py). BackendProxyis a non-instantiable class-level singleton (viaProxyMeta). CallBackendProxy.set(backend)at app startup;BackendProxy.get()raisesBackendNotFoundErrorif unset. Falls back toMemoryBackendautomatically inside@cacheif no backend is set.- Cache values are stored as
CacheEntry(fingerprint, content, media_type)dataclass (defined intypes.py).
2. Application-Level Caching (fastapi_cachex/manager.py, manager_proxy.py)
CacheManageris a thin, JSON-serializing wrapper around whatever backendBackendProxyhas configured, for caching arbitrary developer values (not HTTP responses) viaget/set/delete/has/clear_prefix/clear.- Keys live under their own
cache:-prefixed namespace by default (configurable viakey_prefix), separate from HTTP route keys andoauth_state:. get()never raises — returnsdefault(Noneunless overridden) on a miss or decode failure.set()letsTypeErrorpropagate for non-JSON-serializable values.CacheManagerProxymirrorsBackendProxy/SessionManagerProxy. TheAppCacheFastAPI dependency (get_app_cache, independencies.py) lazily creates and registers a defaultCacheManageron first use.clear()/clear_prefix()are built onbackend.get_all_keys(), so they are no-ops on the Memcached backend (see below).
3. Session Management (fastapi_cachex/session/)
- Optional subsystem, activated via
SessionMiddlewareandSessionManagerProxy. SessionManagerhandles create/get/update/delete/invalidate/regenerate operations. It storesSessionPydantic models serialized as JSON, wrapped inCacheEntryfor backend compatibility.- Token signing:
simpleformat uses HMAC-SHA256 (SecurityManager);jwtformat uses PyJWT (optional dependencyfastapi-cachex[jwt]). - Session token is passed via custom header (
X-Session-Tokenby default) orAuthorization: Bearertoken. SessionManagerProxymirrors theBackendProxypattern for managing theSessionManagersingleton.- Key FastAPI dependencies:
get_session,require_session,get_optional_session(insession/dependencies.py).
4. State Management (fastapi_cachex/state/)
StateManagerprovides one-time-use state tokens for OAuth flows. States are consumed (deleted) on first successfulconsume_state()call.- Uses the same cache backends, with key prefix
oauth_state:by default.
All backends implement BaseCacheBackend (abstract base in backends/base.py):
MemoryBackend: In-process dict with background cleanup task. Not suitable for multi-process production use.AsyncRedisCacheBackend(backends/redis.py): Fully async; usesSCAN(notKEYS) for pattern operations. Requiresredis[hiredis]andorjsonextras.MemcachedBackend(backends/memcached.py):clear_pattern/get_all_keysare no-ops (return0/[]with aRuntimeWarning) since the Memcached protocol has no key enumeration. Requirespymemcacheextra.
Backend keys are namespaced automatically (default prefix: fastapi_cachex:).
tests/conftest.py sets MemoryBackend as the default backend via an autouse=True fixture for every test. Tests requiring Redis or Memcached must configure their own backends. The memory_backend fixture manages the cleanup task lifecycle.
- Ruff is configured with
extend-select = ['ALL']with specific ignores (seepyproject.toml). Notable: E501 (line length), B008 (function calls in defaults), FBT001/FBT002 (boolean args — intentional for Cache-Control API). - mypy runs in strict mode on the package (not tests).
- pydocstring convention is Google style.
from __future__ import annotationsis used for forward references.- All public functions must have complete type annotations.
- Coverage threshold is 90% (enforced by
pytest-cov).