Skip to content

Commit

Permalink
Merge branch 'release/4.38.0' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
rmk135 committed Jan 31, 2022
2 parents 541131e + ad0d430 commit c26b260
Show file tree
Hide file tree
Showing 40 changed files with 18,105 additions and 14,970 deletions.
6 changes: 3 additions & 3 deletions README.rst
Expand Up @@ -90,7 +90,7 @@ Key features of the ``Dependency Injector``:
api_client = providers.Singleton(
ApiClient,
api_key=config.api_key,
timeout=config.timeout.as_int(),
timeout=config.timeout,
)
service = providers.Factory(
Expand All @@ -106,8 +106,8 @@ Key features of the ``Dependency Injector``:
if __name__ == "__main__":
container = Container()
container.config.api_key.from_env("API_KEY")
container.config.timeout.from_env("TIMEOUT")
container.config.api_key.from_env("API_KEY", required=True)
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
container.wire(modules=[__name__])
main() # <-- dependency is injected automatically
Expand Down
2 changes: 1 addition & 1 deletion docs/_static/logo.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/index.rst
Expand Up @@ -96,7 +96,7 @@ Key features of the ``Dependency Injector``:
api_client = providers.Singleton(
ApiClient,
api_key=config.api_key,
timeout=config.timeout.as_int(),
timeout=config.timeout,
)
service = providers.Factory(
Expand All @@ -112,8 +112,8 @@ Key features of the ``Dependency Injector``:
if __name__ == "__main__":
container = Container()
container.config.api_key.from_env("API_KEY")
container.config.timeout.from_env("TIMEOUT")
container.config.api_key.from_env("API_KEY", required=True)
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
container.wire(modules=[__name__])
main() # <-- dependency is injected automatically
Expand Down
8 changes: 4 additions & 4 deletions docs/introduction/di_in_python.rst
Expand Up @@ -150,7 +150,7 @@ What does the Dependency Injector do?
-------------------------------------

With the dependency injection pattern objects loose the responsibility of assembling
the dependencies. The ``Dependency Injector`` absorbs that responsibilities.
the dependencies. The ``Dependency Injector`` absorbs that responsibility.

``Dependency Injector`` helps to assemble and inject the dependencies.

Expand All @@ -172,7 +172,7 @@ the dependency.
api_client = providers.Singleton(
ApiClient,
api_key=config.api_key,
timeout=config.timeout.as_int(),
timeout=config.timeout,
)
service = providers.Factory(
Expand All @@ -188,8 +188,8 @@ the dependency.
if __name__ == "__main__":
container = Container()
container.config.api_key.from_env("API_KEY")
container.config.timeout.from_env("TIMEOUT")
container.config.api_key.from_env("API_KEY", required=True)
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
container.wire(modules=[__name__])
main() # <-- dependency is injected automatically
Expand Down
25 changes: 25 additions & 0 deletions docs/main/changelog.rst
Expand Up @@ -7,6 +7,31 @@ that were made in every particular version.
From version 0.7.6 *Dependency Injector* framework strictly
follows `Semantic versioning`_

4.38.0
------
- Add new provider ``Aggregate``. It is a generalized version of ``FactoryAggregate`` that
can contain providers of any type, not only ``Factory``. See issue
`#530 <https://github.com/ets-labs/python-dependency-injector/issues/530>`_. Thanks to
`@zerlok (Danil Troshnev) <https://github.com/zerlok>`_ for suggesting the feature.
- Add argument ``as_`` to the ``config.from_env()`` method for the explicit type casting
of an environment variable value, e.g.: ``config.timeout.from_env("TIMEOUT", as_=int)``.
See issue `#533 <https://github.com/ets-labs/python-dependency-injector/issues/533>`_. Thanks to
`@gtors (Andrey Torsunov) <https://github.com/gtors>`_ for suggesting the feature.
- Add ``.providers`` attribute to the ``FactoryAggregate`` provider. It is an alias for
``FactoryAggregate.factories`` attribute.
- Add ``.set_providers()`` method to the ``FactoryAggregate`` provider. It is an alias for
``FactoryAggregate.set_factories()`` method.
- Add string imports for ``Factory``, ``Singleton``, ``Callable``, ``Resource``, and ``Coroutine``
providers, e.g. ``Factory("module.Class")``.
See issue `#531 <https://github.com/ets-labs/python-dependency-injector/issues/531>`_.
Thanks to `@al-stefanitsky-mozdor <https://github.com/al-stefanitsky-mozdor>`_ for suggesting the feature.
- Fix ``Dependency`` provider to don't raise "Dependency is not defined" error when the ``default``
is a falsy value of proper type.
See issue `#550 <https://github.com/ets-labs/python-dependency-injector/issues/550>`_. Thanks to
`@approxit <https://github.com/approxit>`_ for reporting the issue.
- Refactor ``FactoryAggregate`` provider internals.
- Update logo on Github and in docs to support dark themes and remove some imperfections.

4.37.0
------
- Add support of Python 3.10.
Expand Down
72 changes: 72 additions & 0 deletions docs/providers/aggregate.rst
@@ -0,0 +1,72 @@
.. _aggregate-provider:

Aggregate provider
==================

.. meta::
:keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection,
Aggregate,Polymorphism,Environment Variable,Flexibility
:description: Aggregate provider aggregates other providers.
This page demonstrates how to implement the polymorphism and increase the
flexibility of your application using the Aggregate provider.

:py:class:`Aggregate` provider aggregates a group of other providers.

.. currentmodule:: dependency_injector.providers

.. literalinclude:: ../../examples/providers/aggregate.py
:language: python
:lines: 3-
:emphasize-lines: 24-27

Each provider in the ``Aggregate`` is associated with a key. You can call aggregated providers by providing
their key as a first argument. All positional and keyword arguments following the key will be forwarded to
the called provider:

.. code-block:: python
yaml_reader = container.config_readers("yaml", "./config.yml", foo=...)
You can also retrieve an aggregated provider by providing its key as an attribute name:

.. code-block:: python
yaml_reader = container.config_readers.yaml("./config.yml", foo=...)
To retrieve a dictionary of aggregated providers, use ``.providers`` attribute:

.. code-block:: python
container.config_readers.providers == {
"yaml": <YAML provider>,
"json": <JSON provider>,
}
.. note::
You can not override the ``Aggregate`` provider.

.. note::
When you inject the ``Aggregate`` provider, it is passed "as is".

To use non-string keys or string keys with ``.`` and ``-``, provide a dictionary as a positional argument:

.. code-block:: python
aggregate = providers.Aggregate({
SomeClass: providers.Factory(...),
"key.with.periods": providers.Factory(...),
"key-with-dashes": providers.Factory(...),
})
.. seealso::
:ref:`selector-provider` to make injections based on a configuration value, environment variable, or a result of a callable.

``Aggregate`` provider is different from the :ref:`selector-provider`. ``Aggregate`` provider doesn't select which provider
to inject and doesn't have a selector. It is a group of providers and is always injected "as is". The rest of the interface
of both providers is similar.

.. note::
``Aggregate`` provider is a successor of :ref:`factory-aggregate-provider` provider. ``Aggregate`` provider doesn't have
a restriction on the provider type, while ``FactoryAggregate`` aggregates only ``Factory`` providers.

.. disqus::
18 changes: 18 additions & 0 deletions docs/providers/configuration.rst
Expand Up @@ -205,6 +205,24 @@ Loading from an environment variable
:lines: 3-
:emphasize-lines: 18-20

You can use ``as_`` argument for the type casting of an environment variable value:

.. code-block:: python
:emphasize-lines: 2,6,10
# API_KEY=secret
container.config.api_key.from_env("API_KEY", as_=str, required=True)
assert container.config.api_key() == "secret"
# SAMPLING_RATIO=0.5
container.config.sampling.from_env("SAMPLING_RATIO", as_=float, required=True)
assert container.config.sampling() == 0.5
# TIMEOUT undefined, default is used
container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
assert container.config.timeout() == 5
Loading a value
---------------

Expand Down

0 comments on commit c26b260

Please sign in to comment.