From 99785f4a2437333f7c07f96602c62b173c2982b7 Mon Sep 17 00:00:00 2001 From: Ivan Belyaev Date: Fri, 22 Nov 2024 23:46:17 +0300 Subject: [PATCH] upd tests and docs about using with litestar --- README.md | 2 +- .../litestar.md | 37 +++++++++++++++---- .../test_litestar/test_integration.py | 18 +++++++-- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 578b39e..95b8186 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ pip install deps-injection | [FastAPI](https://github.com/fastapi/fastapi) | ✅ | ✅ | ➖ | | [Flask](https://github.com/pallets/flask) | ✅ | ✅ | ✅ | | [Django REST Framework](https://github.com/encode/django-rest-framework) | ✅ | ✅ | ✅ | -| [Litestar](https://github.com/litestar-org/litestar) | ✅ | ⚠️ | ➖ | ➖ | +| [Litestar](https://github.com/litestar-org/litestar) | ✅ | ✅ | ➖ | ➖ | ## Using example with FastAPI diff --git a/docs/integration-with-web-frameworks/litestar.md b/docs/integration-with-web-frameworks/litestar.md index dd8d625..c2fc3c5 100644 --- a/docs/integration-with-web-frameworks/litestar.md +++ b/docs/integration-with-web-frameworks/litestar.md @@ -2,10 +2,10 @@ In order to successfully inject dependencies into Litestar request handlers, make sure that the following points are completed: -1. use **@inject** decorator **before** http-method Litestar decorator; +1. use `@inject` decorator **before** http-method `Litestar` decorator; -2. ⚠️ added for each injected parameter to the request handler a typing of the form -`Union[, Any]` for Python versions below 3.10 or ` | Any`; +2. added for each injected parameter to the request handler a typing of the form +`Annotated[, Dependency(skip_validation=True)]`. `Dependency` is object from `litestar.params`; 3. use the `Provide` marker from the `injection` (not from Litestar) package indicating the provider @@ -14,10 +14,17 @@ make sure that the following points are completed: ## Example ```python3 -from typing import Any, Union +from functools import partial +from unittest.mock import Mock +from typing import Annotated -from litestar import Litestar, get from injection import Provide, inject, DeclarativeContainer, providers +from litestar import Litestar, get +from litestar.params import Dependency +from litestar.testing import TestClient + + +_NoValidationDependency = partial(Dependency, skip_validation=True) class Redis: @@ -45,8 +52,8 @@ class Container(DeclarativeContainer): ) @inject async def litestar_endpoint( - redis: Union[Redis, Any] = Provide[Container.redis], - num: Union[int, Any] = Provide[Container.num], + num: Annotated[int, _NoValidationDependency()] = Provide[Container.num], + redis: Annotated[Redis, _NoValidationDependency()] = Provide[Container.redis], ) -> dict: value = redis.get(800) return {"detail": value, "num2": num} @@ -58,7 +65,7 @@ async def litestar_endpoint( ) @inject async def litestar_endpoint_object_provider( - num: Union[int, Any] = Provide[Container.num], + num: Annotated[int, _NoValidationDependency()] = Provide[Container.num], ) -> dict: return {"detail": num} @@ -69,4 +76,18 @@ _handlers = [ ] app = Litestar(route_handlers=_handlers) + +# Testing + +def test_litestar_overriding(): + mock_instance = Mock(get=lambda _: 192342526) + override_providers = {"redis": mock_instance, "num": -2999999999} + + with TestClient(app=app) as client: + with Container.override_providers(override_providers): + response = client.get("/some_resource") + + assert response.status_code == 200 + assert response.json() == {"detail": 192342526, "num2": -2999999999} + ``` diff --git a/tests/integration/test_litestar/test_integration.py b/tests/integration/test_litestar/test_integration.py index 2a58b8e..a8863b2 100644 --- a/tests/integration/test_litestar/test_integration.py +++ b/tests/integration/test_litestar/test_integration.py @@ -1,13 +1,23 @@ +import sys +from functools import partial from typing import Any, Union from unittest.mock import Mock import pytest from litestar import Controller, Litestar, get +from litestar.params import Dependency from litestar.testing import TestClient from injection import Provide, inject from tests.container_objects import Container, Redis +if sys.version_info >= (3, 9): + from typing import Annotated +else: + from typing_extensions import Annotated + +_NoValidationDependency = partial(Dependency, skip_validation=True) + @get( "/some_resource", @@ -15,8 +25,8 @@ ) @inject async def litestar_endpoint( - redis: Union[Redis, Any] = Provide[Container.redis], - num: Union[int, Any] = Provide[Container.num2], + redis: Annotated[Redis, _NoValidationDependency()] = Provide[Container.redis], + num: Annotated[int, _NoValidationDependency()] = Provide[Container.num2], ) -> dict: value = redis.get(800) return {"detail": value, "num2": num} @@ -41,8 +51,8 @@ class LitestarController(Controller): async def controller_endpoint( self, redis_key: int, - redis: Union[Redis, Any] = Provide[Container.redis], - num: Union[int, Any] = Provide[Container.num2], + redis: Annotated[Redis, _NoValidationDependency()] = Provide[Container.redis], + num: Annotated[int, _NoValidationDependency()] = Provide[Container.num2], ) -> dict: value = redis.get(redis_key) return {"detail": value, "num2": num}