.. _litestar: Litestar =========================================== Though it is not required, you can use *dishka-litestar* integration. It features: * automatic *REQUEST* scope management using middleware * passing ``Request`` object as a context data to providers for **HTTP** requests * injection of dependencies into handler function using decorator. How to use **************** 1. Import .. code-block:: python from dishka.integrations.litestar import ( FromDishka, LitestarProvider, inject, setup_dishka, ) from dishka import make_async_container, Provider, provide, Scope 2. Create provider. You can use ``litestar.Request`` as a factory parameter to access on *REQUEST*-scope .. code-block:: python class YourProvider(Provider): @provide(scope=Scope.REQUEST) def create_x(self, request: Request) -> X: ... 3. Mark those of your handlers parameters which are to be injected with ``FromDishka[]`` and decorate them using ``@inject`` .. code-block:: python @get('/') @inject async def endpoint( request: str, gateway: FromDishka[Gateway], ) -> Response: ... 3a. *(optional)* Set route class to each of your litestar routers to enable automatic injection (it works for HTTP and Websockets) .. code-block:: python @get('/') async def endpoint( request: str, gateway: FromDishka[Gateway], ) -> Response: ... r = DishkaRouter('', route_handlers=[endpoint]) app = Litestar(route_handlers=[r]) 4. *(optional)* Use ``LitestarProvider()`` when creating container if you are going to use ``litestar.Request`` in providers .. code-block:: python container = make_async_container(YourProvider(), LitestarProvider()) 5. *(optional)* Setup lifespan to close container on app termination .. code-block:: python @asynccontextmanager async def lifespan(app: Litestar): yield await app.state.dishka_container.close() app = Litestar([endpoint], lifespan=[lifespan]) 6. Setup ``dishka`` integration. .. code-block:: python setup_dishka(container=container, app=app) Websockets ********************** .. include:: _websockets.rst In litestar, your view function is called once per event, and there is no way to determine if it is an http or websocket handler. Therefore, you should use the special ``inject_websocket`` decorator for websocket handlers. Also decorator can be only used to retrieve *SESSION*-scoped objects. To achieve *REQUEST*-scope you can enter in manually: .. code-block:: python @websocket_listener("/") @inject_websocket async def get_with_request( a: FromDishka[A], # object with Scope.SESSION container: FromDishka[AsyncContainer], # container for Scope.SESSION data: dict[str, str] ) -> dict[str, str]: # enter the nested scope, which is Scope.REQUEST async with container() as request_container: b = await request_container.get(B) # object with Scope.REQUEST return {"key": "value"} or with class-based handler: .. code-block:: python class Handler(WebsocketListener): path = "/" @inject_websocket async def on_receive( a: FromDishka[A], # object with Scope.SESSION container: FromDishka[AsyncContainer], # container for Scope.SESSION data: dict[str, str] ) -> dict[str, str]: async with container() as request_container: b = await request_container.get(B) # object with Scope.REQUEST return {"key": "value"}