Ejemplo n.º 1
0
def wsexpose(*args, **kwargs):
    pecan_json_decorate = pecan.expose(
        template='wsmejson:',
        content_type='application/json',
        generic=False)
    pecan_xml_decorate = pecan.expose(
        template='wsmexml:',
        content_type='application/xml',
        generic=False
    )
    sig = wsme.signature(*args, **kwargs)

    def decorate(f):
        sig(f)
        funcdef = wsme.api.FunctionDefinition.get(f)
        funcdef.resolve_types(wsme.types.registry)

        @functools.wraps(f)
        def callfunction(self, *args, **kwargs):
            try:
                args, kwargs = wsme.rest.args.get_args(
                    funcdef, args, kwargs, pecan.request.params, None,
                    pecan.request.body, pecan.request.content_type
                )
                if funcdef.pass_request:
                    kwargs[funcdef.pass_request] = pecan.request
                result = f(self, *args, **kwargs)

                # NOTE: Support setting of status_code with default 201
                pecan.response.status = funcdef.status_code
                if isinstance(result, wsme.api.Response):
                    pecan.response.status = result.status_code
                    result = result.obj

            except Exception:
                raise
                data = wsme.api.format_exception(
                    sys.exc_info(),
                    pecan.conf.get('wsme', {}).get('debug', False)
                )
                if data['faultcode'] == 'Client':
                    pecan.response.status = 400
                else:
                    pecan.response.status = 500
                return data

            return dict(
                datatype=funcdef.return_type,
                result=result
            )

        pecan_xml_decorate(callfunction)
        pecan_json_decorate(callfunction)
        pecan.util._cfg(callfunction)['argspec'] = inspect.getargspec(f)
        callfunction._wsme_definition = funcdef
        return callfunction

    return decorate
Ejemplo n.º 2
0
def wsexpose(*args, **kwargs):
    pecan_json_decorate = pecan.expose(template='wsmejson:',
                                       content_type='application/json',
                                       generic=False)
    pecan_xml_decorate = pecan.expose(template='wsmexml:',
                                      content_type='application/xml',
                                      generic=False)
    sig = wsme.signature(*args, **kwargs)

    def decorate(f):
        sig(f)
        funcdef = wsme.api.FunctionDefinition.get(f)
        funcdef.resolve_types(wsme.types.registry)

        @functools.wraps(f)
        def callfunction(self, *args, **kwargs):
            try:
                args, kwargs = wsme.rest.args.get_args(
                    funcdef, args, kwargs, pecan.request.params, None,
                    pecan.request.body, pecan.request.content_type)
                if funcdef.pass_request:
                    kwargs[funcdef.pass_request] = pecan.request
                result = f(self, *args, **kwargs)

                # NOTE: Support setting of status_code with default 201
                pecan.response.status = funcdef.status_code
                if isinstance(result, wsme.api.Response):
                    pecan.response.status = result.status_code
                    result = result.obj

            except Exception:
                raise
                data = wsme.api.format_exception(
                    sys.exc_info(),
                    pecan.conf.get('wsme', {}).get('debug', False))
                if data['faultcode'] == 'Client':
                    pecan.response.status = 400
                else:
                    pecan.response.status = 500
                return data

            return dict(datatype=funcdef.return_type, result=result)

        pecan_xml_decorate(callfunction)
        pecan_json_decorate(callfunction)
        pecan.util._cfg(callfunction)['argspec'] = inspect.getargspec(f)
        callfunction._wsme_definition = funcdef
        return callfunction

    return decorate
Ejemplo n.º 3
0
    def expose(f):
        f = pecan.expose(*vargs, **vkwargs)(f)

        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            return f(*args, body=deserialize(schema), **kwargs)
        return callfunction
Ejemplo n.º 4
0
    def expose(f):
        f = pecan.expose(*vargs, **vkwargs)(f)

        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            params = jsonutils.loads(pecan.request.body)
            try:
                schema(params)
            except voluptuous.Error as e:
                pecan.abort(400, "Invalid input: %s" % e)
            return f(*args, body=params, **kwargs)
        return callfunction
Ejemplo n.º 5
0
    def test_generics_not_allowed(self):

        class C(object):

            def _default(self):
                pass

            def _lookup(self):
                pass

            def _route(self):
                pass

        for method in (C._default, C._lookup, C._route):
            self.assertRaises(
                ValueError,
                expose(generic=True),
                getattr(method, '__func__', method)
            )
Ejemplo n.º 6
0
    def test_generics_not_allowed(self):

        class C(object):

            def _default(self):
                pass

            def _lookup(self):
                pass

            def _route(self):
                pass

        for method in (C._default, C._lookup, C._route):
            self.assertRaises(
                ValueError,
                expose(generic=True),
                getattr(method, '__func__', method)
            )
Ejemplo n.º 7
0
Archivo: base.py Proyecto: Pulsant/st2
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type="application/json", method=None):
    """
    :param arg_types: A list of types for the function arguments (e.g. [str, str, int, bool]).
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    # Late import to avoid very expensive in-direct import (~1 second) when this function
    # is not called / used
    import jsonschema
    import pecan

    from webob import exc

    from st2common.util.jsonify import json_encode
    from st2common.util.api import get_exception_for_type_error
    from st2common.util.api import get_exception_for_uncaught_api_error

    pecan_json_decorate = pecan.expose(content_type=content_type, generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            args = list(args)
            more = [args.pop(0)]

            def cast_value(value_type, value):
                if value_type == bool:

                    def cast_func(value):
                        return value.lower() in ["1", "true"]

                else:
                    cast_func = value_type

                result = cast_func(value)
                return result

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json

                    obj = body_cls(**data)
                    try:
                        obj = obj.validate()
                    except (jsonschema.ValidationError, ValueError) as e:
                        raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc())
                    except Exception as e:
                        raise exc.HTTPInternalServerError(detail=e.message, comment=traceback.format_exc())
                else:
                    obj = None

                more.append(obj)

            if arg_types:
                # Cast and transform arguments based on the provided arg_types specification
                result_args, result_kwargs = get_controller_args_for_types(
                    func=f, arg_types=arg_types, args=args, kwargs=kwargs
                )
                more = more + result_args
                kwargs.update(result_kwargs)

            args = tuple(more) + tuple(args)

            noop_codes = [http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                e = get_exception_for_type_error(func=f, exc=e)
                raise e
            except Exception as e:
                e = get_exception_for_uncaught_api_error(func=f, exc=e)
                raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == "application/json":
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 8
0
Archivo: pecan.py Proyecto: Kjir/wsme
        pass

    @staticmethod
    def render(template_path, namespace):
        if 'faultcode' in namespace:
            return wsme.rest.xml.encode_error(None, namespace)
        return wsme.rest.xml.encode_result(
            namespace['result'],
            namespace['datatype']
        )

pecan.templating._builtin_renderers['wsmejson'] = JSonRenderer
pecan.templating._builtin_renderers['wsmexml'] = XMLRenderer

pecan_json_decorate = pecan.expose(
    template='wsmejson:',
    content_type='application/json',
    generic=False)
pecan_xml_decorate = pecan.expose(
    template='wsmexml:',
    content_type='application/xml',
    generic=False
)
pecan_text_xml_decorate = pecan.expose(
    template='wsmexml:',
    content_type='text/xml',
    generic=False
)


def wsexpose(*args, **kwargs):
    sig = wsme.signature(*args, **kwargs)
Ejemplo n.º 9
0
def expose(*args, **kwargs):
    kwargs.setdefault('content_type', 'application/json')
    kwargs.setdefault('template', 'json')
    return pecan.expose(*args, **kwargs)
Ejemplo n.º 10
0
Archivo: base.py Proyecto: dekoder/st2
def jsexpose(arg_types=None,
             body_cls=None,
             status_code=None,
             content_type='application/json'):
    """
    :param arg_types: A list of types for the function arguments.
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            args = list(args)
            types = copy.copy(arg_types)
            more = [args.pop(0)]

            if types:
                argspec = inspect.getargspec(f)
                names = argspec.args[1:]

                for name in names:
                    try:
                        a = args.pop(0)
                        more.append(types.pop(0)(a))
                    except IndexError:
                        try:
                            kwargs[name] = types.pop(0)(kwargs[name])
                        except IndexError:
                            LOG.warning(
                                "Type definition for '%s' argument of '%s' "
                                "is missing.", name, f.__name__)
                        except KeyError:
                            pass

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json
                else:
                    data = {}

                obj = body_cls(**data)
                try:
                    obj.validate()
                except jsonschema.ValidationError as e:
                    raise exc.HTTPBadRequest(detail=e.message,
                                             comment=traceback.format_exc())
                except Exception as e:
                    raise exc.HTTPInternalServerError(
                        detail=e.message, comment=traceback.format_exc())
                more.append(obj)

            args = tuple(more) + tuple(args)

            noop_codes = [
                http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED,
                http_client.FORBIDDEN
            ]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            result = f(*args, **kwargs)

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                return json_encode(result, indent=None)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 11
0
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type='application/json',
             method=None):
    """
    :param arg_types: A list of types for the function arguments (e.g. [str, str, int, bool]).
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    # Late import to avoid very expensive in-direct import (~1 second) when this function
    # is not called / used
    import jsonschema
    import pecan

    from webob import exc

    from st2common.util.jsonify import json_encode
    from st2common.util.api import get_exception_for_type_error
    from st2common.util.api import get_exception_for_uncaught_api_error

    pecan_json_decorate = pecan.expose(
        content_type=content_type,
        generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            args = list(args)
            more = [args.pop(0)]

            def cast_value(value_type, value):
                if value_type == bool:
                    def cast_func(value):
                        return value.lower() in ['1', 'true']
                else:
                    cast_func = value_type

                result = cast_func(value)
                return result

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json

                    obj = body_cls(**data)
                    try:
                        obj = obj.validate()
                    except (jsonschema.ValidationError, ValueError) as e:
                        raise exc.HTTPBadRequest(detail=e.message,
                                                 comment=traceback.format_exc())
                    except Exception as e:
                        raise exc.HTTPInternalServerError(detail=e.message,
                                                          comment=traceback.format_exc())
                else:
                    obj = None

                more.append(obj)

            if arg_types:
                # Cast and transform arguments based on the provided arg_types specification
                result_args, result_kwargs = get_controller_args_for_types(func=f,
                                                                           arg_types=arg_types,
                                                                           args=args,
                                                                           kwargs=kwargs)
                more = more + result_args
                kwargs.update(result_kwargs)

            args = tuple(more) + tuple(args)

            noop_codes = [http_client.NOT_IMPLEMENTED,
                          http_client.METHOD_NOT_ALLOWED,
                          http_client.FORBIDDEN]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                e = get_exception_for_type_error(func=f, exc=e)
                raise e
            except Exception as e:
                e = get_exception_for_uncaught_api_error(func=f, exc=e)
                raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 12
0
        pass

    @staticmethod
    def render(template_path, namespace):
        if 'faultcode' in namespace:
            return wsme.rest.xml.encode_error(None, namespace)
        return wsme.rest.xml.encode_result(
            namespace['result'],
            namespace['datatype']
        )

pecan.templating._builtin_renderers['wsmejson'] = JSonRenderer
pecan.templating._builtin_renderers['wsmexml'] = XMLRenderer

pecan_json_decorate = pecan.expose(
    template='wsmejson:',
    content_type='application/json',
    generic=False)
pecan_xml_decorate = pecan.expose(
    template='wsmexml:',
    content_type='application/xml',
    generic=False
)
pecan_text_xml_decorate = pecan.expose(
    template='wsmexml:',
    content_type='text/xml',
    generic=False
)


def wsexpose(*args, **kwargs):
    sig = wsme.signature(*args, **kwargs)
Ejemplo n.º 13
0
def jsexpose(arg_types=None,
             body_cls=None,
             status_code=None,
             content_type='application/json'):
    """
    :param arg_types: A list of types for the function arguments.
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            function_name = f.__name__
            args = list(args)
            types = copy.copy(arg_types)
            more = [args.pop(0)]

            if types:
                argspec = inspect.getargspec(f)
                names = argspec.args[1:]

                for name in names:
                    try:
                        a = args.pop(0)
                        more.append(types.pop(0)(a))
                    except IndexError:
                        try:
                            kwargs[name] = types.pop(0)(kwargs[name])
                        except IndexError:
                            LOG.warning(
                                "Type definition for '%s' argument of '%s' "
                                "is missing.", name, f.__name__)
                        except KeyError:
                            pass

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json
                else:
                    data = {}

                obj = body_cls(**data)
                try:
                    obj = obj.validate()
                except (jsonschema.ValidationError, ValueError) as e:
                    raise exc.HTTPBadRequest(detail=e.message,
                                             comment=traceback.format_exc())
                except Exception as e:
                    raise exc.HTTPInternalServerError(
                        detail=e.message, comment=traceback.format_exc())

                # Set default pack if one is not provided for resource create
                if function_name == 'post' and not hasattr(obj, 'pack'):
                    extra = {
                        'resource_api': obj,
                        'default_pack_name': DEFAULT_PACK_NAME
                    }
                    LOG.debug(
                        'Pack not provided in the body, setting a default pack name',
                        extra=extra)
                    setattr(obj, 'pack', DEFAULT_PACK_NAME)

                more.append(obj)

            args = tuple(more) + tuple(args)

            noop_codes = [
                http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED,
                http_client.FORBIDDEN
            ]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                message = str(e)
                # Invalid number of arguments passed to the function meaning invalid path was
                # requested
                # Note: The check is hacky, but it works for now.
                func_name = f.__name__
                pattern = '%s\(\) takes exactly \d+ arguments \(\d+ given\)' % (
                    func_name)

                if re.search(pattern, message):
                    raise exc.HTTPNotFound()
                else:
                    raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 14
0
    def delete(self, nodeid):
        response.status = http_client.NO_CONTENT
        return {'result': 'Call the method named delete', 'id': nodeid}

    @expose(template='json')
    def start(self, nodeid):
        response.status = http_client.ACCEPTED
        return {'result': 'Call the method named start', 'id': nodeid}

    def power_off(self, nodeid):
        response.status = http_client.ACCEPTED
        return {'result': 'Call the method named power_off', 'id': nodeid}


setattr(NodeController, 'power-operate',
        expose(template='json')(
            six.get_method_function(NodeController.power_operate)))


class VersionController(rest.RestController):

    @expose(template='json')
    def _default(self):
        return {'Version': 'v1.0'}


class RootController(rest.RestController):
    node = NodeController()
    version = VersionController()

    @expose()
    def _route(self, args, request):
Ejemplo n.º 15
0
def jsexpose(*argtypes, **opts):
    content_type = opts.get('content_type', 'application/json')

    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            try:
                args = list(args)
                types = list(argtypes)
                more = [args.pop(0)]

                if len(types):
                    argspec = inspect.getargspec(f)
                    names = argspec.args[1:]

                    for name in names:
                        try:
                            a = args.pop(0)
                            more.append(types.pop(0)(a))
                        except IndexError:
                            try:
                                kwargs[name] = types.pop(0)(kwargs[name])
                            except IndexError:
                                LOG.warning(
                                    "Type definition for '%s' argument of '%s' "
                                    "is missing.", name, f.__name__)
                            except KeyError:
                                pass

                body_cls = opts.get('body')
                if body_cls and pecan.request.body:
                    try:
                        obj = body_cls(**pecan.request.json)
                    except jsonschema.exceptions.ValidationError as e:
                        return _handle_error(http_client.BAD_REQUEST, e)
                    more.append(obj)

                args = tuple(more) + tuple(args)

                status_code = opts.get('status_code')

                noop_codes = [
                    http_client.NOT_IMPLEMENTED,
                    http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN
                ]

                if status_code and status_code in noop_codes:
                    pecan.response.status = status_code
                    return json_encode(None)

                try:
                    result = f(*args, **kwargs)
                    if status_code:
                        pecan.response.status = status_code
                    if content_type == 'application/json':
                        return json_encode(result)
                    else:
                        return result
                except exc.HTTPException as e:
                    return _handle_error(e.wsgi_response.status, e)

            except Exception as e:
                return _handle_error(http_client.INTERNAL_SERVER_ERROR, e)

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 16
0
#    License for the specific language governing permissions and limitations
#    under the License.

import functools
from http import client as http_client
import json
import sys
import traceback

from oslo_config import cfg
from oslo_log import log
import pecan

LOG = log.getLogger(__name__)

pecan_json_decorate = pecan.expose(content_type='application/json',
                                   generic=False)


def expose(status_code=None):
    def decorate(f):
        @functools.wraps(f)
        def callfunction(self, *args, **kwargs):
            try:
                result = f(self, *args, **kwargs)
                if status_code:
                    pecan.response.status = status_code

            except Exception:
                try:
                    exception_info = sys.exc_info()
                    orig_exception = exception_info[1]
Ejemplo n.º 17
0
def expose(*args, **kwargs):
    """Helper function so we don't have to specify json for everything."""
    kwargs.setdefault('content_type', 'application/json')
    kwargs.setdefault('template', 'json')
    return pecan.expose(*args, **kwargs)
Ejemplo n.º 18
0
def wsexpose(*args, **kwargs):
    pecan_json_decorate = pecan.expose(
        template='wsmejson:',
        content_type='application/json',
        generic=False)
    pecan_xml_decorate = pecan.expose(
        template='wsmexml:',
        content_type='application/xml',
        generic=False
    )
    pecan_text_xml_decorate = pecan.expose(
        template='wsmexml:',
        content_type='text/xml',
        generic=False
    )
    sig = wsme.signature(*args, **kwargs)

    def decorate(f):
        sig(f)
        funcdef = wsme.api.FunctionDefinition.get(f)
        funcdef.resolve_types(wsme.types.registry)

        @functools.wraps(f)
        def callfunction(self, *args, **kwargs):
            try:
                args, kwargs = wsme.rest.args.get_args(
                    funcdef, args, kwargs, pecan.request.params, None,
                    pecan.request.body, pecan.request.content_type
                )
                if funcdef.pass_request:
                    kwargs[funcdef.pass_request] = pecan.request
                result = f(self, *args, **kwargs)

                # NOTE: Support setting of status_code with default 201
                pecan.response.status = funcdef.status_code
                if isinstance(result, wsme.api.Response):
                    pecan.response.status = result.status_code
                    result = result.obj

            except:
                try:
                    exception_info = sys.exc_info()
                    orig_exception = exception_info[1]
                    orig_code = getattr(orig_exception, 'code', None)
                    data = wsme.api.format_exception(
                        exception_info,
                        pecan.conf.get('wsme', {}).get('debug', False)
                    )
                finally:
                    del exception_info

                if orig_code and is_valid_code(orig_code):
                    pecan.response.status = orig_code
                else:
                    pecan.response.status = 500

                return data

            if funcdef.return_type is None:
                pecan.request.pecan['content_type'] = None
                pecan.response.content_type = None
                return ''

            return dict(
                datatype=funcdef.return_type,
                result=result
            )

        pecan_xml_decorate(callfunction)
        pecan_text_xml_decorate(callfunction)
        pecan_json_decorate(callfunction)
        pecan.util._cfg(callfunction)['argspec'] = inspect.getargspec(f)
        callfunction._wsme_definition = funcdef
        return callfunction

    return decorate
Ejemplo n.º 19
0
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type='application/json'):
    """
    :param arg_types: A list of types for the function arguments.
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(
        content_type=content_type,
        generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            args = list(args)
            types = copy.copy(arg_types)
            more = [args.pop(0)]

            if types:
                argspec = inspect.getargspec(f)
                names = argspec.args[1:]

                for name in names:
                    try:
                        a = args.pop(0)
                        more.append(types.pop(0)(a))
                    except IndexError:
                        try:
                            kwargs[name] = types.pop(0)(kwargs[name])
                        except IndexError:
                            LOG.warning("Type definition for '%s' argument of '%s' "
                                        "is missing.", name, f.__name__)
                        except KeyError:
                            pass

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json
                else:
                    data = {}

                obj = body_cls(**data)
                try:
                    obj.validate()
                except jsonschema.ValidationError as e:
                    raise exc.HTTPBadRequest(detail=e.message,
                                             comment=traceback.format_exc())
                except Exception as e:
                    raise exc.HTTPInternalServerError(detail=e.message,
                                                      comment=traceback.format_exc())
                more.append(obj)

            args = tuple(more) + tuple(args)

            noop_codes = [http_client.NOT_IMPLEMENTED,
                          http_client.METHOD_NOT_ALLOWED,
                          http_client.FORBIDDEN]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            result = f(*args, **kwargs)

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                return json_encode(result, indent=None)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 20
0
    @staticmethod
    def __init__(path, extra_vars):
        pass

    @staticmethod
    def render(template_path, namespace):
        if 'faultcode' in namespace:
            return encode_error(None, namespace)
        result = encode_result(namespace['result'], namespace['datatype'])
        return result


pecan.templating._builtin_renderers['wsmejson'] = JSonRenderer

pecan_json_decorate = pecan.expose(template='wsmejson:',
                                   content_type='application/json',
                                   generic=False)


def expose(*args, **kwargs):
    sig = wsme.signature(*args, **kwargs)

    def decorate(f):
        sig(f)
        funcdef = wsme.api.FunctionDefinition.get(f)
        funcdef.resolve_types(atypes.registry)

        @functools.wraps(f)
        def callfunction(self, *args, **kwargs):
            return_type = funcdef.return_type
Ejemplo n.º 21
0
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type='application/json',
             method=None):
    """
    :param arg_types: A list of types for the function arguments (e.g. [str, str, int, bool]).
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(
        content_type=content_type,
        generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            function_name = f.__name__
            args = list(args)
            more = [args.pop(0)]

            def cast_value(value_type, value):
                if value_type == bool:
                    def cast_func(value):
                        return value.lower() in ['1', 'true']
                else:
                    cast_func = value_type

                result = cast_func(value)
                return result

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json

                    obj = body_cls(**data)
                    try:
                        obj = obj.validate()
                    except (jsonschema.ValidationError, ValueError) as e:
                        raise exc.HTTPBadRequest(detail=e.message,
                                                 comment=traceback.format_exc())
                    except Exception as e:
                        raise exc.HTTPInternalServerError(detail=e.message,
                                                          comment=traceback.format_exc())

                    # Set default pack if one is not provided for resource create
                    if function_name == 'post' and not hasattr(obj, 'pack'):
                        extra = {
                            'resource_api': obj,
                            'default_pack_name': DEFAULT_PACK_NAME
                        }
                        LOG.debug('Pack not provided in the body, setting a default pack name',
                                  extra=extra)
                        setattr(obj, 'pack', DEFAULT_PACK_NAME)
                else:
                    obj = None

                more.append(obj)

            if arg_types:
                # Cast and transform arguments based on the provided arg_types specification
                result_args, result_kwargs = get_controller_args_for_types(func=f,
                                                                           arg_types=arg_types,
                                                                           args=args,
                                                                           kwargs=kwargs)
                more = more + result_args
                kwargs.update(result_kwargs)

            args = tuple(more) + tuple(args)

            noop_codes = [http_client.NOT_IMPLEMENTED,
                          http_client.METHOD_NOT_ALLOWED,
                          http_client.FORBIDDEN]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                e = get_exception_for_type_error(func=f, exc=e)
                raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 22
0
def jsexpose(*argtypes, **opts):
    content_type = opts.get('content_type', 'application/json')

    pecan_json_decorate = pecan.expose(
        content_type=content_type,
        generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            try:
                args = list(args)
                types = list(argtypes)
                more = [args.pop(0)]

                if len(types):
                    argspec = inspect.getargspec(f)
                    names = argspec.args[1:]

                    for name in names:
                        try:
                            a = args.pop(0)
                            more.append(types.pop(0)(a))
                        except IndexError:
                            try:
                                kwargs[name] = types.pop(0)(kwargs[name])
                            except IndexError:
                                LOG.warning("Type definition for '%s' argument of '%s' "
                                            "is missing.", name, f.__name__)
                            except KeyError:
                                pass

                body_cls = opts.get('body')
                if body_cls:
                    if pecan.request.body:
                        try:
                            obj = body_cls(**pecan.request.json)
                        except jsonschema.exceptions.ValidationError as e:
                            return _handle_error(http_client.BAD_REQUEST, e)
                        more.append(obj)
                    else:
                        more.append(None)

                args = tuple(more) + tuple(args)

                status_code = opts.get('status_code')

                noop_codes = [http_client.NOT_IMPLEMENTED,
                              http_client.METHOD_NOT_ALLOWED,
                              http_client.FORBIDDEN]

                if status_code and status_code in noop_codes:
                    pecan.response.status = status_code
                    return json_encode(None)

                try:
                    result = f(*args, **kwargs)
                    if status_code:
                        pecan.response.status = status_code
                    if content_type == 'application/json':
                        return json_encode(result)
                    else:
                        return result
                except exc.HTTPException as e:
                    return _handle_error(e.wsgi_response.status, e)

            except Exception as e:
                return _handle_error(http_client.INTERNAL_SERVER_ERROR, e)

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 23
0
def expose(*args, **kwargs):
    kwargs.setdefault('content_type', 'application/json')
    kwargs.setdefault('template', 'json')
    return pecan.expose(*args, **kwargs)
Ejemplo n.º 24
0
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type="application/json"):
    """
    :param arg_types: A list of types for the function arguments.
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(content_type=content_type, generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            function_name = f.__name__
            args = list(args)
            types = copy.copy(arg_types)
            more = [args.pop(0)]

            if types:
                argspec = inspect.getargspec(f)
                names = argspec.args[1:]

                for name in names:
                    try:
                        a = args.pop(0)
                        more.append(types.pop(0)(a))
                    except IndexError:
                        try:
                            kwargs[name] = types.pop(0)(kwargs[name])
                        except IndexError:
                            LOG.warning("Type definition for '%s' argument of '%s' " "is missing.", name, f.__name__)
                        except KeyError:
                            pass

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json
                else:
                    data = {}

                obj = body_cls(**data)
                try:
                    obj = obj.validate()
                except (jsonschema.ValidationError, ValueError) as e:
                    raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc())
                except Exception as e:
                    raise exc.HTTPInternalServerError(detail=e.message, comment=traceback.format_exc())

                # Set default pack if one is not provided for resource create
                if function_name == "post" and not hasattr(obj, "pack"):
                    extra = {"resource_api": obj, "default_pack_name": DEFAULT_PACK_NAME}
                    LOG.debug("Pack not provided in the body, setting a default pack name", extra=extra)
                    setattr(obj, "pack", DEFAULT_PACK_NAME)

                more.append(obj)

            args = tuple(more) + tuple(args)

            noop_codes = [http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                message = str(e)
                # Invalid number of arguments passed to the function meaning invalid path was
                # requested
                # Note: The check is hacky, but it works for now.
                func_name = f.__name__
                pattern = "%s\(\) takes exactly \d+ arguments \(\d+ given\)" % (func_name)

                if re.search(pattern, message):
                    raise exc.HTTPNotFound()
                else:
                    raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == "application/json":
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 25
0
def expose(*args, **kwargs):
    """Helper function so we don't have to specify json for everything."""
    kwargs.setdefault('content_type', 'application/json')
    kwargs.setdefault('template', 'json')
    return pecan.expose(*args, **kwargs)
Ejemplo n.º 26
0
Archivo: base.py Proyecto: timff/st2
def jsexpose(*argtypes, **opts):
    content_type = opts.get('content_type', 'application/json')

    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            params = getattr(pecan.request, 'params', {})

            if QUERY_PARAM_ATTRIBUTE_NAME in params and QUERY_PARAM_ATTRIBUTE_NAME in kwargs:
                # Remove auth token if one is provided via query params
                del kwargs[QUERY_PARAM_ATTRIBUTE_NAME]

            try:
                args = list(args)
                types = list(argtypes)
                more = [args.pop(0)]

                if len(types):
                    argspec = inspect.getargspec(f)
                    names = argspec.args[1:]

                    for name in names:
                        try:
                            a = args.pop(0)
                            more.append(types.pop(0)(a))
                        except IndexError:
                            try:
                                kwargs[name] = types.pop(0)(kwargs[name])
                            except IndexError:
                                LOG.warning(
                                    "Type definition for '%s' argument of '%s' "
                                    "is missing.", name, f.__name__)
                            except KeyError:
                                pass

                body_cls = opts.get('body')
                if body_cls:
                    if pecan.request.body:
                        data = pecan.request.json
                    else:
                        data = {}
                    try:
                        obj = body_cls(**data)
                    except jsonschema.exceptions.ValidationError as e:
                        return _handle_error(e, http_client.BAD_REQUEST)
                    more.append(obj)

                args = tuple(more) + tuple(args)

                status_code = opts.get('status_code')

                noop_codes = [
                    http_client.NOT_IMPLEMENTED,
                    http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN
                ]

                if status_code and status_code in noop_codes:
                    pecan.response.status = status_code
                    return json_encode(None)

                try:
                    result = f(*args, **kwargs)
                    if status_code:
                        pecan.response.status = status_code
                    if content_type == 'application/json':
                        return json_encode(result)
                    else:
                        return result
                except exc.HTTPException as e:
                    LOG.exception('API call failed.')
                    # Exception contains pecan.response.header + more. This is per implementation
                    # of the WSGIHTTPException type from WebOb.
                    return _handle_error(e, e.wsgi_response.status_code,
                                         e.wsgi_response.body, e.headers)

            except Exception as e:
                LOG.exception('API call failed.')
                return _handle_error(e, http_client.INTERNAL_SERVER_ERROR)

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 27
0
def jsexpose(arg_types=None,
             body_cls=None,
             status_code=None,
             content_type='application/json'):
    """
    :param arg_types: A list of types for the function arguments.
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            controller = args[0] if args else None

            # Note: We use getattr since in some places (tests) request is mocked
            params = getattr(pecan.request, 'params', {})
            method = getattr(pecan.request, 'method', None)
            path = getattr(pecan.request, 'path', None)
            remote_addr = getattr(pecan.request, 'remote_addr', None)

            # Common request information included in the log context
            request_info = {
                'method': method,
                'path': path,
                'remote_addr': remote_addr
            }

            # Log the incoming request
            values = copy.copy(request_info)
            values['filters'] = kwargs
            LOG.info('%(method)s %(path)s with filters=%(filters)s' % values,
                     extra=values)

            if QUERY_PARAM_ATTRIBUTE_NAME in params and QUERY_PARAM_ATTRIBUTE_NAME in kwargs:
                # Remove auth token if one is provided via query params
                del kwargs[QUERY_PARAM_ATTRIBUTE_NAME]

            try:
                args = list(args)
                types = copy.copy(arg_types)
                more = [args.pop(0)]

                if types:
                    argspec = inspect.getargspec(f)
                    names = argspec.args[1:]

                    for name in names:
                        try:
                            a = args.pop(0)
                            more.append(types.pop(0)(a))
                        except IndexError:
                            try:
                                kwargs[name] = types.pop(0)(kwargs[name])
                            except IndexError:
                                LOG.warning(
                                    "Type definition for '%s' argument of '%s' "
                                    "is missing.", name, f.__name__)
                            except KeyError:
                                pass

                if body_cls:
                    if pecan.request.body:
                        data = pecan.request.json
                    else:
                        data = {}
                    try:
                        obj = body_cls(**data)
                    except jsonschema.exceptions.ValidationError as e:
                        return _handle_error(e, http_client.BAD_REQUEST)
                    more.append(obj)

                args = tuple(more) + tuple(args)

                noop_codes = [
                    http_client.NOT_IMPLEMENTED,
                    http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN
                ]

                if status_code and status_code in noop_codes:
                    pecan.response.status = status_code
                    return json_encode(None)

                try:
                    result = f(*args, **kwargs)

                    # Log the outgoing response
                    values = copy.copy(request_info)
                    values[
                        'status_code'] = status_code or pecan.response.status

                    function_name = f.__name__
                    controller_name = controller.__class__.__name__

                    log_result = True
                    log_result &= function_name not in RESPONSE_LOGGING_METHOD_NAME_BLACKLIST
                    log_result &= controller_name not in RESPONSE_LOGGING_CONTROLLER_NAME_BLACKLIST

                    if log_result:
                        values['result'] = result
                        log_msg = '%(method)s %(path)s result=%(result)s' % values
                    else:
                        # Note: We don't want to include a result for some
                        # methods which have a large result
                        log_msg = '%(method)s %(path)s' % values

                    LOG.info(log_msg, extra=values)

                    if status_code:
                        pecan.response.status = status_code
                    if content_type == 'application/json':
                        return json_encode(result)
                    else:
                        return result
                except exc.HTTPUnauthorized as e:
                    LOG.debug('API call failed: %s' % (str(e)))
                    return _handle_error(e, e.wsgi_response.status_code,
                                         e.wsgi_response.body, e.headers)
                except exc.HTTPException as e:
                    LOG.exception('API call failed: %s' % (str(e)))
                    # Exception contains pecan.response.header + more. This is per implementation
                    # of the WSGIHTTPException type from WebOb.
                    return _handle_error(e, e.wsgi_response.status_code,
                                         e.wsgi_response.body, e.headers)

            except Exception as e:
                LOG.exception('API call failed: %s' % (str(e)))
                return _handle_error(e, http_client.INTERNAL_SERVER_ERROR)

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate
Ejemplo n.º 28
0
def jsexpose(arg_types=None,
             body_cls=None,
             status_code=None,
             content_type='application/json',
             method=None):
    """
    :param arg_types: A list of types for the function arguments (e.g. [str, str, int, bool]).
    :type arg_types: ``list``

    :param body_cls: Request body class. If provided, this class will be used to create an instance
                     out of the request body.
    :type body_cls: :class:`object`

    :param status_code: Response status code.
    :type status_code: ``int``

    :param content_type: Response content type.
    :type content_type: ``str``
    """
    pecan_json_decorate = pecan.expose(content_type=content_type,
                                       generic=False)

    def decorate(f):
        @functools.wraps(f)
        def callfunction(*args, **kwargs):
            function_name = f.__name__
            args = list(args)
            more = [args.pop(0)]

            def cast_value(value_type, value):
                if value_type == bool:

                    def cast_func(value):
                        return value.lower() in ['1', 'true']
                else:
                    cast_func = value_type

                result = cast_func(value)
                return result

            if body_cls:
                if pecan.request.body:
                    data = pecan.request.json

                    obj = body_cls(**data)
                    try:
                        obj = obj.validate()
                    except (jsonschema.ValidationError, ValueError) as e:
                        raise exc.HTTPBadRequest(
                            detail=e.message, comment=traceback.format_exc())
                    except Exception as e:
                        raise exc.HTTPInternalServerError(
                            detail=e.message, comment=traceback.format_exc())

                    # Set default pack if one is not provided for resource create
                    if function_name == 'post' and not hasattr(obj, 'pack'):
                        extra = {
                            'resource_api': obj,
                            'default_pack_name': DEFAULT_PACK_NAME
                        }
                        LOG.debug(
                            'Pack not provided in the body, setting a default pack name',
                            extra=extra)
                        setattr(obj, 'pack', DEFAULT_PACK_NAME)
                else:
                    obj = None

                more.append(obj)

            if arg_types:
                # Cast and transform arguments based on the provided arg_types specification
                result_args, result_kwargs = get_controller_args_for_types(
                    func=f, arg_types=arg_types, args=args, kwargs=kwargs)
                more = more + result_args
                kwargs.update(result_kwargs)

            args = tuple(more) + tuple(args)

            noop_codes = [
                http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED,
                http_client.FORBIDDEN
            ]

            if status_code and status_code in noop_codes:
                pecan.response.status = status_code
                return json_encode(None)

            try:
                result = f(*args, **kwargs)
            except TypeError as e:
                e = get_exception_for_type_error(func=f, exc=e)
                raise e

            if status_code:
                pecan.response.status = status_code
            if content_type == 'application/json':
                if is_debugging_enabled():
                    indent = 4
                else:
                    indent = None
                return json_encode(result, indent=indent)
            else:
                return result

        pecan_json_decorate(callfunction)

        return callfunction

    return decorate