diff --git a/examples/miniapps/giphynav-aiohttp/README.rst b/examples/miniapps/giphynav-aiohttp/README.rst new file mode 100644 index 00000000..e69de29b diff --git a/examples/miniapps/giphynav-aiohttp/config.yml b/examples/miniapps/giphynav-aiohttp/config.yml new file mode 100644 index 00000000..e1a0a14b --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/config.yml @@ -0,0 +1,5 @@ +giphy: + request_timeout: 10 +search: + default_query: "Dependency Injector" + default_limit: 10 diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/__init__.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/__init__.py new file mode 100644 index 00000000..1c744ca5 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/__init__.py @@ -0,0 +1 @@ +"""Top-level package.""" diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/__main__.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/__main__.py new file mode 100644 index 00000000..3ef0e377 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/__main__.py @@ -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) diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/application.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/application.py new file mode 100644 index 00000000..0a9b0e70 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/application.py @@ -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 diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/containers.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/containers.py new file mode 100644 index 00000000..c7ee8af3 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/containers.py @@ -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, + ) diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/giphy.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/giphy.py new file mode 100644 index 00000000..2b3871ba --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/giphy.py @@ -0,0 +1,28 @@ +"""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): + 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() diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/services.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/services.py new file mode 100644 index 00000000..8b704350 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/services.py @@ -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): + if not query: + return [] + + result = await self._giphy_client.search(query, limit) + print(result.keys()) + + return [{'url': gif['url']} for gif in result['data']] diff --git a/examples/miniapps/giphynav-aiohttp/giphynavigator/views.py b/examples/miniapps/giphynav-aiohttp/giphynavigator/views.py new file mode 100644 index 00000000..cd621466 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/giphynavigator/views.py @@ -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 = request.query.get('limit', default_limit) + + gifs = await search_service.search(query, limit) + + return web.json_response( + { + 'query': query, + 'limit': limit, + 'gifs': gifs, + }, + ) diff --git a/examples/miniapps/giphynav-aiohttp/requirements.txt b/examples/miniapps/giphynav-aiohttp/requirements.txt new file mode 100644 index 00000000..72b0cc92 --- /dev/null +++ b/examples/miniapps/giphynav-aiohttp/requirements.txt @@ -0,0 +1,4 @@ +dependency-injector +aiohttp +aiohttp-devtools +pyyaml