Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/advanced/collect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ By default dishka relies on approach "last wins" which means that
if you have multiple factories providing the same type
only the last of them will be used.
The same rule still applies even if factories are marked with ``when=``,
but in that case only active factories are used (see :ref:`when`)
but in that case only active factories are used (see :ref:`when`).

In some cases it is useful to have all objects created instead of a single one.
In some cases, it is useful to create all objects rather than a single one.
To achieve that you should use ``collect`` in your provider.
By default, it provides a list of requested type.
You can use it as a dependency or request directly from a container.
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced/plotter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ Dependency graph plotter

You can visualise your dependency graph by calling one of these functions

* ``dishka.plotter.render_d2(container)`` will produce a string in d2 lang format. Follow `<https://d2lang.com>`_ for more details how to show it.
* ``dishka.plotter.render_d2(container)`` will produce a string in d2 lang format. Follow `<https://d2lang.com>`_ for more details on how to show it.
* ``dishka.plotter.render_mermaid(container)`` will produce a string containing ready to show HTML text containing graph in mermaid js format. Follow `<https://mermaid.js.org>`_ for more details on its customization.


The example rendered with mermaid:

.. image:: ./plotter.png
.. image:: ./plotter.png
2 changes: 1 addition & 1 deletion docs/advanced/testing/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Testing with dishka

Testing your code does not always require the whole application to be started. You can have unit tests for separate components and even integration tests which check only specific links. In many cases you do not need IoC-container: you create objects with a power of **Dependency Injection** and not framework.

For other cases which require calling functions located on application boundaries you need a container. These cases include testing your view functions with mocks of business logic and testing the application as a whole. Comparing to a production mode you will still have same implementations for some classes and others will be replaced with mocks. Luckily, in ``dishka`` your container is not an implicit global thing and can be replaced easily.
For other cases which require calling functions located on application boundaries you need a container. These cases include testing your view functions with mocks of business logic and testing the application as a whole. Compared to a production mode, you will still have the same implementations for some classes, and others will be replaced with mocks. Luckily, in ``dishka`` your container is not an implicit global thing and can be replaced easily.

There are many options to make providers with mock objects. If you are using ``pytest`` then you can

Expand Down
10 changes: 5 additions & 5 deletions docs/advanced/when.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This can be achieved with "activation" approach. Key concepts here:

* **Marker** - special object to distinguish which implementations should be used.
* **Activator** or **activation function** - special function registered in provider and taking decision if marker is active or not.
* **activation condition** - expression with marker objects set in dependency source dynamically associated with activators to select between multiple implementations or enable decorators
* **Activation condition** - expression with marker objects set in dependency source dynamically associated with activators to select between multiple implementations or enable decorators

Activators can be called preliminary or multiple times, so avoid acquiring resources or doing heavy calculations, if necessary, move such things into factories or context data.

Expand Down Expand Up @@ -51,7 +51,7 @@ The base implementation will be used in all other cases as it has no condition s
The overall rule is "last wins" like it worked with overriding.

Second step is to provide logic of marker activation. You write a function returning ``bool`` and register it in provider using ``@activate`` decorator.
It can be the same or another provider while you pass when creating a container.
It can be the same or another provider that you specify when creating a container.

.. code-block:: python

Expand Down Expand Up @@ -189,16 +189,16 @@ For example:
In this case,

* ``memcached_impl`` is not used because no factory for ``MemcachedConfig`` is provided
* ``redis_impl`` is not used while it is registered as ``from_context`` but no real value is provided.
* ``base_impl`` is used as a default one, because none of later is active
* ``redis_impl`` is not used while it is registered as ``from_context`` but no real value is provided
* ``base_impl`` is used as the default because none of the former are active


Preliminary (static) evaluation and graph validation
------------------------------------------------------------

In certain cases activator can be called during graph building step, this allows avoid unnecessary calls in runtime and ignore errors on factories which are never called.

Static evaluation is enabled only if activator a sync non-generator function with dependencies retrieved from root context or without dependencies at all.
Static evaluation is enabled only if the activator is a sync non-generator function with dependencies retrieved from the root context or without dependencies at all.
For example, in the following code ``redis_impl`` is never called because ``RedisConfig`` is not passed, so it won't be validated at all.


Expand Down
6 changes: 3 additions & 3 deletions docs/alternatives.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ For this analysis we imagined several cases. Not all applications require all of
* For some apps (like AWS Lambdas) you do not need to create all singletons at startup as it serves only few requests.
* For some apps (like desktop) you will use threads, for others you will use asyncio.
* Some objects such as database connections may require async initialization and finalization.
* Some dependencies must be shared between other objects. For example: databases connection can be used by multiple data-mappers and unit-of-work within single processing request.
* Some dependencies must be shared between other objects. For example: database connection can be used by multiple data-mappers and unit-of-work within single processing request.

Actually, everything can be done in your code: DI-framework is not a required thing for an application. But isn't it more pleasant when everything is just working out of the box?

There might be errors in this comparison, some features are not well described while still exist in selected libraries. Some features can be implemented manually, but this topic is not about your code - it is about existing libraries.
There might be errors in this comparison, some features are not well described while still existing in selected libraries. Some features can be implemented manually, but this topic is not about your code - it is about existing libraries.

.. note:: The data is up to date as of **March 8, 2024**

Expand Down Expand Up @@ -147,7 +147,7 @@ Why not di?
``di`` is a young promising project which has own advantages comparing to ``dishka``, but looks more complicated.

* You need to pass 3 things to get a dependency: solved dependency, executor and state. In ``dishka`` you need only container (and already known dependency type).
* Scopes in di work differently, they are not thread-safe.
* Scopes in ``di`` work differently, they are not thread-safe.
* It supports binding by subclasses or by name, but retrieving dependencies is more complicated.
* It does not support generic dependencies.
* It is quite fast in creating dependencies, but very slow initialization. For big graphs it can take years to start application. E.g.: if you have graph of 60 classes nested with with depth of 6, then for ``di`` it take **50 sec** to initialize container and only **5ms** for ``dishka``.
Expand Down
2 changes: 1 addition & 1 deletion docs/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ NoActiveFactoryError: Cannot select active factory for ...
鈺扳攢脳 MyProvider.cache: Marker("a")


There were multiple variant of factory provided wit various conditions, but none of them is considered active.
There were multiple variant of factory provided with various conditions, but none of them is considered active.
Check the logic of marker activation.


Expand Down
8 changes: 4 additions & 4 deletions docs/requirements/technical.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Technical requirements

1. Dependencies which require some cleanup must be cleaned up on the scope exit.
2. Dependencies which do not require cleanup should somehow be supported.
3. Dependencies are cleaned in reverse order as they created.
3. Dependencies are cleaned in reverse order as they were created.
4. Exceptions should not prevent cleaning of then rest of dependencies.

5. Context data
Expand All @@ -48,7 +48,7 @@ Technical requirements
6. Modularity
================

1. There can be multiple containers within same code base for different purposes.
1. There can be multiple containers within the same codebase for different purposes.
2. There must be a way to assemble a container from some reusable parts.
3. Assembling of container should be done in runtime in local scope.
4. There should be a way to isolate different parts of container so they do not affect each other.
Expand All @@ -60,8 +60,8 @@ Technical requirements
1. There should be a way to create dependency based on its ``__init__``.
2. When creating a dependency there should be a way to decide which subtype is used and request only its dependencies.
3. There should be a way to reuse same object for multiple requested types.
4. There should be a way to decorate dependency just adding new providers.
5. There should be a way to enter multiple scopes with single call. The last of those scopes is used when dependencies are requested.
4. There should be a way to decorate a dependency by just adding new providers.
5. There should be a way to enter multiple scopes in a single call. The last of those scopes is used when dependencies are requested.
6. Container user errors must be clear and contain information necessary for resolution.
7. Dependency graph should be prematurely analyzed to detect most obvious errors.

Expand Down
Loading