Skip to content
1 change: 1 addition & 0 deletions docs/providers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ Providers package API docs - :py:mod:`dependency_injector.providers`
selector
dependency
overriding
provided_instance
custom
64 changes: 64 additions & 0 deletions docs/providers/provided_instance.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Injecting attributes, items, or call methods of the provided instance
---------------------------------------------------------------------

.. currentmodule:: dependency_injector.providers

In this section you will know how to inject provided instance attribute or item into the other
provider.

It also describes how to call a method of the provided instance and use the result of
this call as an injection value.

.. literalinclude:: ../../examples/providers/provided_instance.py
:language: python
:emphasize-lines: 26-32
:lines: 3-

To use the feature you should use the ``.provided`` attribute of the injected provider. This
attribute helps to specify what happens with the provided instance. You can retrieve an injection
value from:

- an attribute of the provided instance
- an item of the provided instance
- a call of the provided instance method

When you use the call of the provided instance method you can specify the injections into this
method like you do with any other provider.

You can do nested constructions:

.. literalinclude:: ../../examples/providers/provided_instance_complex.py
:language: python
:emphasize-lines: 24-30
:lines: 3-

Attribute ``.provided`` is available for the providers that return instances. Providers that
have ``.provided`` attribute:

- :py:class:`Callable` and its subclasses
- :py:class:`Factory` and its subclasses
- :py:class:`Singleton` and its subclasses
- :py:class:`Object`
- :py:class:`List`
- :py:class:`Selector`
- :py:class:`Dependency`

Special providers like :py:class:`Configuration` or :py:class:`Delegate` do not have the
``.provided`` attribute.

Provider subclasses
-------------------

When you create a new provider subclass and want to implement the ``.provided`` attribute, you
should use the :py:class:`ProvidedInstance` provider.

.. code-block:: python

@property
def provided(self):
"""Return :py:class:`ProvidedInstance` provider."""
return ProvidedInstance(self)

In all other cases you should not use :py:class:`ProvidedInstance`, :py:class:`AttributeGetter`,
:py:class:`ItemGetter`, or :py:class:`MethodCaller` providers directly. Use the ``.provided``
attribute of the injected provider instead.
38 changes: 38 additions & 0 deletions examples/providers/provided_instance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Example of the injecting of provided instance attributes and items."""

from dependency_injector import providers


class Service:
def __init__(self):
self.value = 'foo'
self.values = [self.value]

def get_value(self):
return self.value

def __getitem__(self, item):
return self.values[item]


class Client:
def __init__(self, value1, value2, value3, value4):
self.value1 = value1
self.value2 = value2
self.value3 = value3
self.value4 = value4


service = providers.Singleton(Service)

client_factory = providers.Factory(
Client,
value1=service.provided[0],
value2=service.provided.value,
value3=service.provided.values[0],
value4=service.provided.get_value.call(),
)

if __name__ == '__main__':
client = client_factory()
assert client.value1 == client.value2 == client.value3 == 'foo'
41 changes: 41 additions & 0 deletions examples/providers/provided_instance_complex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Complex example of the injecting of provided instance attributes and items."""

from dependency_injector import providers


class Service:

def __init__(self, value):
self.value = value

def get_value(self):
return self.value


service = providers.Singleton(Service, value=42)

dependency = providers.Object(
{
'foo': {
'bar': 10,
'baz': lambda arg: {'arg': arg}
},
},
)

demo_list = providers.List(
dependency.provided['foo']['bar'],
dependency.provided['foo']['baz'].call(22)['arg'],
dependency.provided['foo']['baz'].call(service)['arg'],
dependency.provided['foo']['baz'].call(service)['arg'].value,
dependency.provided['foo']['baz'].call(service)['arg'].get_value.call(),
)

if __name__ == '__main__':
assert demo_list() == [
10,
22,
service(),
42,
42,
]
Loading