Provider#
Provider is an object which members are used to construct dependencies. Provider
contains different factories and other entities and then is used to create a Container
. You can have multiple providers in one application and combine them in different ways to make it more modular.
To configure provider you can either inherit and use decorators on you methods or just create an instance and use its methods.
For example, imagine you have two classes: connection which is retrieved from external library and a gateway which requires such a connection.
class Connection:
pass
class Gateway:
def __init__(self, conn: Connection):
pass
You can configure Provider
with code like this:
from dishka import make_container, Provider, Scope
def get_connection() -> Iterable[Connection]:
conn = connect(uri)
yield conn
conn.close()
provider = Provider(scope=Scope.APP)
provider.provide(get_connection)
provider.provide(Gateway)
container = make_container(provider)
Or using inheritance:
from dishka import make_container, Provider, provide, Scope
class MyProvider(Provider):
@provide
def get_connection(self) -> Iterable[Connection]:
conn = connect(uri)
yield conn
conn.close()
gateway = provide(Gateway)
container = make_container(MyProvider(scope=Scope.APP))
Your class-based provider can have __init__
method and methods access self
as usual. It can be useful for passing configuration:
class MyProvider(Provider):
def __init__(self, uri: str, scope: Scope):
super().__init__(scope=scope) # do not forget `super`
self.uri = uri
@provide
def get_connection(self) -> Iterable[Connection]:
conn = connect(self.uri) # use passed configuration
yield conn
conn.close()
gateway = provide(Gateway)
provider = MyProvider(uri=os.getenv("DB_URI"), scope=Scope.APP)
container = make_container(provider)
Dependencies have scope and there are three places to set it (according to their priority):
When registering single factory passing to
provide
method
class MyProvider(Provider):
gateway = provide(Gateway, scope=Scope.APP)
When instantiating provider:
provider = Provider(scope=Scope.APP)
Inside class:
class MyProvider(Provider):
scope=Scope.APP
Though it is a normal object, not all attributes are analyzed by Container
, but only those which are marked with special functions: