Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add iterable providers #22

Merged
merged 3 commits into from
Jan 9, 2025

Conversation

fadedDexofan
Copy link
Contributor

@fadedDexofan fadedDexofan commented Jan 4, 2025

Added support for Iterable providers. This makes it possible to register multiple implementations for a single type and query them all at once.

Behaves like .NET DI equivalent
https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#service-registration-methods

class ILogger(Protocol):
    def log(self, msg: str) -> None: ...

class ConsoleLogger(ILogger):
    ...

class FileLogger(ILogger):
    ...

class Service:
    def __init__(
        self,
        all_loggers: Sequence[ILogger],
        actual_logger: ILogger,
    ) -> None:
        self.all_loggers = all_loggers
        self.actual_logger = actual_logger

container = Container()
container.register(Scoped(ConsoleLogger, type_=ILogger))
container.register(Scoped(FileLogger, type_=ILogger))
container.register(Scoped(Service))

async with container.context() as ctx:
    service = await ctx.resolve(Service)
    assert isinstance(service.all_loggers[0], ConsoleLogger)
    assert isinstance(service.all_loggers[1], FileLogger)
    assert isinstance(service.actual_logger, FileLogger)

@fadedDexofan fadedDexofan marked this pull request as draft January 4, 2025 16:08
@fadedDexofan fadedDexofan changed the title WIP: feat: add iterable providers feat: add iterable providers Jan 4, 2025
@fadedDexofan fadedDexofan force-pushed the feat/iterable-providers branch from 990f5ab to b085919 Compare January 4, 2025 16:34
@fadedDexofan fadedDexofan marked this pull request as ready for review January 4, 2025 16:38
@fadedDexofan fadedDexofan force-pushed the feat/iterable-providers branch 5 times, most recently from 5e5e1a8 to 910cdad Compare January 5, 2025 13:53
@fadedDexofan fadedDexofan force-pushed the feat/iterable-providers branch from 910cdad to 934b2e8 Compare January 6, 2025 16:48
@fadedDexofan
Copy link
Contributor Author

fadedDexofan commented Jan 6, 2025

cc @nrbnlulu
With new generic types support:

class MiddlewareBase(abc.ABC, Generic[ReqT, ResT]):
    @abc.abstractmethod
    async def __call__(
        self,
        request: ReqT,
        handle: Callable[[ReqT], Awaitable[ResT]],
    ) -> ResT:
        pass

class FirstMiddleware(MiddlewareBase[ReqT, ResT]):
    async def __call__(
        self,
        request: ReqT,
        handle: Callable[[ReqT], Awaitable[ResT]],
    ) -> ResT:
        return await handle(request)

class SecondMiddleware(MiddlewareBase[ReqT, ResT]):
    async def __call__(
        self,
        request: ReqT,
        handle: Callable[[ReqT], Awaitable[ResT]],
    ) -> ResT:
        return await handle(request)

class ThirdMiddleware(MiddlewareBase[ReqT, ResT]):
    async def __call__(
        self,
        request: ReqT,
        handle: Callable[[ReqT], Awaitable[ResT]],
    ) -> ResT:
        return await handle(request)

container = Container()
container.register(
    Transient(FirstMiddleware, MiddlewareBase[str, str]),
    Transient(SecondMiddleware, MiddlewareBase[int, int]),
    Transient(ThirdMiddleware, MiddlewareBase[int, int]),
)

async with container.context() as ctx:
    instances = await ctx.resolve_iterable(MiddlewareBase[int, int])  # type: ignore[type-abstract]
    assert len(instances) == 2  # noqa: PLR2004
    assert isinstance(instances[0], SecondMiddleware)
    assert isinstance(instances[1], ThirdMiddleware)

@nrbnlulu
Copy link
Contributor

nrbnlulu commented Jan 6, 2025

does it means you can register the same provider twice?

@fadedDexofan
Copy link
Contributor Author

fadedDexofan commented Jan 6, 2025

does it means you can register the same provider twice?

Yes, but only with different implementations. Also there is validator for different provider lifetimes for same type. Just like in .NET DI

@ThirVondukr ThirVondukr merged commit a2b82d1 into ThirVondukr:main Jan 9, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants