Skip to content

Commit

Permalink
Renamed Api classes to API;
Browse files Browse the repository at this point in the history
Documented some AbstractAPI and AbstractApp methods;
Added parameters on some abstract methods;
Removed useless code from ResponseValidator;
Created a wrapper for api.jsonifier.loads on Operation class;
Merged with master.
  • Loading branch information
dutradda committed Mar 14, 2017
1 parent a472d52 commit 2699c36
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 33 deletions.
2 changes: 1 addition & 1 deletion connexion/__init__.py
@@ -1,6 +1,6 @@
import werkzeug.exceptions as exceptions # NOQA
from .apps import AbstractApp, FlaskApp # NOQA
from .apis import AbstractApi, FlaskApi # NOQA
from .apis import AbstractAPI, FlaskApi # NOQA
from .exceptions import ProblemException # NOQA
from .problem import problem # NOQA
from .decorators.produces import NoContent # NOQA
Expand Down
2 changes: 1 addition & 1 deletion connexion/apis/__init__.py
Expand Up @@ -5,5 +5,5 @@ def canonical_base_url(base_path):
"""
return base_path.rstrip('/')

from .abstract import AbstractApi
from .abstract import AbstractAPI
from .flask_api import FlaskApi
41 changes: 30 additions & 11 deletions connexion/apis/abstract.py
Expand Up @@ -47,9 +47,9 @@ def compatibility_layer(spec):


@six.add_metaclass(abc.ABCMeta)
class AbstractApi(object):
class AbstractAPI(object):
"""
Single Abstract API
Defines an abstract interface for a Swagger API
"""

def __init__(self, specification, jsonifier, base_url=None, arguments=None,
Expand Down Expand Up @@ -153,15 +153,21 @@ def _set_base_url(self, base_url):

@abc.abstractmethod
def add_swagger_json(self):
""""""
"""
Adds swagger json to {base_url}/swagger.json
"""

@abc.abstractmethod
def add_swagger_ui(self):
""""""
"""
Adds swagger ui to {base_url}/ui/
"""

@abc.abstractmethod
def add_auth_on_not_found(self, security, security_definitions):
""""""
"""
Adds a 404 error handler to authenticate and only expose the 404 status if the security validation pass.
"""

def add_operation(self, method, path, swagger_operation, path_parameters):
"""
Expand Down Expand Up @@ -199,8 +205,11 @@ def add_operation(self, method, path, swagger_operation, path_parameters):
self._add_operation_internal(method, path, operation)

@abc.abstractmethod
def _add_operation_internal(self):
""""""
def _add_operation_internal(self, method, path, operation):
"""
Adds the operation according to the user framework in use.
It will be used to register the operation on the user framework router.
"""

def _add_resolver_error_handler(self, method, path, err):
"""
Expand Down Expand Up @@ -280,10 +289,20 @@ def load_spec_from_file(self, arguments, specification):

@classmethod
@abc.abstractmethod
def get_request(self):
""""""
def get_request(self, *args, **kwargs):
"""
This method converts the user framework request to a ConnexionRequest.
"""

@classmethod
@abc.abstractmethod
def get_response(self):
""""""
def get_response(self, response, mimetype=None, request=None):
"""
This method converts the ConnexionResponse to a user framework response.
:param response: A response to cast.
:param mimetype: The response mimetype.
:param request: The request associated with this response (the user framework request).
:type response: ConnexionResponse
:type mimetype: str
"""
6 changes: 3 additions & 3 deletions connexion/apis/flask_api.py
@@ -1,16 +1,16 @@
import logging
import functools

import connexion.flask_utils as flask_utils
import flask
import werkzeug.exceptions
import six
from connexion.handlers import AuthErrorHandler
from connexion.apis.abstract import AbstractApi
from connexion.apis.abstract import AbstractAPI
from connexion.response import ConnexionResponse
from connexion.request import ConnexionRequest
from connexion.decorators.produces import BaseSerializer, NoContent
from connexion.utils import is_json_mimetype
from connexion import flask_utils

logger = logging.getLogger('connexion.apis.flask_api')

Expand Down Expand Up @@ -44,7 +44,7 @@ def __repr__(self):
return '<Jsonifier: {}>'.format(self.mimetype)


class FlaskApi(AbstractApi):
class FlaskApi(AbstractAPI):
jsonifier = Jsonifier

def __init__(self, specification, base_url=None, arguments=None,
Expand Down
28 changes: 23 additions & 5 deletions connexion/apps/abstract.py
Expand Up @@ -76,15 +76,21 @@ def __init__(self, import_name, api_cls, port=None, specification_dir='',

@abc.abstractmethod
def create_app(self):
""""""
"""
Creates the user framework application
"""

@abc.abstractmethod
def get_root_path(self):
""""""
"""
Gets the root path of the user framework application
"""

@abc.abstractmethod
def set_errors_handlers(self):
""""""
"""
Sets all errors handlers of the user framework application
"""

def add_api(self, specification, base_path=None, arguments=None,
auth_all_paths=None, swagger_json=None, swagger_ui=None,
Expand Down Expand Up @@ -118,7 +124,7 @@ def add_api(self, specification, base_path=None, arguments=None,
:param resolver_error: If specified, turns ResolverError into error
responses with the given status code.
:type resolver_error: int | None
:rtype: AbstractApi
:rtype: AbstractAPI
"""
# Turn the resolver_error code into a handler object
self.resolver_error = resolver_error
Expand Down Expand Up @@ -231,7 +237,19 @@ def index():

@abc.abstractmethod
def run(self, port=None, server=None, debug=None, host=None, **options): # pragma: no cover
""""""
"""
Runs the application on a local development server.
:param host: the host interface to bind on.
:type host: str
:param port: port to listen to
:type port: int
:param server: which wsgi server to use
:type server: str | None
:param debug: include debugging information
:type debug: bool
:param options: options to be forwarded to the underlying server
:type options: dict
"""

def __call__(self, environ, start_response): # pragma: no cover
"""
Expand Down
12 changes: 2 additions & 10 deletions connexion/decorators/response.py
Expand Up @@ -41,11 +41,7 @@ def validate_response(self, data, status_code, headers, url):
schema = response_definition.get("schema")
v = ResponseBodyValidator(schema)
try:
# For cases of custom encoders, we need to encode and decode to
# transform to the actual types that are going to be returned.
data = data.replace(b'\\"', b'"')
data = self.operation.api.jsonifier.loads(data)

data = self.operation.json_loads(data)
v.validate_schema(data, url)
except ValidationError as e:
raise NonConformingResponseBody(message=str(e))
Expand Down Expand Up @@ -92,11 +88,7 @@ def wrapper(request):
response.get_data(), response.status_code,
response.headers, request.url)

except NonConformingResponseBody as e:
response = problem(500, e.reason, e.message)
return self.operation.api.get_response(response)

except NonConformingResponseHeaders as e:
except (NonConformingResponseBody, NonConformingResponseHeaders) as e:
response = problem(500, e.reason, e.message)
return self.operation.api.get_response(response)

Expand Down
8 changes: 8 additions & 0 deletions connexion/operation.py
Expand Up @@ -445,3 +445,11 @@ def __response_validation_decorator(self):
"""
ResponseValidator = self.validator_map['response']
return ResponseValidator(self, self.get_mimetype())

def json_loads(self, data):
"""
A Wrapper for calling the jsonifier.
:param data: The json to loads
:type data: bytes
"""
return self.api.jsonifier.loads(data)
4 changes: 2 additions & 2 deletions tests/test_flask_encoder.py
Expand Up @@ -17,10 +17,10 @@ def test_json_encoder():
s = json.dumps(datetime.datetime.utcnow(), cls=FlaskJSONEncoder)
assert s.endswith('Z"')

s = json.dumps(Decimal(1.01), cls=JSONEncoder)
s = json.dumps(Decimal(1.01), cls=FlaskJSONEncoder)
assert s == '1.01'

s = json.dumps(math.expm1(1e-10), cls=JSONEncoder)
s = json.dumps(math.expm1(1e-10), cls=FlaskJSONEncoder)
assert s == '1.00000000005e-10'


Expand Down

0 comments on commit 2699c36

Please sign in to comment.