A ContextVar
set within a lifespan
context manager is not available inside request handlers. By contrast, doing the same thing via an application level dependency does appear set in the require handler.
import asyncio
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from contextvars import ContextVar
from litestar import Litestar
from litestar import get
from litestar.testing import AsyncTestClient
VAR = ContextVar[int]("VAR", default=0)
@asynccontextmanager
async def set_var() -> AsyncIterator[None]:
token = VAR.set(1)
try:
yield
finally:
VAR.reset(token)
@get("/example")
async def example() -> int:
return VAR.get()
app = Litestar([example], lifespan=[set_var()])
async def test() -> None:
async with AsyncTestClient(app) as client:
response = await client.get("/example")
assert (value := response.json()) == 1, f"Expected 1, got {value}"
if __name__ == "__main__":
asyncio.run(test())
Run the example above. Either via python example.py
or uvicorn example:app
and check the /example
route.
We should expect the response to be 1
since that's what's set during the lifespan
context manager, but it's always 0.
If you instead swap the lifespan
context manager for a dependency it works as expected:
import asyncio
from collections.abc import AsyncIterator
from contextvars import ContextVar
from litestar import Litestar
from litestar import get
from litestar.testing import AsyncTestClient
VAR = ContextVar[int]("VAR", default=0)
async def set_var() -> AsyncIterator[None]:
token = VAR.set(1)
try:
yield
finally:
VAR.reset(token)
@get("/example")
async def example(set_var: None) -> int:
return VAR.get()
app = Litestar([example], dependencies={"set_var": set_var})
async def test() -> None:
async with AsyncTestClient(app) as client:
response = await client.get("/example")
assert (value := response.json()) == 1, f"Expected 1, got {value}"
if __name__ == "__main__":
asyncio.run(test())
2.12.1
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too