Skip to content

Commit

Permalink
Merge branch 'master' into dev-2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dtkav committed Sep 20, 2018
2 parents 08fa18f + 7e8435a commit b4a794c
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,6 @@ Unless required by applicable law or agreed to in writing, software distributed
.. _described by Flask: http://flask.pocoo.org/snippets/111/
.. _werkzeug: http://werkzeug.pocoo.org/
.. _Connexion's Documentation Page: http://connexion.readthedocs.org/en/latest/
.. _Crafting effective Microservices in Python: http://caricio.com/2016/09/16/crafting-effective-microservices-in-python/
.. _Crafting effective Microservices in Python: https://jobs.zalando.com/tech/blog/crafting-effective-microservices-in-python/
.. _issues where we are looking for contributions: https://github.com/zalando/connexion/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
.. _HTTP Methods work in Flask: http://flask.pocoo.org/docs/1.0/quickstart/#http-methods
3 changes: 2 additions & 1 deletion connexion/decorators/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import sys

import six
from jsonschema import Draft4Validator, ValidationError, draft4_format_checker
from jsonschema import (Draft4Validator, ValidationError,
draft4_format_checker)
from werkzeug import FileStorage

from ..exceptions import ExtraParameterProblem
Expand Down
18 changes: 16 additions & 2 deletions connexion/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,30 @@ def loads(self, data):


def has_coroutine(function, api=None):
"""
Checks if function is a couroutine.
If ``function`` is a decorator (has a ``__wrapped__`` attribute)
this function will also look at the wrapped function.
"""
if six.PY3: # pragma: 2.7 no cover
import asyncio

def iscorofunc(func):
iscorofunc = asyncio.iscoroutinefunction(func)
while not iscorofunc and hasattr(func, '__wrapped__'):
func = func.__wrapped__
iscorofunc = asyncio.iscoroutinefunction(func)
return iscorofunc

if api is None:
return asyncio.iscoroutinefunction(function)
return iscorofunc(function)

else:
return any(
asyncio.iscoroutinefunction(func) for func in (
iscorofunc(func) for func in (
function, api.get_request, api.get_response
)
)
else: # pragma: 3 no cover
# there's no asyncio in python 2
return False
5 changes: 5 additions & 0 deletions docs/routing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ If you provided this path in your specification POST requests to
x-swagger-router-controller: myapp.api
operationId: hello_world
Keep in mind that Connexion follows how `HTTP methods work in Flask`_ and therefore HEAD requests will be handled by the ``operationId`` specified under GET in the specification. If both methods are supported, ``connexion.request.method`` can be used to determine which request was made.

Automatic Routing
-----------------

Expand Down Expand Up @@ -157,3 +159,6 @@ You can also disable it at the API level:
app = connexion.FlaskApp(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml', swagger_json=False)
.. _Operation Object: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object
.. _HTTP Methods work in Flask: http://flask.pocoo.org/docs/1.0/quickstart/#http-methods
19 changes: 19 additions & 0 deletions tests/aiohttp/test_aiohttp_simple_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import sys

import aiohttp.web
import pytest
Expand Down Expand Up @@ -226,3 +227,21 @@ def test_access_request_context(test_client, aiohttp_app):
app_client = yield from test_client(aiohttp_app.app)
resp = yield from app_client.post('/v1.0/aiohttp_access_request_context')
assert resp.status == 204


if sys.version_info[0:2] >= (3, 5):
@pytest.fixture
def aiohttp_app_async_def(aiohttp_api_spec_dir):
app = AioHttpApp(__name__, port=5001,
specification_dir=aiohttp_api_spec_dir,
debug=True)
app.add_api('swagger_simple_async_def.yaml', validate_responses=True)
return app


@asyncio.coroutine
def test_validate_responses_async_def(aiohttp_app_async_def, test_client):
app_client = yield from test_client(aiohttp_app_async_def.app)
get_bye = yield from app_client.get('/v1.0/aiohttp_validate_responses')
assert get_bye.status == 200
assert (yield from get_bye.read()) == b'{"validate": true}'
5 changes: 5 additions & 0 deletions tests/fakeapi/aiohttp_handlers_async_def.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from connexion.lifecycle import ConnexionResponse


async def aiohttp_validate_responses():
return ConnexionResponse(body=b'{"validate": true}')
21 changes: 21 additions & 0 deletions tests/fixtures/aiohttp/swagger_simple_async_def.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
swagger: "2.0"

info:
title: "{{title}}"
version: "1.0"

basePath: /v1.0

paths:
/aiohttp_validate_responses:
get:
summary: Return a bytes response
description: Test returning a bytes response
operationId: fakeapi.aiohttp_handlers_async_def.aiohttp_validate_responses
produces:
- application/json
responses:
200:
description: json response
schema:
type: object

0 comments on commit b4a794c

Please sign in to comment.