mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Merge branch 'release/3.24.0' into master
This commit is contained in:
		
						commit
						469cb37302
					
				| 
						 | 
					@ -3,7 +3,7 @@ dist: xenial
 | 
				
			||||||
language: python
 | 
					language: python
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  include:
 | 
					  include:
 | 
				
			||||||
  - python: 3.6
 | 
					  - python: 3.8
 | 
				
			||||||
    env: TOXENV=coveralls DEPENDENCY_INJECTOR_DEBUG_MODE=1
 | 
					    env: TOXENV=coveralls DEPENDENCY_INJECTOR_DEBUG_MODE=1
 | 
				
			||||||
    install:
 | 
					    install:
 | 
				
			||||||
      - pip install tox
 | 
					      - pip install tox
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								docs/api/aiohttpext.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docs/api/aiohttpext.rst
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					dependency_injector.ext.aiohttp
 | 
				
			||||||
 | 
					===============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. automodule:: dependency_injector.ext.aiohttp
 | 
				
			||||||
 | 
					   :members:
 | 
				
			||||||
 | 
					   :special-members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					@ -8,4 +8,5 @@ API Documentation
 | 
				
			||||||
    providers
 | 
					    providers
 | 
				
			||||||
    containers
 | 
					    containers
 | 
				
			||||||
    errors
 | 
					    errors
 | 
				
			||||||
 | 
					    aiohttpext
 | 
				
			||||||
    flaskext
 | 
					    flaskext
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,11 @@ that were made in every particular version.
 | 
				
			||||||
From version 0.7.6 *Dependency Injector* framework strictly 
 | 
					From version 0.7.6 *Dependency Injector* framework strictly 
 | 
				
			||||||
follows `Semantic versioning`_
 | 
					follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3.24.0
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					- Add ``Aiohttp`` integration module ``dependency_injector.ext.aiohttp``.
 | 
				
			||||||
 | 
					- Add ``Aiohttp`` + ``Dependency Injector`` example ``giphynav-aiohttp``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3.23.2
 | 
					3.23.2
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
- Fix ``Flask`` tutorial code issues, typos and change some wording.
 | 
					- Fix ``Flask`` tutorial code issues, typos and change some wording.
 | 
				
			||||||
| 
						 | 
					@ -48,7 +53,7 @@ follows `Semantic versioning`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3.20.0
 | 
					3.20.0
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
- Add ``Flask`` integration module ``dependency_injector.flask.ext``.
 | 
					- Add ``Flask`` integration module ``dependency_injector.ext.flask``.
 | 
				
			||||||
- Add ``Flask`` + ``Dependency Injector`` example ``ghnav-flask``.
 | 
					- Add ``Flask`` + ``Dependency Injector`` example ``ghnav-flask``.
 | 
				
			||||||
- Add ``Factory.provides`` attribute. It is an alias to the ``Factory.cls``.
 | 
					- Add ``Factory.provides`` attribute. It is an alias to the ``Factory.cls``.
 | 
				
			||||||
- New README.
 | 
					- New README.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ After that visit http://127.0.0.1:5000/ in your browser.
 | 
				
			||||||
Test
 | 
					Test
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This application comes with unit tests.
 | 
					This application comes with the unit tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To run the tests do:
 | 
					To run the tests do:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										117
									
								
								examples/miniapps/giphynav-aiohttp/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								examples/miniapps/giphynav-aiohttp/README.rst
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					Aiohttp Dependency Injection Example
 | 
				
			||||||
 | 
					====================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Application ``giphynavigator`` is a `Aiohttp <https://docs.aiohttp.org/>`_ +
 | 
				
			||||||
 | 
					`Dependency Injector <http://python-dependency-injector.ets-labs.org/>`_ application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Run
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create virtual environment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block:: bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   virtualenv venv
 | 
				
			||||||
 | 
					   . venv/bin/activate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block:: bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pip install -r requirements.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To run the application do:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block:: bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export GIPHY_API_KEY=wBJ2wZG7SRqfrU9nPgPiWvORmloDyuL0
 | 
				
			||||||
 | 
					    adev runserver giphynavigator/application.py --livereload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The output should be something like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   [18:52:59] Starting aux server at http://localhost:8001 ◆
 | 
				
			||||||
 | 
					   [18:52:59] Starting dev server at http://localhost:8000 ●
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After that visit http://127.0.0.1:8000/ in your browser or use CLI command (``curl``, ``httpie``,
 | 
				
			||||||
 | 
					etc). You should see something like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block:: json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
 | 
					       "query": "Dependency Injector",
 | 
				
			||||||
 | 
					       "limit": 10,
 | 
				
			||||||
 | 
					       "gifs": [
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/boxes-dependent-swbf2-6Eo7KzABxgJMY"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/depends-J56qCcOhk6hKE"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/web-series-ccstudios-bro-dependent-1lhU8KAVwmVVu"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/TheBoysTV-friends-friend-weneedeachother-XxR9qcIwcf5Jq404Sx"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/netflix-a-series-of-unfortunate-events-asoue-9rgeQXbwoK53pcxn7f"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/black-and-white-sad-skins-Hs4YzLs2zJuLu"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/always-there-for-you-i-am-here-PlayjhCco9jHBYrd9w"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/stream-famous-dollar-YT2dvOByEwXCdoYiA1"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/i-love-you-there-for-am-1BhGzgpZXYWwWMAGB1"
 | 
				
			||||||
 | 
					           },
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               "url": "https://giphy.com/gifs/life-like-twerk-9hlnWxjHqmH28"
 | 
				
			||||||
 | 
					           }
 | 
				
			||||||
 | 
					       ]
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   To create your own Giphy API key follow this
 | 
				
			||||||
 | 
					   `guide <https://support.giphy.com/hc/en-us/articles/360020283431-Request-A-GIPHY-API-Key>`_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Test
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This application comes with the unit tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To run the tests do:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block:: bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   py.test giphynavigator/tests.py --cov=giphynavigator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The output should be something like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code-block::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
 | 
				
			||||||
 | 
					   plugins: cov-2.10.0, aiohttp-0.3.0, asyncio-0.14.0
 | 
				
			||||||
 | 
					   collected 3 items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   giphynavigator/tests.py ...                                     [100%]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   ---------- coverage: platform darwin, python 3.8.3-final-0 -----------
 | 
				
			||||||
 | 
					   Name                            Stmts   Miss  Cover
 | 
				
			||||||
 | 
					   ---------------------------------------------------
 | 
				
			||||||
 | 
					   giphynavigator/__init__.py          0      0   100%
 | 
				
			||||||
 | 
					   giphynavigator/__main__.py          5      5     0%
 | 
				
			||||||
 | 
					   giphynavigator/application.py      10      0   100%
 | 
				
			||||||
 | 
					   giphynavigator/containers.py       10      0   100%
 | 
				
			||||||
 | 
					   giphynavigator/giphy.py            16     11    31%
 | 
				
			||||||
 | 
					   giphynavigator/services.py          9      1    89%
 | 
				
			||||||
 | 
					   giphynavigator/tests.py            35      0   100%
 | 
				
			||||||
 | 
					   giphynavigator/views.py             7      0   100%
 | 
				
			||||||
 | 
					   ---------------------------------------------------
 | 
				
			||||||
 | 
					   TOTAL                              92     17    82%
 | 
				
			||||||
							
								
								
									
										5
									
								
								examples/miniapps/giphynav-aiohttp/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								examples/miniapps/giphynav-aiohttp/config.yml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					giphy:
 | 
				
			||||||
 | 
					  request_timeout: 10
 | 
				
			||||||
 | 
					search:
 | 
				
			||||||
 | 
					  default_query: "Dependency Injector"
 | 
				
			||||||
 | 
					  default_limit: 10
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					"""Top-level package."""
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					"""Main module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .application import create_app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    app = create_app()
 | 
				
			||||||
 | 
					    web.run_app(app)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					"""Application module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .containers import ApplicationContainer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def create_app():
 | 
				
			||||||
 | 
					    """Create and return Flask application."""
 | 
				
			||||||
 | 
					    container = ApplicationContainer()
 | 
				
			||||||
 | 
					    container.config.from_yaml('config.yml')
 | 
				
			||||||
 | 
					    container.config.giphy.api_key.from_env('GIPHY_API_KEY')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app: web.Application = container.app()
 | 
				
			||||||
 | 
					    app.container = container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app.add_routes([
 | 
				
			||||||
 | 
					        web.get('/', container.index_view.as_view()),
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return app
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,33 @@
 | 
				
			||||||
 | 
					"""Application containers module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import containers, providers
 | 
				
			||||||
 | 
					from dependency_injector.ext import aiohttp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import web
 | 
				
			||||||
 | 
					from . import giphy, services, views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApplicationContainer(containers.DeclarativeContainer):
 | 
				
			||||||
 | 
					    """Application container."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app = aiohttp.Application(web.Application)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    config = providers.Configuration()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    index_view = aiohttp.View(
 | 
				
			||||||
 | 
					        views.index,
 | 
				
			||||||
 | 
					        search_service=search_service,
 | 
				
			||||||
 | 
					        default_query=config.search.default_query,
 | 
				
			||||||
 | 
					        default_limit=config.search.default_limit,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
							
								
								
									
										29
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/giphy.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/giphy.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					"""Giphy client module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import ClientSession, ClientTimeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GiphyClient:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    API_URL = 'http://api.giphy.com/v1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, api_key, timeout):
 | 
				
			||||||
 | 
					        self._api_key = api_key
 | 
				
			||||||
 | 
					        self._timeout = ClientTimeout(timeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def search(self, query, limit):
 | 
				
			||||||
 | 
					        """Make search API call and return result."""
 | 
				
			||||||
 | 
					        if not query:
 | 
				
			||||||
 | 
					            return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        url = f'{self.API_URL}/gifs/search'
 | 
				
			||||||
 | 
					        params = {
 | 
				
			||||||
 | 
					            'q': query,
 | 
				
			||||||
 | 
					            'api_key': self._api_key,
 | 
				
			||||||
 | 
					            'limit': limit,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        async with ClientSession(timeout=self._timeout) as session:
 | 
				
			||||||
 | 
					            async with session.get(url, params=params) as response:
 | 
				
			||||||
 | 
					                if response.status != 200:
 | 
				
			||||||
 | 
					                    response.raise_for_status()
 | 
				
			||||||
 | 
					                return await response.json()
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					"""Services module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .giphy import GiphyClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SearchService:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, giphy_client: GiphyClient):
 | 
				
			||||||
 | 
					        self._giphy_client = giphy_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def search(self, query, limit):
 | 
				
			||||||
 | 
					        """Search for gifs and return formatted data."""
 | 
				
			||||||
 | 
					        if not query:
 | 
				
			||||||
 | 
					            return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = await self._giphy_client.search(query, limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [{'url': gif['url']} for gif in result['data']]
 | 
				
			||||||
							
								
								
									
										77
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/tests.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/tests.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,77 @@
 | 
				
			||||||
 | 
					"""Tests module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from giphynavigator.application import create_app
 | 
				
			||||||
 | 
					from giphynavigator.giphy import GiphyClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def app():
 | 
				
			||||||
 | 
					    return create_app()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def client(app, aiohttp_client, loop):
 | 
				
			||||||
 | 
					    return loop.run_until_complete(aiohttp_client(app))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_index(client, app):
 | 
				
			||||||
 | 
					    giphy_client_mock = mock.AsyncMock(spec=GiphyClient)
 | 
				
			||||||
 | 
					    giphy_client_mock.search.return_value = {
 | 
				
			||||||
 | 
					        'data': [
 | 
				
			||||||
 | 
					            {'url': 'https://giphy/gif1.gif'},
 | 
				
			||||||
 | 
					            {'url': 'https://giphy/gif2.gif'},
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with app.container.giphy_client.override(giphy_client_mock):
 | 
				
			||||||
 | 
					        response = await client.get(
 | 
				
			||||||
 | 
					            '/',
 | 
				
			||||||
 | 
					            params={
 | 
				
			||||||
 | 
					                'query': 'test',
 | 
				
			||||||
 | 
					                'limit': 10,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    data = await response.json()
 | 
				
			||||||
 | 
					    assert data == {
 | 
				
			||||||
 | 
					        'query': 'test',
 | 
				
			||||||
 | 
					        'limit': 10,
 | 
				
			||||||
 | 
					        'gifs': [
 | 
				
			||||||
 | 
					            {'url': 'https://giphy/gif1.gif'},
 | 
				
			||||||
 | 
					            {'url': 'https://giphy/gif2.gif'},
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_index_no_data(client, app):
 | 
				
			||||||
 | 
					    giphy_client_mock = mock.AsyncMock(spec=GiphyClient)
 | 
				
			||||||
 | 
					    giphy_client_mock.search.return_value = {
 | 
				
			||||||
 | 
					        'data': [],
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with app.container.giphy_client.override(giphy_client_mock):
 | 
				
			||||||
 | 
					        response = await client.get('/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    data = await response.json()
 | 
				
			||||||
 | 
					    assert data['gifs'] == []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test_index_default_params(client, app):
 | 
				
			||||||
 | 
					    giphy_client_mock = mock.AsyncMock(spec=GiphyClient)
 | 
				
			||||||
 | 
					    giphy_client_mock.search.return_value = {
 | 
				
			||||||
 | 
					        'data': [],
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with app.container.giphy_client.override(giphy_client_mock):
 | 
				
			||||||
 | 
					        response = await client.get('/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert response.status == 200
 | 
				
			||||||
 | 
					    data = await response.json()
 | 
				
			||||||
 | 
					    assert data['query'] == app.container.config.search.default_query()
 | 
				
			||||||
 | 
					    assert data['limit'] == app.container.config.search.default_limit()
 | 
				
			||||||
							
								
								
									
										25
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								examples/miniapps/giphynav-aiohttp/giphynavigator/views.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					"""Views module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .services import SearchService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def index(
 | 
				
			||||||
 | 
					        request: web.Request,
 | 
				
			||||||
 | 
					        search_service: SearchService,
 | 
				
			||||||
 | 
					        default_query: str,
 | 
				
			||||||
 | 
					        default_limit: int,
 | 
				
			||||||
 | 
					) -> web.Response:
 | 
				
			||||||
 | 
					    query = request.query.get('query', default_query)
 | 
				
			||||||
 | 
					    limit = int(request.query.get('limit', default_limit))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gifs = await search_service.search(query, limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return web.json_response(
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            'query': query,
 | 
				
			||||||
 | 
					            'limit': limit,
 | 
				
			||||||
 | 
					            'gifs': gifs,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
							
								
								
									
										6
									
								
								examples/miniapps/giphynav-aiohttp/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								examples/miniapps/giphynav-aiohttp/requirements.txt
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					dependency-injector
 | 
				
			||||||
 | 
					aiohttp
 | 
				
			||||||
 | 
					aiohttp-devtools
 | 
				
			||||||
 | 
					pyyaml
 | 
				
			||||||
 | 
					pytest-aiohttp
 | 
				
			||||||
 | 
					pytest-cov
 | 
				
			||||||
| 
						 | 
					@ -1 +1,2 @@
 | 
				
			||||||
flask
 | 
					flask
 | 
				
			||||||
 | 
					aiohttp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								setup.py
									
									
									
									
									
								
							| 
						 | 
					@ -67,6 +67,9 @@ setup(name='dependency-injector',
 | 
				
			||||||
          'flask': [
 | 
					          'flask': [
 | 
				
			||||||
              'flask',
 | 
					              'flask',
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
 | 
					          'aiohttp': [
 | 
				
			||||||
 | 
					              'aiohttp',
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      zip_safe=True,
 | 
					      zip_safe=True,
 | 
				
			||||||
      license='BSD New',
 | 
					      license='BSD New',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
"""Dependency injector top-level package."""
 | 
					"""Dependency injector top-level package."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = '3.23.2'
 | 
					__version__ = '3.24.0'
 | 
				
			||||||
"""Version number that follows semantic versioning.
 | 
					"""Version number that follows semantic versioning.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:type: str
 | 
					:type: str
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/dependency_injector/ext/aiohttp.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/dependency_injector/ext/aiohttp.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					"""Aiohttp extension module."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import functools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Application(providers.Singleton):
 | 
				
			||||||
 | 
					    """Aiohttp application provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Extension(providers.Singleton):
 | 
				
			||||||
 | 
					    """Aiohttp extension provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Middleware(providers.DelegatedCallable):
 | 
				
			||||||
 | 
					    """Aiohttp middleware provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    __middleware_version__ = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MiddlewareFactory(providers.Factory):
 | 
				
			||||||
 | 
					    """Aiohttp middleware factory provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class View(providers.Callable):
 | 
				
			||||||
 | 
					    """Aiohttp view provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def as_view(self):
 | 
				
			||||||
 | 
					        """Return aiohttp view function."""
 | 
				
			||||||
 | 
					        @functools.wraps(self.provides)
 | 
				
			||||||
 | 
					        async def _view(request, *args, **kwargs):
 | 
				
			||||||
 | 
					            return await self.__call__(request, *args, **kwargs)
 | 
				
			||||||
 | 
					        return _view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClassBasedView(providers.Factory):
 | 
				
			||||||
 | 
					    """Aiohttp class-based view provider."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def as_view(self):
 | 
				
			||||||
 | 
					        """Return aiohttp view function."""
 | 
				
			||||||
 | 
					        async def _view(request, *args, **kwargs):
 | 
				
			||||||
 | 
					            return await self.__call__(request, *args, **kwargs)
 | 
				
			||||||
 | 
					        return _view
 | 
				
			||||||
							
								
								
									
										93
									
								
								tests/unit/ext/test_aiohttp_py35.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								tests/unit/ext/test_aiohttp_py35.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,93 @@
 | 
				
			||||||
 | 
					"""Dependency injector Aiohttp extension unit tests."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aiohttp import web
 | 
				
			||||||
 | 
					from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import containers, providers
 | 
				
			||||||
 | 
					from dependency_injector.ext import aiohttp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def index(_):
 | 
				
			||||||
 | 
					    return web.Response(text='Hello World!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def test(_):
 | 
				
			||||||
 | 
					    return web.Response(text='Test!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Test(web.View):
 | 
				
			||||||
 | 
					    async def get(self):
 | 
				
			||||||
 | 
					        return web.Response(text='Test class-based!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@web.middleware
 | 
				
			||||||
 | 
					async def middleware(request, handler):
 | 
				
			||||||
 | 
					    resp = await handler(request)
 | 
				
			||||||
 | 
					    resp.text = resp.text + ' wink1'
 | 
				
			||||||
 | 
					    return resp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def middleware_factory(text):
 | 
				
			||||||
 | 
					    @web.middleware
 | 
				
			||||||
 | 
					    async def sample_middleware(request, handler):
 | 
				
			||||||
 | 
					        resp = await handler(request)
 | 
				
			||||||
 | 
					        resp.text = resp.text + text
 | 
				
			||||||
 | 
					        return resp
 | 
				
			||||||
 | 
					    return sample_middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApplicationContainer(containers.DeclarativeContainer):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app = aiohttp.Application(
 | 
				
			||||||
 | 
					        web.Application,
 | 
				
			||||||
 | 
					        middlewares=providers.List(
 | 
				
			||||||
 | 
					            aiohttp.Middleware(middleware),
 | 
				
			||||||
 | 
					            aiohttp.MiddlewareFactory(middleware_factory, text=' wink2'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    index_view = aiohttp.View(index)
 | 
				
			||||||
 | 
					    test_view = aiohttp.View(test)
 | 
				
			||||||
 | 
					    test_class_view = aiohttp.ClassBasedView(Test)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApplicationTests(AioHTTPTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get_application(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Override the get_app method to return your application.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        container = ApplicationContainer()
 | 
				
			||||||
 | 
					        app = container.app()
 | 
				
			||||||
 | 
					        app.container = container
 | 
				
			||||||
 | 
					        app.add_routes([
 | 
				
			||||||
 | 
					            web.get('/', container.index_view.as_view()),
 | 
				
			||||||
 | 
					            web.get('/test', container.test_view.as_view(), name='test'),
 | 
				
			||||||
 | 
					            web.get('/test-class', container.test_class_view.as_view()),
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					        return app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @unittest_run_loop
 | 
				
			||||||
 | 
					    async def test_index(self):
 | 
				
			||||||
 | 
					        response = await self.client.get('/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(response.status, 200)
 | 
				
			||||||
 | 
					        self.assertEqual(await response.text(), 'Hello World! wink2 wink1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @unittest_run_loop
 | 
				
			||||||
 | 
					    async def test_test(self):
 | 
				
			||||||
 | 
					        response = await self.client.get('/test')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(response.status, 200)
 | 
				
			||||||
 | 
					        self.assertEqual(await response.text(), 'Test! wink2 wink1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @unittest_run_loop
 | 
				
			||||||
 | 
					    async def test_test_class_based(self):
 | 
				
			||||||
 | 
					        response = await self.client.get('/test-class')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(response.status, 200)
 | 
				
			||||||
 | 
					        self.assertEqual(await response.text(), 'Test class-based! wink2 wink1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @unittest_run_loop
 | 
				
			||||||
 | 
					    async def test_endpoints(self):
 | 
				
			||||||
 | 
					        self.assertEqual(str(self.app.router['test'].url_for()), '/test')
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import unittest2 as unittest
 | 
				
			||||||
from flask import Flask, url_for
 | 
					from flask import Flask, url_for
 | 
				
			||||||
from flask.views import MethodView
 | 
					from flask.views import MethodView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from dependency_injector import containers, providers
 | 
					from dependency_injector import containers
 | 
				
			||||||
from dependency_injector.ext import flask
 | 
					from dependency_injector.ext import flask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,9 @@
 | 
				
			||||||
"""Dependency injector coroutine providers unit tests."""
 | 
					"""Dependency injector coroutine providers unit tests."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import asyncio
 | 
					import asyncio
 | 
				
			||||||
 | 
					import contextlib
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import gc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import unittest2 as unittest
 | 
					import unittest2 as unittest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,20 +13,65 @@ from dependency_injector import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@asyncio.coroutine
 | 
					async def _example(arg1, arg2, arg3, arg4):
 | 
				
			||||||
def _example(arg1, arg2, arg3, arg4):
 | 
					 | 
				
			||||||
    future = asyncio.Future()
 | 
					    future = asyncio.Future()
 | 
				
			||||||
    future.set_result(None)
 | 
					    future.set_result(None)
 | 
				
			||||||
    yield from future
 | 
					    await future
 | 
				
			||||||
    return arg1, arg2, arg3, arg4
 | 
					    return arg1, arg2, arg3, arg4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _run(coro):
 | 
					def run(main):
 | 
				
			||||||
    loop = asyncio.get_event_loop()
 | 
					    loop = asyncio.get_event_loop()
 | 
				
			||||||
    return loop.run_until_complete(coro)
 | 
					    return loop.run_until_complete(main)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CoroutineTests(unittest.TestCase):
 | 
					def setup_test_loop(
 | 
				
			||||||
 | 
					        loop_factory=asyncio.new_event_loop
 | 
				
			||||||
 | 
					) -> asyncio.AbstractEventLoop:
 | 
				
			||||||
 | 
					    loop = loop_factory()
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        module = loop.__class__.__module__
 | 
				
			||||||
 | 
					        skip_watcher = 'uvloop' in module
 | 
				
			||||||
 | 
					    except AttributeError:  # pragma: no cover
 | 
				
			||||||
 | 
					        # Just in case
 | 
				
			||||||
 | 
					        skip_watcher = True
 | 
				
			||||||
 | 
					    asyncio.set_event_loop(loop)
 | 
				
			||||||
 | 
					    if sys.platform != "win32" and not skip_watcher:
 | 
				
			||||||
 | 
					        policy = asyncio.get_event_loop_policy()
 | 
				
			||||||
 | 
					        watcher = asyncio.SafeChildWatcher()  # type: ignore
 | 
				
			||||||
 | 
					        watcher.attach_loop(loop)
 | 
				
			||||||
 | 
					        with contextlib.suppress(NotImplementedError):
 | 
				
			||||||
 | 
					            policy.set_child_watcher(watcher)
 | 
				
			||||||
 | 
					    return loop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def teardown_test_loop(loop: asyncio.AbstractEventLoop,
 | 
				
			||||||
 | 
					                       fast: bool=False) -> None:
 | 
				
			||||||
 | 
					    closed = loop.is_closed()
 | 
				
			||||||
 | 
					    if not closed:
 | 
				
			||||||
 | 
					        loop.call_soon(loop.stop)
 | 
				
			||||||
 | 
					        loop.run_forever()
 | 
				
			||||||
 | 
					        loop.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not fast:
 | 
				
			||||||
 | 
					        gc.collect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    asyncio.set_event_loop(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AsyncTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        self.loop = setup_test_loop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tearDown(self):
 | 
				
			||||||
 | 
					        teardown_test_loop(self.loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _run(self, f):
 | 
				
			||||||
 | 
					        return self.loop.run_until_complete(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CoroutineTests(AsyncTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_init_with_coroutine(self):
 | 
					    def test_init_with_coroutine(self):
 | 
				
			||||||
        self.assertTrue(providers.Coroutine(_example))
 | 
					        self.assertTrue(providers.Coroutine(_example))
 | 
				
			||||||
| 
						 | 
					@ -33,34 +81,34 @@ class CoroutineTests(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_positional_args(self):
 | 
					    def test_call_with_positional_args(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example, 1, 2, 3, 4)
 | 
					        provider = providers.Coroutine(_example, 1, 2, 3, 4)
 | 
				
			||||||
        self.assertTupleEqual(_run(provider()), (1, 2, 3, 4))
 | 
					        self.assertTupleEqual(self._run(provider()), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_keyword_args(self):
 | 
					    def test_call_with_keyword_args(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example,
 | 
					        provider = providers.Coroutine(_example,
 | 
				
			||||||
                                       arg1=1, arg2=2, arg3=3, arg4=4)
 | 
					                                       arg1=1, arg2=2, arg3=3, arg4=4)
 | 
				
			||||||
        self.assertTupleEqual(_run(provider()), (1, 2, 3, 4))
 | 
					        self.assertTupleEqual(self._run(provider()), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_positional_and_keyword_args(self):
 | 
					    def test_call_with_positional_and_keyword_args(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example,
 | 
					        provider = providers.Coroutine(_example,
 | 
				
			||||||
                                       1, 2,
 | 
					                                       1, 2,
 | 
				
			||||||
                                       arg3=3, arg4=4)
 | 
					                                       arg3=3, arg4=4)
 | 
				
			||||||
        self.assertTupleEqual(_run(provider()), (1, 2, 3, 4))
 | 
					        self.assertTupleEqual(run(provider()), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_context_args(self):
 | 
					    def test_call_with_context_args(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example, 1, 2)
 | 
					        provider = providers.Coroutine(_example, 1, 2)
 | 
				
			||||||
        self.assertTupleEqual(_run(provider(3, 4)), (1, 2, 3, 4))
 | 
					        self.assertTupleEqual(self._run(provider(3, 4)), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_context_kwargs(self):
 | 
					    def test_call_with_context_kwargs(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example, arg1=1)
 | 
					        provider = providers.Coroutine(_example, arg1=1)
 | 
				
			||||||
        self.assertTupleEqual(
 | 
					        self.assertTupleEqual(
 | 
				
			||||||
            _run(provider(arg2=2, arg3=3, arg4=4)),
 | 
					            self._run(provider(arg2=2, arg3=3, arg4=4)),
 | 
				
			||||||
            (1, 2, 3, 4),
 | 
					            (1, 2, 3, 4),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_with_context_args_and_kwargs(self):
 | 
					    def test_call_with_context_args_and_kwargs(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example, 1)
 | 
					        provider = providers.Coroutine(_example, 1)
 | 
				
			||||||
        self.assertTupleEqual(
 | 
					        self.assertTupleEqual(
 | 
				
			||||||
            _run(provider(2, arg3=3, arg4=4)),
 | 
					            self._run(provider(2, arg3=3, arg4=4)),
 | 
				
			||||||
            (1, 2, 3, 4),
 | 
					            (1, 2, 3, 4),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +117,7 @@ class CoroutineTests(unittest.TestCase):
 | 
				
			||||||
            .add_args(1, 2) \
 | 
					            .add_args(1, 2) \
 | 
				
			||||||
            .add_kwargs(arg3=3, arg4=4)
 | 
					            .add_kwargs(arg3=3, arg4=4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertTupleEqual(_run(provider()), (1, 2, 3, 4))
 | 
					        self.assertTupleEqual(self._run(provider()), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_args(self):
 | 
					    def test_set_args(self):
 | 
				
			||||||
        provider = providers.Coroutine(_example) \
 | 
					        provider = providers.Coroutine(_example) \
 | 
				
			||||||
| 
						 | 
					@ -213,7 +261,7 @@ class DelegatedCoroutineTests(unittest.TestCase):
 | 
				
			||||||
                             hex(id(provider))))
 | 
					                             hex(id(provider))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AbstractCoroutineTests(unittest.TestCase):
 | 
					class AbstractCoroutineTests(AsyncTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_inheritance(self):
 | 
					    def test_inheritance(self):
 | 
				
			||||||
        self.assertIsInstance(providers.AbstractCoroutine(_example),
 | 
					        self.assertIsInstance(providers.AbstractCoroutine(_example),
 | 
				
			||||||
| 
						 | 
					@ -227,7 +275,7 @@ class AbstractCoroutineTests(unittest.TestCase):
 | 
				
			||||||
        provider = providers.AbstractCoroutine(_abstract_example)
 | 
					        provider = providers.AbstractCoroutine(_abstract_example)
 | 
				
			||||||
        provider.override(providers.Coroutine(_example))
 | 
					        provider.override(providers.Coroutine(_example))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertTrue(_run(provider(1, 2, 3, 4)), (1, 2, 3, 4))
 | 
					        self.assertTrue(self._run(provider(1, 2, 3, 4)), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_overridden_by_delegated_coroutine(self):
 | 
					    def test_call_overridden_by_delegated_coroutine(self):
 | 
				
			||||||
        @asyncio.coroutine
 | 
					        @asyncio.coroutine
 | 
				
			||||||
| 
						 | 
					@ -237,7 +285,7 @@ class AbstractCoroutineTests(unittest.TestCase):
 | 
				
			||||||
        provider = providers.AbstractCoroutine(_abstract_example)
 | 
					        provider = providers.AbstractCoroutine(_abstract_example)
 | 
				
			||||||
        provider.override(providers.DelegatedCoroutine(_example))
 | 
					        provider.override(providers.DelegatedCoroutine(_example))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertTrue(_run(provider(1, 2, 3, 4)), (1, 2, 3, 4))
 | 
					        self.assertTrue(self._run(provider(1, 2, 3, 4)), (1, 2, 3, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_not_overridden(self):
 | 
					    def test_call_not_overridden(self):
 | 
				
			||||||
        provider = providers.AbstractCoroutine(_example)
 | 
					        provider = providers.AbstractCoroutine(_example)
 | 
				
			||||||
							
								
								
									
										15
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								tox.ini
									
									
									
									
									
								
							| 
						 | 
					@ -8,12 +8,13 @@ deps=
 | 
				
			||||||
extras=
 | 
					extras=
 | 
				
			||||||
    yaml
 | 
					    yaml
 | 
				
			||||||
    flask
 | 
					    flask
 | 
				
			||||||
 | 
					    aiohttp
 | 
				
			||||||
commands=
 | 
					commands=
 | 
				
			||||||
    unit2 discover -s tests/unit -p test_*_py3.py
 | 
					    unit2 discover -s tests/unit -p test_*_py3*.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:coveralls]
 | 
					[testenv:coveralls]
 | 
				
			||||||
passenv=TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH DEPENDENCY_INJECTOR_DEBUG_MODE
 | 
					passenv=TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH DEPENDENCY_INJECTOR_DEBUG_MODE
 | 
				
			||||||
basepython=python3.6
 | 
					basepython=python3.8
 | 
				
			||||||
usedevelop=True
 | 
					usedevelop=True
 | 
				
			||||||
deps=
 | 
					deps=
 | 
				
			||||||
    {[testenv]deps}
 | 
					    {[testenv]deps}
 | 
				
			||||||
| 
						 | 
					@ -22,19 +23,27 @@ deps=
 | 
				
			||||||
    coveralls
 | 
					    coveralls
 | 
				
			||||||
commands=
 | 
					commands=
 | 
				
			||||||
    coverage erase
 | 
					    coverage erase
 | 
				
			||||||
    coverage run --rcfile=./.coveragerc -m unittest2 discover -s tests/unit/ -p test_*_py3.py
 | 
					    coverage run --rcfile=./.coveragerc -m unittest2 discover -s tests/unit/ -p test_*_py3*.py
 | 
				
			||||||
    coverage report --rcfile=./.coveragerc
 | 
					    coverage report --rcfile=./.coveragerc
 | 
				
			||||||
    coveralls
 | 
					    coveralls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:py27]
 | 
					[testenv:py27]
 | 
				
			||||||
 | 
					extras=
 | 
				
			||||||
 | 
					    yaml
 | 
				
			||||||
 | 
					    flask
 | 
				
			||||||
commands=
 | 
					commands=
 | 
				
			||||||
    unit2 discover -s tests/unit -p test_*_py2_py3.py
 | 
					    unit2 discover -s tests/unit -p test_*_py2_py3.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:py34]
 | 
					[testenv:py34]
 | 
				
			||||||
 | 
					commands=
 | 
				
			||||||
 | 
					    unit2 discover -s tests/unit -p test_*_py3.py
 | 
				
			||||||
extras=
 | 
					extras=
 | 
				
			||||||
    flask
 | 
					    flask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:pypy]
 | 
					[testenv:pypy]
 | 
				
			||||||
 | 
					extras=
 | 
				
			||||||
 | 
					    yaml
 | 
				
			||||||
 | 
					    flask
 | 
				
			||||||
commands=
 | 
					commands=
 | 
				
			||||||
    unit2 discover -s tests/unit -p test_*_py2_py3.py
 | 
					    unit2 discover -s tests/unit -p test_*_py2_py3.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user