From 90e75164ce058067bb2346ec2239e3f8e89858f9 Mon Sep 17 00:00:00 2001 From: nir Date: Tue, 17 Sep 2024 08:23:26 +0300 Subject: [PATCH 1/5] add `Injected` annotation --- aioinject/markers.py | 9 +++++++++ tests/test_inject.py | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/aioinject/markers.py b/aioinject/markers.py index 4589f67..4129a9b 100644 --- a/aioinject/markers.py +++ b/aioinject/markers.py @@ -1,6 +1,15 @@ import dataclasses +from typing import TYPE_CHECKING, Annotated @dataclasses.dataclass(slots=True) class Inject: pass + +if TYPE_CHECKING: + type Injected[T] = Annotated[T, Inject] +else: + class Injected[T]: + @classmethod + def __class_getitem__(cls, item): # noqa: ANN206, ANN001 + return Annotated[item, Inject] diff --git a/tests/test_inject.py b/tests/test_inject.py index 7941042..8189ff0 100644 --- a/tests/test_inject.py +++ b/tests/test_inject.py @@ -1,5 +1,6 @@ from typing import Annotated, NewType +from aioinject.markers import Injected import pytest from aioinject import Container, Inject, Object, Scoped, inject, providers @@ -56,6 +57,17 @@ def test_simple_inject(container: Container) -> None: session, *_ = _injectee() # type: ignore[call-arg] assert isinstance(session, _Session) +def test_simple_inject_with_injected(container: Container) -> None: + @inject + def injectee( + test: Injected[_Session], + test_no_cache: Injected[_Session], + ) -> tuple[_Session, _Session]: + return test, test_no_cache + + with container.sync_context(): + session, *_ = _injectee() # type: ignore[call-arg] + assert isinstance(session, _Session) async def test_simple_service(container: Container) -> None: with container.sync_context() as ctx: From 1cd1262589338b9c654c0501f35d3fd7eb6403b5 Mon Sep 17 00:00:00 2001 From: nir Date: Tue, 17 Sep 2024 09:04:32 +0300 Subject: [PATCH 2/5] export to init + docs --- aioinject/__init__.py | 3 ++- docs/code/integrations/aiogram_.py | 5 ++--- docs/code/integrations/fastapi_.py | 5 ++--- docs/code/integrations/litestar_.py | 5 ++--- docs/code/integrations/strawberry-graphql.py | 6 +++--- tests/test_inject.py | 2 +- tests/validation/test_dependency_validator.py | 2 +- 7 files changed, 13 insertions(+), 15 deletions(-) diff --git a/aioinject/__init__.py b/aioinject/__init__.py index 266bda1..80b8006 100644 --- a/aioinject/__init__.py +++ b/aioinject/__init__.py @@ -1,7 +1,7 @@ from aioinject.containers import Container from aioinject.context import InjectionContext, SyncInjectionContext from aioinject.decorators import inject -from aioinject.markers import Inject +from aioinject.markers import Inject, Injected from aioinject.providers import ( Object, Provider, @@ -22,6 +22,7 @@ "SyncInjectionContext", "Transient", "inject", + "Injected", ] __version__ = "0.34.0" diff --git a/docs/code/integrations/aiogram_.py b/docs/code/integrations/aiogram_.py index d5bbdef..2ff8939 100644 --- a/docs/code/integrations/aiogram_.py +++ b/docs/code/integrations/aiogram_.py @@ -1,12 +1,11 @@ import asyncio -from typing import Annotated from aiogram import Bot, Dispatcher, Router from aiogram.filters import Command from aiogram.types import Message from benchmark.container import create_container -from aioinject import Inject, Object +from aioinject import Injected, Object from aioinject.ext.aiogram import AioInjectMiddleware, inject @@ -24,7 +23,7 @@ async def main() -> None: @inject async def start( message: Message, - value: Annotated[int, Inject], + value: Injected[int], ) -> None: await message.reply(f"Injected value is {value}") diff --git a/docs/code/integrations/fastapi_.py b/docs/code/integrations/fastapi_.py index fc8d67c..281ba5d 100644 --- a/docs/code/integrations/fastapi_.py +++ b/docs/code/integrations/fastapi_.py @@ -1,12 +1,11 @@ import contextlib from collections.abc import AsyncIterator -from typing import Annotated import uvicorn from fastapi import FastAPI import aioinject -from aioinject import Inject +from aioinject import Injected from aioinject.ext.fastapi import AioInjectMiddleware, inject @@ -26,7 +25,7 @@ def create_app() -> FastAPI: @app.get("/") @inject - async def root(number: Annotated[int, Inject]) -> int: + async def root(number: Injected[int]) -> int: return number return app diff --git a/docs/code/integrations/litestar_.py b/docs/code/integrations/litestar_.py index f63b92a..f9fc651 100644 --- a/docs/code/integrations/litestar_.py +++ b/docs/code/integrations/litestar_.py @@ -1,10 +1,9 @@ -from typing import Annotated import uvicorn from litestar import Litestar, get import aioinject -from aioinject import Inject +from aioinject import Injected from aioinject.ext.litestar import AioInjectPlugin, inject @@ -15,7 +14,7 @@ @get("/") @inject async def function_route( - number: Annotated[int, Inject], + number: Injected[int], ) -> int: return number diff --git a/docs/code/integrations/strawberry-graphql.py b/docs/code/integrations/strawberry-graphql.py index 53fc3e8..f7a6c09 100644 --- a/docs/code/integrations/strawberry-graphql.py +++ b/docs/code/integrations/strawberry-graphql.py @@ -1,4 +1,4 @@ -from typing import Annotated, Any +from typing import Any import strawberry import uvicorn @@ -6,7 +6,7 @@ from strawberry.asgi import GraphQL import aioinject -from aioinject import Inject +from aioinject import Injected from aioinject.ext.strawberry import AioInjectExtension, inject # (1)! @@ -18,7 +18,7 @@ class Query: @strawberry.field @inject - async def number(self, number: Annotated[int, Inject]) -> int: + async def number(self, number: Injected[int]) -> int: return number diff --git a/tests/test_inject.py b/tests/test_inject.py index 8189ff0..d48f99c 100644 --- a/tests/test_inject.py +++ b/tests/test_inject.py @@ -1,11 +1,11 @@ from typing import Annotated, NewType -from aioinject.markers import Injected import pytest from aioinject import Container, Inject, Object, Scoped, inject, providers from aioinject.context import container_var from aioinject.decorators import InjectMethod +from aioinject.markers import Injected class _Session: diff --git a/tests/validation/test_dependency_validator.py b/tests/validation/test_dependency_validator.py index d0907a6..b97aab0 100644 --- a/tests/validation/test_dependency_validator.py +++ b/tests/validation/test_dependency_validator.py @@ -46,4 +46,4 @@ def test_err() -> None: assert len(exc_info.value.errors) == 1 err = exc_info.value.errors[0] assert isinstance(err, DependencyNotFoundError) - assert err.dependency == int + assert err.dependency is int From 1dc2730c757fac76985a90b0e54877d72382242d Mon Sep 17 00:00:00 2001 From: nir Date: Tue, 17 Sep 2024 09:08:48 +0300 Subject: [PATCH 3/5] lints --- aioinject/markers.py | 11 ++++++++--- docs/code/integrations/litestar_.py | 1 - tests/test_inject.py | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/aioinject/markers.py b/aioinject/markers.py index 4129a9b..b95f4f7 100644 --- a/aioinject/markers.py +++ b/aioinject/markers.py @@ -1,15 +1,20 @@ import dataclasses -from typing import TYPE_CHECKING, Annotated +from typing import TYPE_CHECKING, Annotated, Generic, TypeAlias, TypeVar @dataclasses.dataclass(slots=True) class Inject: pass + +T = TypeVar("T") + if TYPE_CHECKING: - type Injected[T] = Annotated[T, Inject] + Injected: TypeAlias = Annotated[T, Inject] + else: - class Injected[T]: + + class Injected(Generic[T]): @classmethod def __class_getitem__(cls, item): # noqa: ANN206, ANN001 return Annotated[item, Inject] diff --git a/docs/code/integrations/litestar_.py b/docs/code/integrations/litestar_.py index f9fc651..aed6e9c 100644 --- a/docs/code/integrations/litestar_.py +++ b/docs/code/integrations/litestar_.py @@ -1,4 +1,3 @@ - import uvicorn from litestar import Litestar, get diff --git a/tests/test_inject.py b/tests/test_inject.py index d48f99c..75539df 100644 --- a/tests/test_inject.py +++ b/tests/test_inject.py @@ -57,6 +57,7 @@ def test_simple_inject(container: Container) -> None: session, *_ = _injectee() # type: ignore[call-arg] assert isinstance(session, _Session) + def test_simple_inject_with_injected(container: Container) -> None: @inject def injectee( @@ -69,6 +70,7 @@ def injectee( session, *_ = _injectee() # type: ignore[call-arg] assert isinstance(session, _Session) + async def test_simple_service(container: Container) -> None: with container.sync_context() as ctx: session = ctx.resolve(_Session) From c571e4b6fc29c3519b5211d6d424f436df171c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:07:18 +0300 Subject: [PATCH 4/5] Update aioinject/markers.py --- aioinject/markers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aioinject/markers.py b/aioinject/markers.py index b95f4f7..1467df0 100644 --- a/aioinject/markers.py +++ b/aioinject/markers.py @@ -15,6 +15,5 @@ class Inject: else: class Injected(Generic[T]): - @classmethod def __class_getitem__(cls, item): # noqa: ANN206, ANN001 return Annotated[item, Inject] From 7a631d844fafe4b5a4be30d5446094f139bb006c Mon Sep 17 00:00:00 2001 From: Doctor Date: Tue, 17 Sep 2024 10:22:04 +0300 Subject: [PATCH 5/5] annotate `Injected.__class_getitem__` parameter and return with `object` --- aioinject/markers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aioinject/markers.py b/aioinject/markers.py index 1467df0..a3a41fe 100644 --- a/aioinject/markers.py +++ b/aioinject/markers.py @@ -15,5 +15,5 @@ class Inject: else: class Injected(Generic[T]): - def __class_getitem__(cls, item): # noqa: ANN206, ANN001 + def __class_getitem__(cls, item: object) -> object: return Annotated[item, Inject]