mirror of https://github.com/tiangolo/fastapi.git
fix: resolve merge with master — lifespan app vs router
- Default lifespan: use app.router for _DefaultLifespan (router has _startup/_shutdown; FastAPI app does not). - Wrapper: when app is FastAPI, set fastapi_app from app and pass app.router to _run_lifespan_dependencies so lifespan deps are collected. - Test: use only Request.receive() (Starlette Request has no .send). Made-with: Cursor
This commit is contained in:
parent
df44ff0d9e
commit
53ebb9b46a
|
|
@ -49,6 +49,11 @@ def _wrap_lifespan_with_dependency_cache(original: Any) -> Any:
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def cm() -> Any:
|
async def cm() -> Any:
|
||||||
fastapi_app = getattr(app, "_fastapi_app", None)
|
fastapi_app = getattr(app, "_fastapi_app", None)
|
||||||
|
if fastapi_app is None and hasattr(app, "router"):
|
||||||
|
router = getattr(app, "router", None)
|
||||||
|
if router is not None and getattr(router, "_fastapi_app", None) is app:
|
||||||
|
fastapi_app = app
|
||||||
|
router_for_deps = getattr(app, "router", app)
|
||||||
stack: AsyncExitStack | None = None
|
stack: AsyncExitStack | None = None
|
||||||
orig_cm = original(app)
|
orig_cm = original(app)
|
||||||
try:
|
try:
|
||||||
|
|
@ -56,7 +61,9 @@ def _wrap_lifespan_with_dependency_cache(original: Any) -> Any:
|
||||||
stack = AsyncExitStack()
|
stack = AsyncExitStack()
|
||||||
await stack.__aenter__()
|
await stack.__aenter__()
|
||||||
cache: dict[Any, Any] = {}
|
cache: dict[Any, Any] = {}
|
||||||
await routing._run_lifespan_dependencies(app, cache, stack)
|
await routing._run_lifespan_dependencies(
|
||||||
|
router_for_deps, cache, stack
|
||||||
|
)
|
||||||
setattr(
|
setattr(
|
||||||
fastapi_app.state,
|
fastapi_app.state,
|
||||||
FASTAPI_LIFESPAN_DEPENDENCY_CACHE,
|
FASTAPI_LIFESPAN_DEPENDENCY_CACHE,
|
||||||
|
|
@ -1020,7 +1027,7 @@ class FastAPI(Starlette):
|
||||||
_inner_lifespan = (
|
_inner_lifespan = (
|
||||||
lifespan
|
lifespan
|
||||||
if lifespan is not None
|
if lifespan is not None
|
||||||
else (lambda app: routing._DefaultLifespan(app))
|
else (lambda app: routing._DefaultLifespan(app.router))
|
||||||
)
|
)
|
||||||
_lifespan = _wrap_lifespan_with_dependency_cache(_inner_lifespan)
|
_lifespan = _wrap_lifespan_with_dependency_cache(_inner_lifespan)
|
||||||
self.router: routing.APIRouter = routing.APIRouter(
|
self.router: routing.APIRouter = routing.APIRouter(
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,9 @@ def test_collect_lifespan_dependants_route_level_scope() -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_lifespan_dependency_synthetic_request_receive_send() -> None:
|
def test_lifespan_dependency_synthetic_request_receive_send() -> None:
|
||||||
"""Lifespan dep that uses Request.receive/send covers noop_receive and noop_send during startup."""
|
"""Lifespan dep that uses Request.receive covers noop_receive during startup."""
|
||||||
async def lifespan_dep(request: Request) -> str:
|
async def lifespan_dep(request: Request) -> str:
|
||||||
await request.receive()
|
await request.receive()
|
||||||
await request.send({"type": "http.response.body"})
|
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue