diff --git a/pyproject.toml b/pyproject.toml index fe89efaa..fc8b36c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,8 @@ dynamic = ["version"] dependencies = [ # typing.Annotated since v3.9 # typing.Self and typing.assert_never since v3.11 - "typing-extensions; python_version<'3.11'", + # typing.TypeVar default since v3.13 + "typing-extensions; python_version<'3.13'", ] [project.optional-dependencies] diff --git a/src/dependency_injector/providers.pyi b/src/dependency_injector/providers.pyi index 8f9b525a..a4443107 100644 --- a/src/dependency_injector/providers.pyi +++ b/src/dependency_injector/providers.pyi @@ -4,7 +4,6 @@ from contextlib import AbstractContextManager, AbstractAsyncContextManager from pathlib import Path from typing import ( Awaitable, - TypeVar, Generic, Type, Callable as _Callable, @@ -22,6 +21,8 @@ from typing import ( overload, ) +from typing_extensions import Self as _Self, TypeVar + try: import yaml except ImportError: @@ -38,6 +39,7 @@ Injection = Any ProviderParent = Union["Provider", Any] T = TypeVar("T") TT = TypeVar("TT") +T_Any = TypeVar("T_Any", default=Any) P = TypeVar("P", bound="Provider") BS = TypeVar("BS", bound="BaseSingleton") @@ -542,17 +544,17 @@ class Container(Provider[T]): def parent_name(self) -> Optional[str]: ... def assign_parent(self, parent: ProviderParent) -> None: ... -class Selector(Provider[Any]): +class Selector(Provider[T_Any]): def __init__( self, selector: Optional[_Callable[..., Any]] = None, **providers: Provider ): ... - def __getattr__(self, name: str) -> Provider: ... + def __getattr__(self, name: str) -> Provider[T_Any]: ... @property def selector(self) -> Optional[_Callable[..., Any]]: ... - def set_selector(self, selector: Optional[_Callable[..., Any]]) -> Selector: ... + def set_selector(self, selector: Optional[_Callable[..., Any]]) -> _Self: ... @property - def providers(self) -> _Dict[str, Provider]: ... - def set_providers(self, **providers: Provider) -> Selector: ... + def providers(self) -> _Dict[str, Provider[T_Any]]: ... + def set_providers(self, **providers: Provider) -> _Self: ... class ProvidedInstanceFluentInterface: def __getattr__(self, item: Any) -> AttributeGetter: ... diff --git a/tests/typing/selector.py b/tests/typing/selector.py index 5d89ec66..6297baf1 100644 --- a/tests/typing/selector.py +++ b/tests/typing/selector.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Callable, Optional, Dict from dependency_injector import providers @@ -40,3 +40,36 @@ async def _async4() -> None: var1: Any = await provider4() var2: Any = await provider4.async_() + + +# Test 5: to check selector getter and setter +provider5 = providers.Selector( + lambda: "a", + a=providers.Factory(object), + b=providers.Factory(object), +) +selector5: Optional[Callable[..., Any]] = provider5.selector +provider5_after_set_selector: providers.Selector[Any] = provider5.set_selector(lambda: "a") + +# Test 6: to check providers getter and setter +provider6 = providers.Selector( + lambda: "a", + a=providers.Factory(object), + b=providers.Factory(object), +) +providers6: Dict[str, providers.Provider[Any]] = provider6.providers +provider6_after_set_providers: providers.Selector[Any] = provider6.set_providers(c=providers.Factory(object)) + + +# Test 7: to check explicit typing: return type, getattr, getter/setter of providers and selectors +provider7 = providers.Selector[bool](lambda: "a", a=providers.Factory(bool), b=providers.Factory(int)) +var7: bool = provider7() +attr7: providers.Provider[bool] = provider7.a + +selector7: Optional[Callable[..., Any]] = provider7.selector +provider7_after_set_selector: providers.Selector[bool] = provider7.set_selector(lambda: "a") + +providers7: Dict[str, providers.Provider[bool]] = provider7.providers +provider7_after_set_providers: providers.Selector[bool] = provider7.set_providers( + c=providers.Factory(str) +) # We don't require Provider of subclass of bool yet since Provider is invariant