Creating a custom provider¶
You can create a custom provider.
To create a custom provider you need to follow these rules:
New provider class should inherit
Provider
.You need to implement the
Provider._provide()
method.You need to implement the
Provider.__deepcopy__()
method. It should return an equivalent copy of a provider. All providers must be copied with thedeepcopy()
function from theproviders
module. It’s essential to passmemo
intodeepcopy
in order to keep the preconfiguredargs
andkwargs
of stored providers. After the a new provider object is created, useProvider._copy_overriding()
method to copy all overriding providers. See the example below.If new provider has a
__init__()
method, it should call the parentProvider.__init__()
.If new provider stores any other providers, these providers should be listed in
.related
property. Property.related
also should yield providers from parent.related
property.
from dependency_injector import containers, providers
class CustomFactory(providers.Provider):
__slots__ = ("_factory",)
def __init__(self, provides, *args, **kwargs):
self._factory = providers.Factory(provides, *args, **kwargs)
super().__init__()
def __deepcopy__(self, memo):
copied = memo.get(id(self))
if copied is not None:
return copied
copied = self.__class__(
self._factory.provides,
*providers.deepcopy(self._factory.args, memo),
**providers.deepcopy(self._factory.kwargs, memo),
)
self._copy_overridings(copied, memo)
return copied
@property
def related(self):
"""Return related providers generator."""
yield from [self._factory]
yield from super().related
def _provide(self, args, kwargs):
return self._factory(*args, **kwargs)
class Container(containers.DeclarativeContainer):
factory = CustomFactory(object)
if __name__ == "__main__":
container = Container()
object1 = container.factory()
assert isinstance(object1, object)
object2 = container.factory()
assert isinstance(object1, object)
assert object1 is not object2
Note
Prefer delegation over inheritance. If you choose between inheriting a
Factory
or inheriting aProvider
and useFactory
internally - the last is better.When creating a new provider follow the
Factory
-like injections style. Consistency matters.Use the
__slots__
attribute to make sure nothing could be attached to your provider. You will also save some memory.
Note
If you don’t find needed provider in the providers
module and experience troubles creating
one by your own - open a
Github Issue.
I’ll help you to resolve the issue if that’s possible. If the new provider can be useful for
others I’ll include it into the providers
module.