Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.3 #210

Merged
merged 109 commits into from
Aug 15, 2024
Merged

v1.3 #210

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
3c88e33
Added `CONTAINER_NAME` to `__all__`
ilya-nikolaev May 22, 2024
d624158
Merge pull request #158 from ilya-nikolaev/develop
Tishka17 May 23, 2024
fa74eb5
Added aiogram_dialog inject
IvanKirpichnikov May 24, 2024
4012740
Added new integration in docs
IvanKirpichnikov May 24, 2024
b41036a
Update 'tox.ini'
IvanKirpichnikov May 24, 2024
22db29d
fixed old annotations in tests
IvanKirpichnikov May 24, 2024
2b840d0
freeze typing-extensions version for non latest faststream
Tishka17 May 25, 2024
47af5a7
Merge pull request #162 from reagento/fix/faststream-tests
Tishka17 May 25, 2024
a56e1b8
Merge branch 'reagento:develop' into aiogram-dialog-integrantion
IvanKirpichnikov May 25, 2024
2b3ea5a
Merge branch 'reagento:develop' into update-tests
IvanKirpichnikov May 25, 2024
2d40d0e
Add dunder method 'add'
IvanKirpichnikov May 26, 2024
3194b0b
Add test
IvanKirpichnikov May 26, 2024
b40f7ba
added new information in documentation
IvanKirpichnikov May 26, 2024
207815b
Added new information in documentation
IvanKirpichnikov May 26, 2024
2dd67c3
Merge branch 'develop' of https://github.com/IvanKirpichnikov/dishka …
IvanKirpichnikov May 26, 2024
30f0a86
Added test for 'Dialog.on_process_result'
IvanKirpichnikov May 26, 2024
0b35ff5
fix ruff
IvanKirpichnikov May 26, 2024
0f16514
Merge pull request #160 from IvanKirpichnikov/aiogram-dialog-integran…
Tishka17 May 29, 2024
fc893b1
moved 'join provides' docs
IvanKirpichnikov Jun 2, 2024
730e9ad
Merge pull request #163 from IvanKirpichnikov/join_provides
Tishka17 Jun 2, 2024
2a21eea
update aiogram example
Olegt0rr Jun 6, 2024
53b67d4
Fixed small typo inside integrations docs
r-chulkevich Jun 6, 2024
e66aa32
Merge pull request #167 from r-chulkevich/patch-1
Tishka17 Jun 8, 2024
33af680
Merge pull request #166 from Olegt0rr/update-example
Tishka17 Jun 8, 2024
5ab72d4
Skip not DI-related annotations
Olegt0rr Jun 9, 2024
4c012bc
Use main annotation
Olegt0rr Jun 9, 2024
1aca17c
Test resolved type too
Olegt0rr Jun 9, 2024
b2710bd
Rm duplicated test
Olegt0rr Jun 9, 2024
0faac46
Merge pull request #169 from Olegt0rr/fix/skip-not-related-annotations
Tishka17 Jun 10, 2024
e5a2ed1
add imports from dishka
Jun 17, 2024
c804abb
Merge pull request #170 from ApostolFet/edit_example_context
Tishka17 Jun 17, 2024
170dd27
grpcio integration support
Jun 18, 2024
7a32676
linter errors fix
Jun 18, 2024
296dfe5
the argument provides has become free
IvanKirpichnikov Jun 22, 2024
c4814ed
Merge pull request #175 from IvanKirpichnikov/join_provides
Tishka17 Jun 22, 2024
57790f3
typo "ar" in README
evgene-sh Jul 2, 2024
50841df
Merge pull request #176 from evgene-sh/patch-1
Tishka17 Jul 4, 2024
ab2c732
Fixed typehint for sanic integration
ilya-nikolaev Jul 17, 2024
b05cf15
Merge pull request #180 from ilya-nikolaev/develop
Tishka17 Jul 17, 2024
b4619e1
fix typos
newonlynew Jul 20, 2024
935af77
Merge pull request #183 from newonlynew/fix/typos
Tishka17 Jul 21, 2024
01f406c
Merge pull request #172 from Dark04072006/grpcio-integration
Tishka17 Jul 26, 2024
410c9e4
Merge pull request #161 from IvanKirpichnikov/update-tests
Tishka17 Jul 26, 2024
16b1487
Pass typehint to NoContextValueError
Tishka17 Jul 26, 2024
e676d5a
Merge pull request #188 from reagento/fix/no_context_hint
Tishka17 Jul 26, 2024
94a52ee
Check if provides same is dep for provider
Tishka17 Jul 26, 2024
808ce39
Merge pull request #189 from reagento/fix/check_recursive_provder
Tishka17 Jul 26, 2024
bd06466
ruff 0.5
Tishka17 Jul 27, 2024
0198b0b
Merge pull request #190 from reagento/feature/bump_ruff
Tishka17 Jul 27, 2024
93d19c3
Add click integration
vashcheulov Jul 31, 2024
acf44ca
Use only app scope for click
vashcheulov Aug 2, 2024
c6a90db
Add 'WithParents'
IvanKirpichnikov Aug 2, 2024
ca32f22
Add 'WithParents' class
IvanKirpichnikov Aug 2, 2024
23840a6
Add support 'TypeVarTuple' for 'WithParents'
IvanKirpichnikov Aug 3, 2024
05d05dd
one check for ignoring type has been removed
IvanKirpichnikov Aug 3, 2024
b8feaf8
Add 'WithParents' in docs'
IvanKirpichnikov Aug 3, 2024
fd8d53d
parents search changed
IvanKirpichnikov Aug 3, 2024
3579857
Add docs, tests, support 'TypeVarTuple'
IvanKirpichnikov Aug 3, 2024
86346e1
fix ruff
IvanKirpichnikov Aug 3, 2024
55723e9
Code review bugs fixed
IvanKirpichnikov Aug 3, 2024
e78ccdf
support python 3.10
IvanKirpichnikov Aug 3, 2024
6e742f5
support python 3.10
IvanKirpichnikov Aug 3, 2024
a84928b
replacing parentheses
IvanKirpichnikov Aug 3, 2024
88d39cc
explicit call to __class_getitem__
IvanKirpichnikov Aug 3, 2024
b336850
Merge branch 'reagento:develop' into with-parents
IvanKirpichnikov Aug 3, 2024
16160ff
edited generic class creation
IvanKirpichnikov Aug 4, 2024
cf90a98
grpcio integration streams support
Dark04072006 Aug 4, 2024
9742396
edit test for WithParents
IvanKirpichnikov Aug 4, 2024
c946937
fix ruff
IvanKirpichnikov Aug 4, 2024
2f08723
edit docs for WithParents
IvanKirpichnikov Aug 4, 2024
f011fcc
edit WithParents test
IvanKirpichnikov Aug 4, 2024
9188cd6
'is_ignore_type' -> 'is_ignored_type'
IvanKirpichnikov Aug 4, 2024
0b40307
Merge pull request #196 from Dark04072006/grpcio-streams-support
Tishka17 Aug 4, 2024
b8bf92f
Merge branch 'develop' into add-click-integration
Tishka17 Aug 4, 2024
de4a0f4
Fix pytest.raises
Tishka17 Aug 4, 2024
19bef4c
Merge pull request #194 from vashcheulov/add-click-integration
Tishka17 Aug 4, 2024
8868894
Merge pull request #195 from IvanKirpichnikov/with-parents
Tishka17 Aug 4, 2024
9b04889
Validate decorator really decorates
Tishka17 Aug 4, 2024
85e4e4a
Merge pull request #197 from reagento/feature/validate_decorator_deps
Tishka17 Aug 4, 2024
0dac9cc
add tests and fix check object is GenericAlias
IvanKirpichnikov Aug 7, 2024
6077e92
Merge pull request #199 from IvanKirpichnikov/with-parents
Tishka17 Aug 7, 2024
f0f467d
use tox-uv, fix skipping tests
Tishka17 Aug 7, 2024
dd09825
Merge pull request #200 from reagento/feature/tox-uv
Tishka17 Aug 7, 2024
8f34547
reworked WithParents
IvanKirpichnikov Aug 7, 2024
d1fe88d
Merge branch 'reagento:develop' into with-parents
IvanKirpichnikov Aug 7, 2024
0c62051
Merge pull request #201 from IvanKirpichnikov/with-parents
Tishka17 Aug 8, 2024
1befabf
fix mypy --strict
IvanKirpichnikov Aug 8, 2024
4439c55
fix code review
IvanKirpichnikov Aug 9, 2024
0ffea8f
fix ruff
IvanKirpichnikov Aug 9, 2024
b5d348d
fix mypy ci
IvanKirpichnikov Aug 9, 2024
1bd7142
fix mypy ci
IvanKirpichnikov Aug 9, 2024
1697ae5
fix ci
IvanKirpichnikov Aug 9, 2024
aa9c282
search for tests
Tishka17 Aug 9, 2024
cf238a5
Merge pull request #203 from reagento/fix/more_tests
Tishka17 Aug 9, 2024
0200b16
--amend
IvanKirpichnikov Aug 10, 2024
af73020
fix ci and integration
IvanKirpichnikov Aug 10, 2024
aeb32d0
fix code review
IvanKirpichnikov Aug 10, 2024
33f6f04
removed scope check for context vars
IvanKirpichnikov Aug 10, 2024
0d33044
add ClassVar typehint
IvanKirpichnikov Aug 10, 2024
3c5b459
Merge pull request #202 from IvanKirpichnikov/support-mypy
Tishka17 Aug 10, 2024
5d5ced1
replace newtype with temporary object for decorators
Tishka17 Aug 10, 2024
2a4d6fa
Merge pull request #205 from reagento/fix/decorate_hints
Tishka17 Aug 10, 2024
2dac79c
Fix a type in `di_intro.rst`
wojcikstefan Aug 11, 2024
80fc556
Merge pull request #206 from wojcikstefan/patch-1
Tishka17 Aug 11, 2024
239d224
grpc.aio support with context vars, cleanup tests, support generators…
Tishka17 Aug 14, 2024
337f45c
update doc
Tishka17 Aug 14, 2024
8d85824
3.13.0-rc.1 in ci
Tishka17 Aug 14, 2024
cf770ff
Merge pull request #209 from reagento/feature/3.13
Tishka17 Aug 14, 2024
17f8636
Merge pull request #208 from reagento/feature/grpc_aio
Tishka17 Aug 15, 2024
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
3 changes: 2 additions & 1 deletion .github/workflows/frameworks-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
- "3.13.0-rc.1"

steps:
- uses: actions/checkout@v4
Expand All @@ -33,5 +34,5 @@ jobs:

- name: Run tests
run: |
tox -e aiohttp-latest,fastapi-latest,aiogram-latest,telebot-latest,flask-latest,litestar-latest,starlette-latest,faststream-latest,arq-latest,taskiq-latest,sanic-latest
find requirements -name "*-latest.txt" -exec basename {} .txt \; | xargs -d , tox -e

6 changes: 5 additions & 1 deletion .github/workflows/setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ jobs:
- name: Run ruff
run: |
ruff check .


- name: Run mypy
run: |
mypy src

- name: Run tests
run: |
tox
65 changes: 65 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[mypy]
exclude = ^src/dishka/(_adaptix|integrations)/

[mypy-dishka._adaptix.*]
disable_error_code = attr-defined

[mypy-dishka._adaptix.type_tools.normalize_type]
disable_error_code = arg-type

[mypy-pydantic.*]
ignore_missing_imports = True

[mypy-aiogram.*]
ignore_missing_imports = True

[mypy-aiogram_dialog.*]
ignore_missing_imports = True

[mypy-aiohttp.*]
ignore_missing_imports = True

[mypy-arq.*]
ignore_missing_imports = True

[mypy-asgi.*]
ignore_missing_imports = True

[mypy-click.*]
ignore_missing_imports = True

[mypy-fastapi.*]
ignore_missing_imports = True

[mypy-faststream.*]
ignore_missing_imports = True

[mypy-flask.*]
ignore_missing_imports = True

[mypy-grpc.*]
ignore_missing_imports = True

[mypy-grpcio.*]
ignore_missing_imports = True

[mypy-google.*]
ignore_missing_imports = True

[mypy-litestar.*]
ignore_missing_imports = True

[mypy-sanic.*]
ignore_missing_imports = True

[mypy-sanic_routing.*]
ignore_missing_imports = True

[mypy-starlette.*]
ignore_missing_imports = True

[mypy-taskiq.*]
ignore_missing_imports = True

[mypy-telebot.*]
ignore_missing_imports = True
2 changes: 2 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ lint.ignore = [
"SIM108",
"SIM114",
"TRY003",
"TCH003",
"PLW2901",
"RET505",
"PLR0913",
"UP038",
"TCH001",
"SIM103",
]

[lint.per-file-ignores]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ from dishka import Provider
provider = Provider()
```

3. Register functions which provide dependencies. Do not forget to place correct typehints for parameters and result. We use `scope=Scope.APP` for dependencies which ar created only once in application lifetime, and `scope=Scope.REQUEST` for those which should be recreated for each processing request/event/etc.
3. Register functions which provide dependencies. Do not forget to place correct typehints for parameters and result. We use `scope=Scope.APP` for dependencies which are created only once in application lifetime, and `scope=Scope.REQUEST` for those which should be recreated for each processing request/event/etc.

```python
from dishka import Provider, Scope
Expand Down Expand Up @@ -240,8 +240,8 @@ from dishka import from_context, Provider, provide, Scope
class MyProvider(Provider):
scope = Scope.REQUEST

app = from_context(provides=App, scope=Scope.APP)
request = from_context(provides=RequestClass)
app = from_context(App, scope=Scope.APP)
request = from_context(RequestClass)

@provide
def get_a(self, request: RequestClass, app: App) -> A:
Expand Down
10 changes: 6 additions & 4 deletions docs/advanced/context.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ Working with context data consists of three parts:
.. code-block:: python

from framework import Request
from dishka import Provider, make_container, Scope, from_context, provide

class MyProvider:
scope=Scope.REQUEST

class MyProvider(Provider):
scope = Scope.REQUEST

# declare source
request = from_context(provides=Request, scope=Scope.REQUEST)
Expand All @@ -33,8 +35,8 @@ Working with context data consists of three parts:
while True:
request = broker.recv()
# provide REQUEST-scoped context variable
with container(context={Request:request}) as request_container:
a = request_container.get(A)
with container(context={Request: request}) as request_container:
a = request_container.get(A)

.. note::

Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/scopes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ In dishka scope determines a lifespan of dependency. Firstly, when creating prov

The set of scopes is defined once per container and providers should use the same scopes. You are not limited to standard scopes and can create custom ones, but it is hardly ever needed.

In most cases you need only 2 scopes. ``APP``-scope is usually entered on container creation and ``REQUEST``-scope is the on you go into during some event processing:
In most cases you need only 2 scopes. ``APP``-scope is usually entered on container creation and ``REQUEST``-scope is the one you go into during some event processing:

``APP`` |rarr| ``REQUEST``

Expand Down
4 changes: 2 additions & 2 deletions docs/advanced/testing/index.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Testing with dishka
***************************

Testing you 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.
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 you 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. 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.

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

Expand Down
6 changes: 3 additions & 3 deletions docs/alternatives.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ Fastapi depends provides simple but effective API to inject dependencies, but th
* It can be used only inside fastapi.
* You cannot use it for lazy initialization of singletons
* It mixes up Dependency Injection and Request decomposition. That leads to incorrect openapi specification or even broken app.
* You have to declare each dependencies with ``Depends`` on each level of application. So ether you business logic contains details of IoC-container or you have to duplicate constructor signatures.
* You have to declare each dependency with ``Depends`` on each level of application. So either your business logic contains details of IoC-container or you have to duplicate constructor signatures.
* It is not very fast in runtime, though you might never notice that
* Almost all examples in documentation ignore ``dependency_overrides``, which is actually a main thing to use fastapi as IoC-container.

Expand All @@ -169,14 +169,14 @@ Why not svcs?

On first approach ``dishka`` and ``svcs`` have similar api, but ``svcs`` does much less automation:

1. In svcs all binding between classes is done manually by calling ``container`` inside ach factory. In dishka you can just add class if you have type-hinted its ``__init__``. Additionally, in ``svsc`` you cannot use this information to validate graph or somehow visualize.
1. In svcs all binding between classes is done manually by calling ``container`` inside each factory. In dishka you can just add class if you have type-hinted its ``__init__``. Additionally, in ``svsc`` you cannot use this information to validate graph or somehow visualize.
2. While ``svsc`` caches dependencies there is no scope hierarchy. You can create multiple containers to make lazy singletons, but they are not thread-safe.
3. There are no predefined patterns like multiple providers and class-based providers. So the only way to make your container modular you need to decide how to do it. With ``dishka`` you can reuse ``providers`` making different combinations for different environments or cases.

Why not rodi?
=============================

``Rodi`` is pretty simple and fast. Though is misses most of the useful features.
``Rodi`` is pretty simple and fast. Though it misses most of the useful features.

* It has auto-wiring, but no isolated components.
* No resources finalization. You can somehow track what to finalize using your instance of ``ActivationScope``, but you have to write it on your own.
Expand Down
6 changes: 3 additions & 3 deletions docs/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ Standard scopes are (excluding skipped):
You decide when to enter and exit them, but it is done one by one. If you entered ``APP`` scope then the next step deeper will enter ``REQUEST`` scope.

.. note::
``APP`` scope can be used for lazy initialisation of singletons, while ``REQUEST`` scope is good for processing events like HTTP-requests or messenger updates. It is unlikely that you will need other scopes
``APP`` scope can be used for lazy initialization of singletons, while ``REQUEST`` scope is good for processing events like HTTP-requests or messenger updates. It is unlikely that you will need other scopes


In dishka dependencies are lazy - they are created when you first request them. If the same dependency is requested multiple time within one scope then the same instance is returned (you can disable it for each dependency separately). A created dependency is kept until you exit the scope. And in that moment it is not just dropped away, but corresponding finalization steps are done. You can enter same scope multiple times concurrently so to have multiple instances of objects you can work simultaneously.
In dishka dependencies are lazy - they are created when you first request them. If the same dependency is requested multiple times within one scope then the same instance is returned (you can disable it for each dependency separately). A created dependency is kept until you exit the scope. And in that moment it is not just dropped away, but corresponding finalization steps are done. You can enter same scope multiple times concurrently so to have multiple instances of objects you can work simultaneously.

Each object can depend on other objects from the same or previous scopes. So, if you have ``Config`` with scope of *APP* and ``Connection`` with scope of *REQUEST* you cannot have an *APP*-scoped object which requires a connection, but you can have *REQUEST*-scoped object which requires a ``Connection`` or a ``Config`` (or even both).

Expand Down Expand Up @@ -100,7 +100,7 @@ Component
====================
**Component** - is an isolated group of providers within the same container identified by a string. When dependency is requested it is searched only within the same component as its dependant, unless it is declared explicitly.

This allows you to have multiple parts of application build separately without need to think if the use same types.
This allows you to have multiple parts of application build separately without need to think if they use same types.

.. code-block:: python

Expand Down
16 changes: 8 additions & 8 deletions docs/di_intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Imagine you have a business logic which uses some remote API client
service = Service()
service.action()

Here, the ``client`` is a **dependency**. Imagine that you have many methods working with same client and each methods knows how to create the client. Than think about these question?
Here, the ``client`` is a **dependency**. Imagine that you have many methods working with same client and each method knows how to create the client. Than think about these questions?

* How do they get the ``token``? Should the every method read it on its own?
* What if the ``Client`` constructor will require more than one token? Should we copy-paste new parameters to each method?
Expand Down Expand Up @@ -79,12 +79,12 @@ Additionally I need to name anti-patterns, which should be avoided as they canno

* *Singleton*. It's mostly a variant of global variable. It can add laziness, but other characteristics are the same.

* *Monkey patch*. Or `mock.patch()` as an example. It allows to replace behavior in tests but it also relies on details how the class is imported and used instead of its interface. That make tests more fragile and requires more work to support them
* *Monkey patch*. Or `mock.patch()` as an example. It allows to replace behavior in tests but it also relies on details how the class is imported and used instead of its interface. That makes tests more fragile and requires more work to support them

When to inject dependencies?
===================================

For simple cases it is obvious that you have some classes with their requirements and once you start you app you create all of them and wire together. But real applications are more complicated things. They operate dozens or even hundreds of objects in complex hierarchy, they do concurrent processing.
For simple cases it is obvious that you have some classes with their requirements and once you start your app you create all of them and wire together. But real applications are more complicated things. They operate dozens or even hundreds of objects in complex hierarchy, they do concurrent processing.


It is a good idea to separate the code which uses dependencies and the code which creates them. Usually we want to reduce the knowledge about our dependencies in the code which uses them. But it is not always possible as different objects have different lifespan.
Expand Down Expand Up @@ -125,9 +125,9 @@ The trick is how to manage those dependencies when you have a lot of request han
service = request.state.service
service.action()

It works good. You have clean request handlers and you can change middlewares in tests. But it can become a problem if you have lot's of objects which are not cheap to create.
It works good. You have clean request handlers and you can change middlewares in tests. But it can become a problem if you have lots of objects which are not cheap to create.

* The second approach is to create some factory (let's call it **container**) and call it within request handler. You can still use middleware to pass it into handler (check also others features of your framework)
* The second approach is to create some factory (let's call it **container**) and call it within request handler. You can still use middleware to pass it into handler (check also other features of your framework)

.. code-block:: python

Expand Down Expand Up @@ -157,9 +157,9 @@ In both approaches you can control whether the instance is created on each reque
What is IoC-container?
=============================

IoC-container is a special object (or a framework providing such an object) which provides required objects following dependency injection rules and manages their lifetime. DI-framework is another name fur such frameworks.
IoC-container is a special object (or a framework providing such an object) which provides required objects following dependency injection rules and manages their lifetime. DI-framework is another name for such frameworks.

Common mistake is to treat IoC-container as a single way to inject dependencies. It has nothing common with reality. Dependency injection can be done just by passing one object to another, but in complex application it is not so easy to do. As it was shown above you might want to create a separate object to encapsulate all DI-related logic. ``Container`` in previous example is a an example of hand-written primitive IoC-container.
Common mistake is to treat IoC-container as a single way to inject dependencies. It has nothing common with reality. Dependency injection can be done just by passing one object to another, but in complex application it is not so easy to do. As it was shown above you might want to create a separate object to encapsulate all DI-related logic. ``Container`` in previous example is an example of hand-written primitive IoC-container.

Bigger is your application, more complex factories you need, more necessary is to automate creation of a container. You do not need to use IoC-container to test one small part of application, but it can be essential for launching it in whole. Fortunately, there are frameworks for it. But again, beware of spreading container-related details around your application code with an exception on scope boundaries.

Expand All @@ -172,4 +172,4 @@ So, talking about IoC-container we can write-down these ideas:

More about possible requirements you can read in :ref:`technical-requirements`.

So here is the time for **dishka** - an implementation of IoC-container with everything you need.
So here is the time for **dishka** - an implementation of IoC-container with everything you need.
Loading
Loading