diff --git a/connexion/apis/aiohttp_api.py b/connexion/apis/aiohttp_api.py index 0d5d83c27..de3f37c76 100644 --- a/connexion/apis/aiohttp_api.py +++ b/connexion/apis/aiohttp_api.py @@ -44,10 +44,9 @@ def _generic_problem(http_status: HTTPStatus, exc: Exception = None): @web.middleware -@asyncio.coroutine -def problems_middleware(request, handler): +async def problems_middleware(request, handler): try: - response = yield from handler(request) + response = await handler(request) except ProblemException as exc: response = problem(status=exc.status, detail=exc.detail, title=exc.title, type=exc.type, instance=exc.instance, headers=exc.headers, ext=exc.ext) @@ -75,7 +74,7 @@ def problems_middleware(request, handler): response = _generic_problem(HTTPStatus.INTERNAL_SERVER_ERROR, exc) if isinstance(response, ConnexionResponse): - response = yield from AioHttpApi.get_response(response) + response = await AioHttpApi.get_response(response) return response @@ -165,16 +164,14 @@ def add_openapi_yaml(self): self._get_openapi_yaml ) - @asyncio.coroutine - def _get_openapi_json(self, request): + async def _get_openapi_json(self, request): return web.Response( status=200, content_type='application/json', body=self.jsonifier.dumps(self._spec_for_prefix(request)) ) - @asyncio.coroutine - def _get_openapi_yaml(self, request): + async def _get_openapi_yaml(self, request): return web.Response( status=200, content_type='text/yaml', @@ -211,8 +208,7 @@ def add_swagger_ui(self): # normalize_path_middleware because we also serve static files # from this dir (below) - @asyncio.coroutine - def redirect(request): + async def redirect(request): raise web.HTTPMovedPermanently( location=self.base_path + console_ui_path + '/' ) @@ -232,8 +228,7 @@ def redirect(request): ) @aiohttp_jinja2.template('index.j2') - @asyncio.coroutine - def _get_swagger_ui_home(self, req): + async def _get_swagger_ui_home(self, req): base_path = self._base_path_for_prefix(req) template_variables = { 'openapi_spec_url': (base_path + self.options.openapi_spec_path) @@ -242,8 +237,7 @@ def _get_swagger_ui_home(self, req): template_variables['configUrl'] = 'swagger-ui-config.json' return template_variables - @asyncio.coroutine - def _get_swagger_ui_config(self, req): + async def _get_swagger_ui_config(self, req): return web.Response( status=200, content_type='text/json', @@ -291,8 +285,7 @@ def _add_operation_internal(self, method, path, operation): ) @classmethod - @asyncio.coroutine - def get_request(cls, req): + async def get_request(cls, req): """Convert aiohttp request to connexion :param req: instance of aiohttp.web.Request @@ -307,7 +300,7 @@ def get_request(cls, req): headers = req.headers body = None if req.body_exists: - body = yield from req.read() + body = await req.read() return ConnexionRequest(url=url, method=req.method.lower(), @@ -320,8 +313,7 @@ def get_request(cls, req): context=req) @classmethod - @asyncio.coroutine - def get_response(cls, response, mimetype=None, request=None): + async def get_response(cls, response, mimetype=None, request=None): """Get response. This method is used in the lifecycle decorators @@ -329,7 +321,7 @@ def get_response(cls, response, mimetype=None, request=None): :rtype: aiohttp.web.Response """ while asyncio.iscoroutine(response): - response = yield from response + response = await response url = str(request.url) if request else '' diff --git a/examples/openapi3/helloworld_aiohttp/hello.py b/examples/openapi3/helloworld_aiohttp/hello.py index 37f63f9b3..1453928ca 100755 --- a/examples/openapi3/helloworld_aiohttp/hello.py +++ b/examples/openapi3/helloworld_aiohttp/hello.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import asyncio import connexion from aiohttp import web -@asyncio.coroutine -def post_greeting(name): +async def post_greeting(name): return web.Response(text='Hello {name}'.format(name=name)) diff --git a/tests/aiohttp/test_get_response.py b/tests/aiohttp/test_get_response.py index 5fbe839e0..5a3aa9a04 100644 --- a/tests/aiohttp/test_get_response.py +++ b/tests/aiohttp/test_get_response.py @@ -1,4 +1,3 @@ -import asyncio import json import pytest @@ -13,9 +12,8 @@ def api(aiohttp_api_spec_dir): yield AioHttpApi(specification=aiohttp_api_spec_dir / 'swagger_secure.yaml') -@asyncio.coroutine -def test_get_response_from_aiohttp_response(api): - response = yield from api.get_response(web.Response(text='foo', status=201, headers={'X-header': 'value'})) +async def test_get_response_from_aiohttp_response(api): + response = await api.get_response(web.Response(text='foo', status=201, headers={'X-header': 'value'})) assert isinstance(response, web.Response) assert response.status == 201 assert response.body == b'foo' @@ -23,18 +21,16 @@ def test_get_response_from_aiohttp_response(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_response_from_aiohttp_stream_response(api): - response = yield from api.get_response(web.StreamResponse(status=201, headers={'X-header': 'value'})) +async def test_get_response_from_aiohttp_stream_response(api): + response = await api.get_response(web.StreamResponse(status=201, headers={'X-header': 'value'})) assert isinstance(response, web.StreamResponse) assert response.status == 201 assert response.content_type == 'application/octet-stream' assert dict(response.headers) == {'X-header': 'value'} -@asyncio.coroutine -def test_get_response_from_connexion_response(api): - response = yield from api.get_response(ConnexionResponse(status_code=201, mimetype='text/plain', body='foo', headers={'X-header': 'value'})) +async def test_get_response_from_connexion_response(api): + response = await api.get_response(ConnexionResponse(status_code=201, mimetype='text/plain', body='foo', headers={'X-header': 'value'})) assert isinstance(response, web.Response) assert response.status == 201 assert response.body == b'foo' @@ -42,9 +38,8 @@ def test_get_response_from_connexion_response(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_response_from_string(api): - response = yield from api.get_response('foo') +async def test_get_response_from_string(api): + response = await api.get_response('foo') assert isinstance(response, web.Response) assert response.status == 200 assert response.body == b'foo' @@ -52,9 +47,8 @@ def test_get_response_from_string(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8'} -@asyncio.coroutine -def test_get_response_from_string_tuple(api): - response = yield from api.get_response(('foo',)) +async def test_get_response_from_string_tuple(api): + response = await api.get_response(('foo',)) assert isinstance(response, web.Response) assert response.status == 200 assert response.body == b'foo' @@ -62,9 +56,8 @@ def test_get_response_from_string_tuple(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8'} -@asyncio.coroutine -def test_get_response_from_string_status(api): - response = yield from api.get_response(('foo', 201)) +async def test_get_response_from_string_status(api): + response = await api.get_response(('foo', 201)) assert isinstance(response, web.Response) assert response.status == 201 assert response.body == b'foo' @@ -72,9 +65,8 @@ def test_get_response_from_string_status(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8'} -@asyncio.coroutine -def test_get_response_from_string_headers(api): - response = yield from api.get_response(('foo', {'X-header': 'value'})) +async def test_get_response_from_string_headers(api): + response = await api.get_response(('foo', {'X-header': 'value'})) assert isinstance(response, web.Response) assert response.status == 200 assert response.body == b'foo' @@ -82,9 +74,8 @@ def test_get_response_from_string_headers(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_response_from_string_status_headers(api): - response = yield from api.get_response(('foo', 201, {'X-header': 'value'})) +async def test_get_response_from_string_status_headers(api): + response = await api.get_response(('foo', 201, {'X-header': 'value'})) assert isinstance(response, web.Response) assert response.status == 201 assert response.body == b'foo' @@ -92,16 +83,14 @@ def test_get_response_from_string_status_headers(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_response_from_tuple_error(api): +async def test_get_response_from_tuple_error(api): with pytest.raises(TypeError) as e: - yield from api.get_response((web.Response(text='foo', status=201, headers={'X-header': 'value'}), 200)) + await api.get_response((web.Response(text='foo', status=201, headers={'X-header': 'value'}), 200)) assert str(e.value) == "Cannot return web.StreamResponse in tuple. Only raw data can be returned in tuple." -@asyncio.coroutine -def test_get_response_from_dict(api): - response = yield from api.get_response({'foo': 'bar'}) +async def test_get_response_from_dict(api): + response = await api.get_response({'foo': 'bar'}) assert isinstance(response, web.Response) assert response.status == 200 # odd, yes. but backwards compatible. see test_response_with_non_str_and_non_json_body in tests/aiohttp/test_aiohttp_simple_api.py @@ -111,9 +100,8 @@ def test_get_response_from_dict(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8'} -@asyncio.coroutine -def test_get_response_from_dict_json(api): - response = yield from api.get_response({'foo': 'bar'}, mimetype='application/json') +async def test_get_response_from_dict_json(api): + response = await api.get_response({'foo': 'bar'}, mimetype='application/json') assert isinstance(response, web.Response) assert response.status == 200 assert json.loads(response.body.decode()) == {"foo": "bar"} @@ -121,9 +109,8 @@ def test_get_response_from_dict_json(api): assert dict(response.headers) == {'Content-Type': 'application/json; charset=utf-8'} -@asyncio.coroutine -def test_get_response_no_data(api): - response = yield from api.get_response(None, mimetype='application/json') +async def test_get_response_no_data(api): + response = await api.get_response(None, mimetype='application/json') assert isinstance(response, web.Response) assert response.status == 204 assert response.body is None @@ -131,9 +118,8 @@ def test_get_response_no_data(api): assert dict(response.headers) == {'Content-Type': 'application/json'} -@asyncio.coroutine -def test_get_response_binary_json(api): - response = yield from api.get_response(b'{"foo":"bar"}', mimetype='application/json') +async def test_get_response_binary_json(api): + response = await api.get_response(b'{"foo":"bar"}', mimetype='application/json') assert isinstance(response, web.Response) assert response.status == 200 assert json.loads(response.body.decode()) == {"foo": "bar"} @@ -141,9 +127,8 @@ def test_get_response_binary_json(api): assert dict(response.headers) == {'Content-Type': 'application/json'} -@asyncio.coroutine -def test_get_response_binary_no_mimetype(api): - response = yield from api.get_response(b'{"foo":"bar"}') +async def test_get_response_binary_no_mimetype(api): + response = await api.get_response(b'{"foo":"bar"}') assert isinstance(response, web.Response) assert response.status == 200 assert response.body == b'{"foo":"bar"}' @@ -151,8 +136,7 @@ def test_get_response_binary_no_mimetype(api): assert dict(response.headers) == {} -@asyncio.coroutine -def test_get_connexion_response_from_aiohttp_response(api): +async def test_get_connexion_response_from_aiohttp_response(api): response = api.get_connexion_response(web.Response(text='foo', status=201, headers={'X-header': 'value'})) assert isinstance(response, ConnexionResponse) assert response.status_code == 201 @@ -161,8 +145,7 @@ def test_get_connexion_response_from_aiohttp_response(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_connexion_response_from_connexion_response(api): +async def test_get_connexion_response_from_connexion_response(api): response = api.get_connexion_response(ConnexionResponse(status_code=201, content_type='text/plain', body='foo', headers={'X-header': 'value'})) assert isinstance(response, ConnexionResponse) assert response.status_code == 201 @@ -171,8 +154,7 @@ def test_get_connexion_response_from_connexion_response(api): assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_connexion_response_from_tuple(api): +async def test_get_connexion_response_from_tuple(api): response = api.get_connexion_response(('foo', 201, {'X-header': 'value'})) assert isinstance(response, ConnexionResponse) assert response.status_code == 201 @@ -180,8 +162,8 @@ def test_get_connexion_response_from_tuple(api): assert response.content_type == 'text/plain' assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'} -@asyncio.coroutine -def test_get_connexion_response_from_aiohttp_stream_response(api): + +async def test_get_connexion_response_from_aiohttp_stream_response(api): response = api.get_connexion_response(web.StreamResponse(status=201, headers={'X-header': 'value'})) assert isinstance(response, ConnexionResponse) assert response.status_code == 201 diff --git a/tests/fakeapi/aiohttp_handlers.py b/tests/fakeapi/aiohttp_handlers.py index dbb99daea..d1302e466 100755 --- a/tests/fakeapi/aiohttp_handlers.py +++ b/tests/fakeapi/aiohttp_handlers.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -import asyncio import datetime import uuid @@ -9,60 +8,49 @@ from connexion.lifecycle import ConnexionResponse -@asyncio.coroutine -def get_bye(name): +async def get_bye(name): return AioHttpResponse(text='Goodbye {}'.format(name)) -@asyncio.coroutine -def aiohttp_str_response(): +async def aiohttp_str_response(): return 'str response' -@asyncio.coroutine -def aiohttp_non_str_non_json_response(): +async def aiohttp_non_str_non_json_response(): return 1234 -@asyncio.coroutine -def aiohttp_bytes_response(): +async def aiohttp_bytes_response(): return b'bytes response' -@asyncio.coroutine -def aiohttp_validate_responses(): +async def aiohttp_validate_responses(): return {"validate": True} -@asyncio.coroutine -def aiohttp_post_greeting(name, **kwargs): +async def aiohttp_post_greeting(name, **kwargs): data = {'greeting': 'Hello {name}'.format(name=name)} return data -@asyncio.coroutine -def aiohttp_echo(**kwargs): +async def aiohttp_echo(**kwargs): return aiohttp.web.json_response(data=kwargs, status=200) -@asyncio.coroutine -def aiohttp_access_request_context(request_ctx): +async def aiohttp_access_request_context(request_ctx): assert request_ctx is not None assert isinstance(request_ctx, aiohttp.web.Request) return None -@asyncio.coroutine -def aiohttp_query_parsing_str(query): +async def aiohttp_query_parsing_str(query): return {'query': query} -@asyncio.coroutine -def aiohttp_query_parsing_array(query): +async def aiohttp_query_parsing_array(query): return {'query': query} -@asyncio.coroutine -def aiohttp_query_parsing_array_multi(query): +async def aiohttp_query_parsing_array_multi(query): return {'query': query} @@ -72,13 +60,11 @@ def aiohttp_query_parsing_array_multi(query): ] -@asyncio.coroutine -def aiohttp_users_get(*args): +async def aiohttp_users_get(*args): return aiohttp.web.json_response(data=USERS, status=200) -@asyncio.coroutine -def aiohttp_users_post(user): +async def aiohttp_users_post(user): if "name" not in user: return ConnexionResponse(body={"error": "name is undefined"}, status_code=400, @@ -88,16 +74,13 @@ def aiohttp_users_post(user): return aiohttp.web.json_response(data=USERS[-1], status=201) -@asyncio.coroutine -def get_datetime(): +async def get_datetime(): return ConnexionResponse(body={'value': datetime.datetime(2000, 1, 2, 3, 4, 5, 6)}) -@asyncio.coroutine -def get_date(): +async def get_date(): return ConnexionResponse(body={'value': datetime.date(2000, 1, 2)}) -@asyncio.coroutine -def get_uuid(): +async def get_uuid(): return ConnexionResponse(body={'value': uuid.UUID(hex='e7ff66d0-3ec2-4c4e-bed0-6e4723c24c51')})