Files
responder/tests/test_di_nesting.py
kennethreitz 0eb9f27755 Support nested inline Depends; cache dependency & body-param inspection
- Inline Depends(...) can now nest inside a provider (sub-dependency
  chains), matching FastAPI. The resolver checked a provider's parameter
  annotations but not its _Depends defaults, so a provider with an inline
  Depends param raised DependencyResolutionError; only named
  @api.dependency() providers could chain. Both resolve() and
  resolve_provider() now resolve inline Depends defaults recursively (cycle
  detection via the existing resolution stack still applies).

- _depends_params ran uncached inspect.signature on every request; it now
  uses a WeakKeyDictionary keyed on __func__, matching the sibling caches.

- _body_injections recomputed the model-parameter plan and an uncached
  inspect.signature on every write request. The per-endpoint signature/hint
  work is now memoized (_body_model_candidates); only the cheap per-request
  path/dependency/auth filtering runs per call. Behavior is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:22:35 -04:00

48 lines
1.2 KiB
Python

"""Inline Depends(...) can now nest inside a provider (sub-dependency chains),
matching the FastAPI pattern. Previously only named @api.dependency() providers
could chain; a provider with an inline Depends default raised
DependencyResolutionError."""
import responder
from responder import Depends
def _api():
return responder.API(allowed_hosts=[";"], session_https_only=False)
def test_inline_depends_nests_inside_provider():
api = _api()
def get_db():
return "db-conn"
def get_user(db=Depends(get_db)):
return f"user@{db}"
@api.route("/me")
def me(req, resp, *, user=Depends(get_user)):
resp.text = user
assert api.requests.get("/me").text == "user@db-conn"
def test_inline_depends_deeper_chain_and_request_access():
api = _api()
def get_prefix():
return "id"
def get_token(req, prefix=Depends(get_prefix)):
return f"{prefix}:{req.headers.get('X-Token', 'anon')}"
def get_principal(token=Depends(get_token)):
return {"token": token}
@api.route("/who")
def who(req, resp, *, principal=Depends(get_principal)):
resp.media = principal
r = api.requests.get("/who", headers={"X-Token": "abc"})
assert r.json() == {"token": "id:abc"}