Creating a custom provider

You can create a custom provider.

To create a custom provider you need to follow these rules:

  1. New provider class should inherit Provider.

  2. You need to implement the Provider._provide() method.

  3. You need to implement the Provider.__deepcopy__() method. It should return an equivalent copy of a provider. All providers must be copied with a deepcopy() function from the providers module. After the a new provider object is created use Provider._copy_overriding() method to copy all overriding providers. See the example below.

  4. If the new provider has a __init__() method, it should call the parent Provider.__init__().

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

    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

  1. Prefer delegation over inheritance. If you choose between inheriting a Factory or inheriting a Provider and use Factory internally - the last is better.

  2. When create a new provider follow the Factory-like injections style. Consistency matters.

  3. 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.