-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #256 from reagento/feature/integrations_docs
Integrations docs
- Loading branch information
Showing
29 changed files
with
1,183 additions
and
291 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.. include:: <isonum.txt> | ||
|
||
For most cases we operate single events like HTTP-requests. In this case we operate only 2 scopes: ``APP`` and ``REQUEST``. | ||
Websockets are different: for one application you have multiple connections (one per client) and each connection delivers multiple messages. | ||
To support this we use additional scope: ``SESSION``: | ||
|
||
``APP`` |rarr| ``SESSION`` |rarr| ``REQUEST`` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
.. _adding_new: | ||
|
||
Adding new integrations | ||
=========================== | ||
|
||
Though there are some integrations in library you are not limited to use them. | ||
|
||
The main points are: | ||
|
||
1. Find a way to pass a global container instance. Often it is attached to application instance or passed by a middleware. | ||
2. Find a place to enter request scope and how to pass it to a handler. Usually, it is entered in a middleware and container is stored in some kind of request context. | ||
3. Configure a decorator. The main option here is to provide a way for retrieving container. Often, need to modify handler signature adding additional parameters. It is also available. | ||
4. Check if you can apply decorator automatically. | ||
|
||
While writing middlewares and working with scopes is done by your custom code, we have a helper for creating ``@inject`` decorators - a ``wrap_injection`` function. | ||
|
||
* ``container_getter`` is a function with two params ``(args, kwargs)`` which is called to get a container used to retrieve dependencies within scope. | ||
* ``additional_params`` is a list of ``inspect.Parameter`` which should be added to handler signature. | ||
|
||
For more details, check existing integrations. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
.. _aiogram: | ||
|
||
aiogram | ||
=========================================== | ||
|
||
Though it is not required, you can use dishka-aiogram integration. It features: | ||
|
||
* automatic REQUEST scope management using middleware | ||
* passing ``TelegramObject`` object as a context data to providers for telegram events (update object fields) | ||
* automatic injection of dependencies into handler function | ||
|
||
Only async handlers are supported. | ||
|
||
How to use | ||
**************** | ||
|
||
1. Import | ||
|
||
.. code-block:: python | ||
from dishka.integrations.aiogram import ( | ||
AiogramProvider, | ||
FromDishka, | ||
inject, | ||
setup_dishka, | ||
) | ||
from dishka import make_async_container, Provider, provide, Scope | ||
2. Create provider. You can use ``aiogram.types.TelegramObject`` as a factory parameter to access on REQUEST-scope | ||
|
||
.. code-block:: python | ||
class YourProvider(Provider): | ||
@provide(scope=Scope.REQUEST) | ||
def create_x(self, event: TelegramObject) -> X: | ||
... | ||
3. Mark those of your handlers parameters which are to be injected with ``FromDishka[]`` | ||
|
||
.. code-block:: python | ||
@dp.message() | ||
async def start( | ||
message: Message, | ||
gateway: FromDishka[Gateway], | ||
): | ||
3a. *(optional)* decorate them using ``@inject`` if you are not using auto-injection | ||
|
||
.. code-block:: python | ||
@dp.message() | ||
@inject | ||
async def start( | ||
message: Message, | ||
gateway: FromDishka[Gateway], | ||
): | ||
4. *(optional)* Use ``AiogramProvider()`` when creating container if you are going to use ``aiogram.types.TelegramObject`` in providers. | ||
|
||
.. code-block:: python | ||
container = make_async_container(YourProvider(), AiogramProvider()) | ||
6. Setup dishka integration. ``autoinject=True`` is required unless you explicitly use ``@inject`` decorator | ||
|
||
.. code-block:: python | ||
setup_dishka(container=container, router=dp, auto_inject=True) | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
.. _aiogram_dialog: | ||
|
||
aiogram-dialog | ||
=========================================== | ||
|
||
|
||
Though it is not required, you can use dishka-aiogram_dialog integration. It allows you to inject object into aiogram-dialog handlers | ||
|
||
|
||
How to use | ||
**************** | ||
|
||
1. Setup :ref:`aiogram integration<aiogram>` | ||
|
||
2. Import decorator | ||
|
||
.. code-block:: python | ||
from dishka.integrations.aiogram_dialog import inject | ||
3. Mark those of your aiogram-dialog handlers and getters parameters which are to be injected with ``FromDishka[]`` decorate them using imported ``@inject`` decorator. | ||
|
||
.. code-block:: python | ||
@inject | ||
async def getter( | ||
a: FromDishka[RequestDep], | ||
mock: FromDishka[Mock], | ||
**kwargs, | ||
): | ||
... | ||
@inject | ||
async def on_click( | ||
event, | ||
widget, | ||
manager, | ||
a: FromDishka[RequestDep], | ||
mock: FromDishka[Mock], | ||
): | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
.. _aiohttp: | ||
|
||
aiohttp | ||
=========================================== | ||
|
||
Though it is not required, you can use dishka-aiohttp integration. It features: | ||
|
||
* automatic REQUEST and SESSION scope management using middleware | ||
* passing ``Request`` object as a context data to providers for both **Websockets** and **HTTP** requests | ||
* automatic injection of dependencies into handler function | ||
|
||
|
||
How to use | ||
**************** | ||
|
||
1. Import | ||
|
||
.. code-block:: python | ||
from dishka.integrations.aiohttp import ( | ||
DISHKA_CONTAINER_KEY, | ||
FromDishka, | ||
inject, | ||
setup_dishka, | ||
AiohttpProvider, | ||
) | ||
from dishka import make_async_container, Provider, provide, Scope | ||
2. Create provider. You can use ``aiohttp.web.Request`` as a factory parameter to access HTTP or Websocket request. | ||
It is available on ``SESSION`` and ``REQUEST`` scopes. | ||
|
||
.. code-block:: python | ||
class YourProvider(Provider): | ||
@provide(scope=Scope.REQUEST) | ||
def create_x(self, request: Request) -> X: | ||
... | ||
3. Mark those of your handlers parameters which are to be injected with ``FromDishka[]`` | ||
|
||
.. code-block:: python | ||
@router.get('/') | ||
async def endpoint( | ||
request: str, gateway: FromDishka[Gateway], | ||
) -> Response: | ||
... | ||
3a. *(optional)* decorate them using ``@inject`` | ||
|
||
.. code-block:: python | ||
@router.get('/') | ||
@inject | ||
async def endpoint( | ||
request: str, gateway: FromDishka[Gateway], | ||
) -> Response: | ||
... | ||
4. *(optional)* Use ``AiohttpProvider()`` when creating container if you are going to use ``aiohttp.web.Request`` in providers. | ||
|
||
.. code-block:: python | ||
container = make_async_container(YourProvider(), AiohttpProvider()) | ||
5. Setup dishka integration. ``autoinject=True`` is required unless you explicitly use ``@inject`` decorator | ||
|
||
.. code-block:: python | ||
setup_dishka(container=container, app=app, autoinject=True) | ||
6. *(optional)* Close container on app termination | ||
|
||
.. code-block:: python | ||
async def on_shutdown(app: Application): | ||
await app[DISHKA_CONTAINER_KEY].close() | ||
app.on_shutdown.append(on_shutdown) | ||
Websockets | ||
********************** | ||
|
||
.. include:: _websockets.rst | ||
|
||
In aiohttp your view function is called once per connection and then you retrieve messages in loop. | ||
So, ``inject`` decorator can be only used to retrieve SESSION-scoped objects. | ||
To achieve REQUEST-scope you can enter in manually: | ||
|
||
.. code-block:: python | ||
@inject | ||
async def get_with_request( | ||
request: Request, | ||
a: FromDishka[A], # some object with Scope.SESSION | ||
container: FromDishka[AsyncContainer], # container for Scope.SESSION | ||
) -> web.WebsocketResponse: | ||
websocket = web.WebsocketResponse() | ||
await websocket.prepare(request) | ||
async for message in weboscket: | ||
# enter the nested scope, which is Scope.REQUEST | ||
async with container() as request_container: | ||
b = await request_container.get(B) # object with Scope.REQUEST |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
.. _arq: | ||
|
||
arq | ||
================ | ||
|
||
Though it is not required, you can use dishka-taskiq integration. It features: | ||
|
||
* automatic REQUEST scope management using middleware | ||
* injection of dependencies into task handler function using decorator | ||
|
||
|
||
How to use | ||
**************** | ||
|
||
1. Import | ||
|
||
.. code-block:: python | ||
from dishka.integrations.arq import ( | ||
FromDishka, | ||
inject, | ||
setup_dishka, | ||
) | ||
2. Create provider and container as usual | ||
|
||
3. Mark those of your handlers parameters which are to be injected with ``FromDishka[]`` and decorate them using ``@inject`` | ||
|
||
.. code-block:: python | ||
@inject | ||
async def get_content( | ||
context: dict[Any, Any], | ||
gateway: FromDishka[Gateway], | ||
): | ||
... | ||
4. Setup dishka integration on your Worker class or directly on WorkerSettings | ||
|
||
.. code-block:: python | ||
setup_dishka(container=container, worker_settings=WorkerSettings) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
.. _click: | ||
|
||
Click | ||
================================= | ||
|
||
|
||
Though it is not required, you can use dishka-click integration. It features automatic injection to command handlers | ||
In contrast with other integrations there is no scope management. | ||
|
||
|
||
|
||
How to use | ||
**************** | ||
|
||
1. Import | ||
|
||
.. code-block:: python | ||
from dishka.integrations.click import setup_dishka, inject | ||
2. Create container in group handler and setup it to click context. Pass ``auto_inject=True`` unless you want to use ``@inject`` decorator explicitly. | ||
|
||
.. code-block:: python | ||
@click.group() | ||
@click.pass_context | ||
def main(context: click.Context): | ||
container = make_container(MyProvider()) | ||
setup_dishka(container=container, context=context, auto_inject=True) | ||
3. Mark those of your command handlers parameters which are to be injected with ``FromDishka[]`` | ||
|
||
.. code-block:: python | ||
@main.command(name="hello") | ||
def hello(interactor: FromDishka[Interactor]): | ||
... | ||
3a. *(optional)* decorate them using ``@inject`` | ||
|
||
.. code-block:: python | ||
@main.command(name="hello") | ||
@inject | ||
def hello(interactor: FromDishka[Interactor]): | ||
... |
Oops, something went wrong.