Generic types¶
You can use dishka with TypeVars and Generic-classes.
Note
Though generics are supported, there are some limitations:
You cannot use
TypeVarbounded to aGenerictype.Generic-decorators are only applied to concrete factories or factories with more narrowTypeVars.
Creating objects with @provide¶
You can create generic factories, use type[T] to access resolved value of TypeVar. TypeVar can have bound or constraints, which are checked.
For example, here we have a factory providing instances of generic class A. Note that A[int] and A[bool] are different types and cached separately.
from typing import Generic, TypeVar
from dishka import make_container, Provider, provide, Scope
T = TypeVar("T", bound=int)
class A(Generic[T]):
pass
class MyProvider(Provider):
@provide(scope=Scope.APP)
def make_a(self, t: type[T]) -> A[T]:
print("Requested type", t)
return A()
container = make_container(MyProvider())
container.get(A[int]) # printed: Requested type <class 'int'>
container.get(A[bool]) # printed: Requested type <class 'bool'>
container.get(A[str]) # NoFactoryError
Decorating objects with @decorate¶
You can also make Generic decorator. Here it is used to decorate any type.
from collections.abc import Iterator
from typing import TypeVar
from dishka import make_container, Provider, provide, Scope, decorate
T = TypeVar("T")
class MyProvider(Provider):
scope = Scope.APP
@provide
def make_int(self) -> int:
return 1
@provide
def make_str(self) -> str:
return "hello"
@decorate
def log(self, a: T, t: type[T]) -> Iterator[T]:
print("Requested", t, "with value", a)
yield a
print("Requested release", a)
container = make_container(MyProvider())
container.get(int) # Requested <class 'int'> with value 1
container.get(str) # Requested <class 'str'> with value hello
container.close()
# Requested release object hello
# Requested release object 1