Update aiohttp example and tutorial

This commit is contained in:
Roman Mogylatov 2021-10-31 17:46:23 -04:00
parent f531de3138
commit 29d0900970
5 changed files with 76 additions and 75 deletions

View File

@ -127,8 +127,6 @@ Now it's time to install the project requirements. We will use next packages:
- ``dependency-injector`` - the dependency injection framework - ``dependency-injector`` - the dependency injection framework
- ``aiohttp`` - the web framework - ``aiohttp`` - the web framework
- ``aiohttp-devtools`` - the helper library that will provide a development server with live
reloading
- ``pyyaml`` - the YAML files parsing library, used for the reading of the configuration files - ``pyyaml`` - the YAML files parsing library, used for the reading of the configuration files
- ``pytest-aiohttp`` - the helper library for the testing of the ``aiohttp`` application - ``pytest-aiohttp`` - the helper library for the testing of the ``aiohttp`` application
- ``pytest-cov`` - the helper library for measuring the test coverage - ``pytest-cov`` - the helper library for measuring the test coverage
@ -139,7 +137,6 @@ Put next lines into the ``requirements.txt`` file:
dependency-injector dependency-injector
aiohttp aiohttp
aiohttp-devtools
pyyaml pyyaml
pytest-aiohttp pytest-aiohttp
pytest-cov pytest-cov
@ -232,26 +229,31 @@ Put next into the ``application.py``:
]) ])
return app return app
if __name__ == "__main__":
app = create_app()
web.run_app(app)
Now we're ready to run our application Now we're ready to run our application
Do next in the terminal: Do next in the terminal:
.. code-block:: bash .. code-block:: bash
adev runserver giphynavigator/application.py --livereload python -m giphynavigator.application
The output should be something like: The output should be something like:
.. code-block:: bash .. code-block:: bash
[18:52:59] Starting aux server at http://localhost:8001 ◆ ======== Running on http://0.0.0.0:8080 ========
[18:52:59] Starting dev server at http://localhost:8000 ● (Press CTRL+C to quit)
Let's check that it works. Open another terminal session and use ``httpie``: Let's check that it works. Open another terminal session and use ``httpie``:
.. code-block:: bash .. code-block:: bash
http http://127.0.0.1:8000/ http http://0.0.0.0:8080/
You should see: You should see:
@ -261,7 +263,7 @@ You should see:
Content-Length: 844 Content-Length: 844
Content-Type: application/json; charset=utf-8 Content-Type: application/json; charset=utf-8
Date: Wed, 29 Jul 2020 21:01:50 GMT Date: Wed, 29 Jul 2020 21:01:50 GMT
Server: Python/3.9 aiohttp/3.6.2 Server: Python/3.10 aiohttp/3.6.2
{ {
"gifs": [], "gifs": [],
@ -328,8 +330,10 @@ Now we need to add ``GiphyClient`` into the container. The ``GiphyClient`` has t
that have to be injected: the API key and the request timeout. We will need to use two more that have to be injected: the API key and the request timeout. We will need to use two more
providers from the ``dependency_injector.providers`` module: providers from the ``dependency_injector.providers`` module:
- ``Factory`` provider that will create the ``GiphyClient`` client. - ``Factory`` provider. It will create a ``GiphyClient`` client.
- ``Configuration`` provider that will provide the API key and the request timeout. - ``Configuration`` provider. It will provide an API key and a request timeout for the ``GiphyClient``
client. We will specify the location of the configuration file. The configuration provider will parse
the configuration file when we create a container instance.
Edit ``containers.py``: Edit ``containers.py``:
@ -345,7 +349,7 @@ Edit ``containers.py``:
class Container(containers.DeclarativeContainer): class Container(containers.DeclarativeContainer):
config = providers.Configuration() config = providers.Configuration(yaml_files=["config.yml"])
giphy_client = providers.Factory( giphy_client = providers.Factory(
giphy.GiphyClient, giphy.GiphyClient,
@ -353,18 +357,8 @@ Edit ``containers.py``:
timeout=config.giphy.request_timeout, timeout=config.giphy.request_timeout,
) )
.. note:: Now let's add the configuration file. We will use YAML. Create an empty file ``config.yml`` in
the root root of the project:
We have used the configuration value before it was defined. That's the principle how the
``Configuration`` provider works.
Use first, define later.
Now let's add the configuration file.
We will use YAML.
Create an empty file ``config.yml`` in the root root of the project:
.. code-block:: bash .. code-block:: bash
:emphasize-lines: 9 :emphasize-lines: 9
@ -387,17 +381,14 @@ and put next into it:
giphy: giphy:
request_timeout: 10 request_timeout: 10
We will use an environment variable ``GIPHY_API_KEY`` to provide the API key.
Now we need to edit ``create_app()`` to make two things when application starts: We will use the ``GIPHY_API_KEY`` environment variable to provide the API key. Lets edit
``create_app()`` to fetch the key value from it.
- Load the configuration file the ``config.yml``.
- Load the API key from the ``GIPHY_API_KEY`` environment variable.
Edit ``application.py``: Edit ``application.py``:
.. code-block:: python .. code-block:: python
:emphasize-lines: 11-12 :emphasize-lines: 11
"""Application module.""" """Application module."""
@ -409,7 +400,6 @@ Edit ``application.py``:
def create_app() -> web.Application: def create_app() -> web.Application:
container = Container() container = Container()
container.config.from_yaml("config.yml")
container.config.giphy.api_key.from_env("GIPHY_API_KEY") container.config.giphy.api_key.from_env("GIPHY_API_KEY")
app = web.Application() app = web.Application()
@ -420,6 +410,10 @@ Edit ``application.py``:
return app return app
if __name__ == "__main__":
app = create_app()
web.run_app(app)
Now we need to create an API key and set it to the environment variable. Now we need to create an API key and set it to the environment variable.
As for now, dont worry, just take this one: As for now, dont worry, just take this one:
@ -502,7 +496,7 @@ Edit ``containers.py``:
class Container(containers.DeclarativeContainer): class Container(containers.DeclarativeContainer):
config = providers.Configuration() config = providers.Configuration(yaml_files=["config.yml"])
giphy_client = providers.Factory( giphy_client = providers.Factory(
giphy.GiphyClient, giphy.GiphyClient,
@ -555,47 +549,50 @@ Edit ``handlers.py``:
}, },
) )
To make the injection work we need to wire the container instance with the ``handlers`` module. To make the injection work we need to wire the container with the ``handlers`` module.
This needs to be done once. After it's done we can use ``Provide`` markers to specify as many Let's configure the container to automatically make wiring with the ``handlers`` module when we
injections as needed for any handler. create a container instance.
Edit ``application.py``: Edit ``containers.py``:
.. code-block:: python .. code-block:: python
:emphasize-lines: 13 :emphasize-lines: 10
"""Application module.""" """Containers module."""
from aiohttp import web from dependency_injector import containers, providers
from .containers import Container from . import giphy, services
from . import handlers
def create_app() -> web.Application: class Container(containers.DeclarativeContainer):
container = Container()
container.config.from_yaml("config.yml")
container.config.giphy.api_key.from_env("GIPHY_API_KEY")
container.wire(modules=[handlers])
app = web.Application() wiring_config = containers.WiringConfiguration(modules=[".handlers"])
app.container = container
app.add_routes([
web.get("/", handlers.index),
])
return app
Make sure the app is running or use: config = providers.Configuration(yaml_files=["config.yml"])
giphy_client = providers.Factory(
giphy.GiphyClient,
api_key=config.giphy.api_key,
timeout=config.giphy.request_timeout,
)
search_service = providers.Factory(
services.SearchService,
giphy_client=giphy_client,
)
Make sure the app is running:
.. code-block:: bash .. code-block:: bash
adev runserver giphynavigator/application.py --livereload python -m giphynavigator.application
and make a request to the API in the terminal: and make a request to the API in the terminal:
.. code-block:: bash .. code-block:: bash
http http://localhost:8000/ query=="wow,it works" limit==5 http http://0.0.0.0:8080/ query=="wow,it works" limit==5
You should see: You should see:
@ -605,7 +602,7 @@ You should see:
Content-Length: 492 Content-Length: 492
Content-Type: application/json; charset=utf-8 Content-Type: application/json; charset=utf-8
Date: Fri, 09 Oct 2020 01:35:48 GMT Date: Fri, 09 Oct 2020 01:35:48 GMT
Server: Python/3.9 aiohttp/3.6.2 Server: Python/3.10 aiohttp/3.6.2
{ {
"gifs": [ "gifs": [
@ -810,24 +807,24 @@ You should see:
.. code-block:: .. code-block::
platform darwin -- Python 3.9, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 platform darwin -- Python 3.10.0, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
plugins: cov-2.10.0, aiohttp-0.3.0, asyncio-0.14.0 plugins: asyncio-0.16.0, anyio-3.3.4, aiohttp-0.3.0, cov-3.0.0
collected 3 items collected 3 items
giphynavigator/tests.py ... [100%] giphynavigator/tests.py ... [100%]
---------- coverage: platform darwin, python 3.9 ----------- ---------- coverage: platform darwin, python 3.10.0-final-0 ----------
Name Stmts Miss Cover Name Stmts Miss Cover
--------------------------------------------------- ---------------------------------------------------
giphynavigator/__init__.py 0 0 100% giphynavigator/__init__.py 0 0 100%
giphynavigator/application.py 12 0 100% giphynavigator/application.py 13 2 85%
giphynavigator/containers.py 6 0 100% giphynavigator/containers.py 7 0 100%
giphynavigator/giphy.py 14 9 36% giphynavigator/giphy.py 14 9 36%
giphynavigator/handlers.py 10 0 100% giphynavigator/handlers.py 10 0 100%
giphynavigator/services.py 9 1 89% giphynavigator/services.py 9 1 89%
giphynavigator/tests.py 37 0 100% giphynavigator/tests.py 37 0 100%
--------------------------------------------------- ---------------------------------------------------
TOTAL 88 10 89% TOTAL 90 12 87%
.. note:: .. note::

View File

@ -27,16 +27,16 @@ To run the application do:
.. code-block:: bash .. code-block:: bash
export GIPHY_API_KEY=wBJ2wZG7SRqfrU9nPgPiWvORmloDyuL0 export GIPHY_API_KEY=wBJ2wZG7SRqfrU9nPgPiWvORmloDyuL0
adev runserver giphynavigator/application.py --livereload python -m giphynavigator.application
The output should be something like: The output should be something like:
.. code-block:: .. code-block::
[18:52:59] Starting aux server at http://localhost:8001 ◆ ======== Running on http://0.0.0.0:8080 ========
[18:52:59] Starting dev server at http://localhost:8000 ● (Press CTRL+C to quit)
After that visit http://127.0.0.1:8000/ in your browser or use CLI command (``curl``, ``httpie``, After that visit http://0.0.0.0:8080/ in your browser or use CLI command (``curl``, ``httpie``,
etc). You should see something like: etc). You should see something like:
.. code-block:: json .. code-block:: json
@ -98,21 +98,21 @@ The output should be something like:
.. code-block:: .. code-block::
platform darwin -- Python 3.9, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 platform darwin -- Python 3.10.0, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
plugins: cov-2.10.0, aiohttp-0.3.0, asyncio-0.14.0 plugins: asyncio-0.16.0, anyio-3.3.4, aiohttp-0.3.0, cov-3.0.0
collected 3 items collected 3 items
giphynavigator/tests.py ... [100%] giphynavigator/tests.py ... [100%]
---------- coverage: platform darwin, python 3.9 ----------- ---------- coverage: platform darwin, python 3.10.0-final-0 ----------
Name Stmts Miss Cover Name Stmts Miss Cover
--------------------------------------------------- ---------------------------------------------------
giphynavigator/__init__.py 0 0 100% giphynavigator/__init__.py 0 0 100%
giphynavigator/application.py 12 0 100% giphynavigator/application.py 13 2 85%
giphynavigator/containers.py 6 0 100% giphynavigator/containers.py 7 0 100%
giphynavigator/giphy.py 14 9 36% giphynavigator/giphy.py 14 9 36%
giphynavigator/handlers.py 10 0 100% giphynavigator/handlers.py 10 0 100%
giphynavigator/services.py 9 1 89% giphynavigator/services.py 9 1 89%
giphynavigator/tests.py 37 0 100% giphynavigator/tests.py 37 0 100%
--------------------------------------------------- ---------------------------------------------------
TOTAL 88 10 89% TOTAL 90 12 87%

View File

@ -8,9 +8,7 @@ from . import handlers
def create_app() -> web.Application: def create_app() -> web.Application:
container = Container() container = Container()
container.config.from_yaml("config.yml")
container.config.giphy.api_key.from_env("GIPHY_API_KEY") container.config.giphy.api_key.from_env("GIPHY_API_KEY")
container.wire(modules=[handlers])
app = web.Application() app = web.Application()
app.container = container app.container = container
@ -18,3 +16,8 @@ def create_app() -> web.Application:
web.get("/", handlers.index), web.get("/", handlers.index),
]) ])
return app return app
if __name__ == "__main__":
app = create_app()
web.run_app(app)

View File

@ -7,7 +7,9 @@ from . import giphy, services
class Container(containers.DeclarativeContainer): class Container(containers.DeclarativeContainer):
config = providers.Configuration() wiring_config = containers.WiringConfiguration(modules=[".handlers"])
config = providers.Configuration(yaml_files=["config.yml"])
giphy_client = providers.Factory( giphy_client = providers.Factory(
giphy.GiphyClient, giphy.GiphyClient,

View File

@ -1,6 +1,5 @@
dependency-injector dependency-injector
aiohttp aiohttp
aiohttp-devtools
pyyaml pyyaml
pytest-aiohttp pytest-aiohttp
pytest-cov pytest-cov