Skip to content

Commit

Permalink
#1182 get rid of @asyncio.coroutine (deprecated in Python 3.8) (#1186)
Browse files Browse the repository at this point in the history
Signed-off-by: Sławomir Zborowski <[email protected]>
  • Loading branch information
szborows authored Apr 25, 2020
1 parent aafc80a commit bed4b95
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 107 deletions.
32 changes: 12 additions & 20 deletions connexion/apis/aiohttp_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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 + '/'
)
Expand All @@ -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)
Expand All @@ -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',
Expand Down Expand Up @@ -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
Expand All @@ -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(),
Expand All @@ -320,16 +313,15 @@ 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
:type response: aiohttp.web.StreamResponse | (Any,) | (Any, int) | (Any, dict) | (Any, int, dict)
:rtype: aiohttp.web.Response
"""
while asyncio.iscoroutine(response):
response = yield from response
response = await response

url = str(request.url) if request else ''

Expand Down
4 changes: 1 addition & 3 deletions examples/openapi3/helloworld_aiohttp/hello.py
Original file line number Diff line number Diff line change
@@ -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))


Expand Down
84 changes: 33 additions & 51 deletions tests/aiohttp/test_get_response.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import json

import pytest
Expand All @@ -13,95 +12,85 @@ 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'
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_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'
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_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'
assert response.content_type == 'text/plain'
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'
assert response.content_type == 'text/plain'
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'
assert response.content_type == 'text/plain'
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'
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_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'
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_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
Expand All @@ -111,48 +100,43 @@ 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"}
assert response.content_type == 'application/json'
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
assert response.content_type == 'application/json'
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"}
assert response.content_type == 'application/json'
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"}'
assert response.content_type == 'application/octet-stream'
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
Expand All @@ -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
Expand All @@ -171,17 +154,16 @@ 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
assert response.body == b'foo'
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
Expand Down
Loading

0 comments on commit bed4b95

Please sign in to comment.