Exemple #1
0
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            # XXX: given that request.context exists and root-factory
            # only expects request param, having params seems unnecessary
            # ob = args['klass'](request)
            params = dict(request=request)
            if 'factory' in route_args:
                params['context'] = request.context
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())
            elif isinstance(view, _UnboundView):
                view_ = view.make_bound_view(ob)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request, **args)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            try:
                # If we have an object, it already has the request.
                if ob:
                    response = view_()
                else:
                    response = view_(request)
            except Exception:
                # cors headers need to be set if an exception was raised
                request.info['cors_checked'] = False
                raise

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request)

        # if the view returns its own response, cors headers need to be set
        if isinstance(response, Response):
            request.info['cors_checked'] = False

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response
Exemple #2
0
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            # XXX: given that request.context exists and root-factory
            # only expects request param, having params seems unnecessary
            # ob = args['klass'](request)
            params = dict(request=request)
            if 'factory' in route_args:
                params['context'] = request.context
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())
            elif isinstance(view, _UnboundView):
                view_ = view.make_bound_view(ob)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request, **args)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            try:
                # If we have an object, it already has the request.
                if ob:
                    response = view_()
                else:
                    response = view_(request)
            except Exception:
                # cors headers need to be set if an exception was raised
                request.info['cors_checked'] = False
                raise

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request)

        # if the view returns its own response, cors headers need to be set
        if isinstance(response, Response):
            request.info['cors_checked'] = False

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response
Exemple #3
0
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            params = dict(request=request)
            if 'factory' in args and 'acl' not in args:
                params['context'] = request.context
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())
            elif isinstance(view, _UnboundView):
                view_ = view.make_bound_view(ob)

        # set data deserializer
        if 'deserializer' in args:
            request.deserializer = args['deserializer']

        # do schema validation
        if 'schema' in args:
            validate_colander_schema(args['schema'], request)
        elif hasattr(ob, 'schema'):
            validate_colander_schema(ob.schema, request)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            # if we have an object, the request had already been passed to it
            if ob:
                response = view_()
            else:
                response = view_(request)

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request.errors)

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response
Exemple #4
0
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            params = dict(request=request)
            if 'factory' in args and 'acl' not in args:
                params['context'] = args['factory'](request)
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())

        # set data deserializer
        if 'deserializer' in args:
            request.deserializer = args['deserializer']

        # do schema validation
        if 'schema' in args:
            validate_colander_schema(args['schema'], request)
        elif hasattr(ob, 'schema'):
            validate_colander_schema(ob.schema, request)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            # if we have an object, the request had already been passed to it
            if ob:
                response = view_()
            else:
                response = view_(request)

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request.errors)

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response
Exemple #5
0
 def _resolve_obj_to_docstring(self, obj, args):
     # Resolve a view or validator to an object if type string
     # and return docstring.
     if is_string(obj):
         if 'klass' in args:
             ob = args['klass']
             obj_ = getattr(ob, obj.lower())
             return format_docstring(obj_)
         else:
             return ''
     else:
         return format_docstring(obj)
Exemple #6
0
 def _resolve_obj_to_docstring(self, obj, args):
     # Resolve a view or validator to an object if type string
     # and return docstring.
     if is_string(obj):
         if 'klass' in args:
             ob = args['klass']
             obj_ = getattr(ob, obj.lower())
             return format_docstring(obj_)
         else:
             return ''
     else:
         return format_docstring(obj)
Exemple #7
0
def apply_filters(request, response):
    if request.matched_route is not None:
        # do some sanity checking on the response using filters
        services = request.registry.get('cornice_services', {})
        pattern = request.matched_route.pattern
        service = services.get(pattern, None)
        if service is not None:
            kwargs, ob = getattr(request, "cornice_args", ({}, None))
            for _filter in kwargs.get('filters', []):
                if is_string(_filter) and ob is not None:
                    _filter = getattr(ob, _filter)
                try:
                    response = _filter(response, request)
                except TypeError:
                    response = _filter(response)
            if service.cors_enabled:
                apply_cors_post_request(service, request, response)

    return response
Exemple #8
0
def apply_filters(request, response):
    if request.matched_route is not None:
        # do some sanity checking on the response using filters
        services = request.registry.cornice_services
        pattern = request.matched_route.pattern
        service = services.get(pattern, None)
        if service is not None:
            kwargs, ob = getattr(request, "cornice_args", ({}, None))
            for _filter in kwargs.get('filters', []):
                if is_string(_filter) and ob is not None:
                    _filter = getattr(ob, _filter)
                try:
                    response = _filter(response, request)
                except TypeError:
                    response = _filter(response)
            if service.cors_enabled:
                apply_cors_post_request(service, request, response)

    return response
Exemple #9
0
    def _render_service(self, service):
        service_id = "service-%d" % self.env.new_serialno('service')
        service_node = nodes.section(ids=[service_id])

        title = '%s service at %s' % (service.name.title(), service.path)
        service_node += nodes.title(text=title)

        if service.description is not None:
            service_node += rst2node(trim(service.description))

        for method, view, args in service.definitions:
            if method == 'HEAD':
                #Skip head - this is essentially duplicating the get docs.
                continue
            method_id = '%s-%s' % (service_id, method)
            method_node = nodes.section(ids=[method_id])
            method_node += nodes.title(text=method)

            if is_string(view):
                if 'klass' in args:
                    ob = args['klass']
                    view_ = getattr(ob, view.lower())
                    docstring = trim(view_.__doc__ or "") + '\n'
            else:
                docstring = trim(view.__doc__ or "") + '\n'

            if 'schema' in args:
                schema = args['schema']

                attrs_node = nodes.inline()
                for location in ('header', 'querystring', 'body'):
                    attributes = schema.get_attributes(location=location)
                    if attributes:
                        attrs_node += nodes.inline(text='values in the %s' %
                                                   location)
                        location_attrs = nodes.bullet_list()

                        for attr in attributes:
                            temp = nodes.list_item()
                            desc = "%s : " % attr.name

                            # Get attribute data-type
                            if hasattr(attr, 'type'):
                                attr_type = attr.type
                            elif hasattr(attr, 'typ'):
                                attr_type = attr.typ.__class__.__name__

                            desc += " %s, " % attr_type

                            if attr.required:
                                desc += "required "
                            else:
                                desc += "optional "

                            temp += nodes.inline(text=desc)
                            location_attrs += temp

                        attrs_node += location_attrs
                method_node += attrs_node

            for validator in args.get('validators', ()):
                if validator.__doc__ is not None:
                    docstring += trim(validator.__doc__)

            if 'accept' in args:
                accept = to_list(args['accept'])

                if callable(accept):
                    if accept.__doc__ is not None:
                        docstring += accept.__doc__.strip()
                else:
                    accept_node = nodes.strong(text='Accepted content types:')
                    node_accept_list = nodes.bullet_list()
                    accept_node += node_accept_list

                    for item in accept:
                        temp = nodes.list_item()
                        temp += nodes.inline(text=item)
                        node_accept_list += temp

                    method_node += accept_node

            node = rst2node(docstring)
            DocFieldTransformer(self).transform_all(node)
            if node is not None:
                method_node += node

            renderer = args['renderer']
            if renderer == 'simplejson':
                renderer = 'json'

            response = nodes.paragraph()

            response += nodes.strong(text='Response: %s' % renderer)
            method_node += response

            service_node += method_node

        return service_node
Exemple #10
0
def decorate_view(view, args, method):
    """Decorate a given view with cornice niceties.

    This function returns a function with the same signature than the one
    you give as :param view:

    :param view: the view to decorate
    :param args: the args to use for the decoration
    :param method: the HTTP method
    """
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            params = dict(request=request)
            if 'factory' in args and 'acl' not in args:
                params['context'] = request.context
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())
            elif isinstance(view, _UnboundView):
                view_ = view.make_bound_view(ob)

        # set data deserializer
        if 'deserializer' in args:
            request.deserializer = args['deserializer']

        # do schema validation
        if 'schema' in args:
            validate_colander_schema(args['schema'], request)
        elif hasattr(ob, 'schema'):
            validate_colander_schema(ob.schema, request)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            try:
                # If we have an object, it already has the request.
                if ob:
                    response = view_()
                else:
                    response = view_(request)
            except:
                # cors headers need to be set if an exception was raised
                request.info['cors_checked'] = False
                raise

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request.errors)

        # if the view returns its own response, cors headers need to be set
        if isinstance(response, Response):
            request.info['cors_checked'] = False

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response

    # return the wrapper, not the function, keep the same signature
    if not is_string(view):
        functools.update_wrapper(wrapper, view)

    # Set the wrapper name to something useful
    wrapper.__name__ = "{0}__{1}".format(func_name(view), method)
    return wrapper
Exemple #11
0
    def _render_service(self, service):
        service_id = "service-%d" % self.env.new_serialno('service')
        service_node = nodes.section(ids=[service_id])

        title = '%s service at %s' % (service.name.title(), service.path)
        service_node += nodes.title(text=title)

        if service.description is not None:
            service_node += rst2node(trim(service.description))

        for method, view, args in service.definitions:
            if method == 'HEAD':
                #Skip head - this is essentially duplicating the get docs.
                continue
            method_id = '%s-%s' % (service_id, method)
            method_node = nodes.section(ids=[method_id])
            method_node += nodes.title(text=method)

            if is_string(view):
                if 'klass' in args:
                    ob = args['klass']
                    view_ = getattr(ob, view.lower())
                    docstring = trim(view_.__doc__ or "") + '\n'
            else:
                docstring = trim(view.__doc__ or "") + '\n'

            if 'schema' in args:
                schema = args['schema']

                attrs_node = nodes.inline()
                for location in ('header', 'querystring', 'body'):
                    attributes = schema.get_attributes(location=location)
                    if attributes:
                        attrs_node += nodes.inline(
                                text='values in the %s' % location)
                        location_attrs = nodes.bullet_list()

                        for attr in attributes:
                            temp = nodes.list_item()
                            desc = "%s : " % attr.name

                            # Get attribute data-type
                            if hasattr(attr, 'type'):
                                attr_type = attr.type
                            elif hasattr(attr, 'typ'):
                                attr_type = attr.typ.__class__.__name__

                            desc += " %s, " % attr_type

                            if attr.required:
                                desc += "required "
                            else:
                                desc += "optional "

                            temp += nodes.inline(text=desc)
                            location_attrs += temp

                        attrs_node += location_attrs
                method_node += attrs_node

            for validator in args.get('validators', ()):
                if validator.__doc__ is not None:
                    docstring += trim(validator.__doc__)

            if 'accept' in args:
                accept = to_list(args['accept'])

                if callable(accept):
                    if accept.__doc__ is not None:
                        docstring += accept.__doc__.strip()
                else:
                    accept_node = nodes.strong(text='Accepted content types:')
                    node_accept_list = nodes.bullet_list()
                    accept_node += node_accept_list

                    for item in accept:
                        temp = nodes.list_item()
                        temp += nodes.inline(text=item)
                        node_accept_list += temp

                    method_node += accept_node

            node = rst2node(docstring)
            DocFieldTransformer(self).transform_all(node)
            if node is not None:
                method_node += node

            renderer = args['renderer']
            if renderer == 'simplejson':
                renderer = 'json'

            response = nodes.paragraph()

            response += nodes.strong(text='Response: %s' % renderer)
            method_node += response

            service_node += method_node

        return service_node
Exemple #12
0
def decorate_view(view, args, method):
    """Decorate a given view with cornice niceties.

    This function returns a function with the same signature than the one
    you give as :param view:

    :param view: the view to decorate
    :param args: the args to use for the decoration
    :param method: the HTTP method
    """
    def wrapper(request):
        # if the args contain a klass argument then use it to resolve the view
        # location (if the view argument isn't a callable)
        ob = None
        view_ = view
        if 'klass' in args and not callable(view):
            params = dict(request=request)
            if 'factory' in args and 'acl' not in args:
                params['context'] = request.context
            ob = args['klass'](**params)
            if is_string(view):
                view_ = getattr(ob, view.lower())
            elif isinstance(view, _UnboundView):
                view_ = view.make_bound_view(ob)

        # set data deserializer
        if 'deserializer' in args:
            request.deserializer = args['deserializer']

        # do schema validation
        if 'schema' in args:
            validate_colander_schema(args['schema'], request)
        elif hasattr(ob, 'schema'):
            validate_colander_schema(ob.schema, request)

        # the validators can either be a list of callables or contain some
        # non-callable values. In which case we want to resolve them using the
        # object if any
        validators = args.get('validators', ())
        for validator in validators:
            if is_string(validator) and ob is not None:
                validator = getattr(ob, validator)
            validator(request)

        # only call the view if we don't have validation errors
        if len(request.errors) == 0:
            try:
                # If we have an object, it already has the request.
                if ob:
                    response = view_()
                else:
                    response = view_(request)
            except:
                # cors headers need to be set if an exception was raised
                request.info['cors_checked'] = False
                raise

        # check for errors and return them if any
        if len(request.errors) > 0:
            # We already checked for CORS, but since the response is created
            # again, we want to do that again before returning the response.
            request.info['cors_checked'] = False
            return args['error_handler'](request.errors)

        # if the view returns its own response, cors headers need to be set
        if isinstance(response, Response):
            request.info['cors_checked'] = False

        # We can't apply filters at this level, since "response" may not have
        # been rendered into a proper Response object yet.  Instead, give the
        # request a reference to its api_kwargs so that a tween can apply them.
        # We also pass the object we created (if any) so we can use it to find
        # the filters that are in fact methods.
        request.cornice_args = (args, ob)
        return response

    # return the wrapper, not the function, keep the same signature
    if not is_string(view):
        functools.update_wrapper(wrapper, view)

    # Set the wrapper name to something useful
    wrapper.__name__ = "{0}__{1}".format(func_name(view), method)
    return wrapper
Exemple #13
0
    def _render_service(self, service):
        service_id = "service-%d" % self.env.new_serialno('service')
        service_node = nodes.section(ids=[service_id])

        title = '%s service at %s' % (service.name.title(), service.path)
        title = title.replace('Collection_', '')
        service_node += nodes.title(text=title)

        if service.description is not None:
            service_node += rst2node(trim(service.description))

        for method, view, args in service.definitions:
            if method == 'HEAD':
                # Skip head - this is essentially duplicating the get docs.
                continue
            if method in self.options.get('ignore-methods', []):
                continue
            method_id = '%s-%s' % (service_id, method)
            method_node = nodes.section(ids=[method_id])
            method_node += nodes.title(text=method)

            if is_string(view):
                if 'klass' in args:
                    ob = args['klass']
                    view_ = getattr(ob, view.lower())
                    docstring = trim(view_.__doc__ or "") + '\n'
            else:
                docstring = trim(view.__doc__ or "") + '\n'

            print('Replacing BIMT strings with app strings in API docstrings.')
            docstring = docstring.replace(
                'BIMT', self.options.get('app-title', 'BIMT'))
            docstring = docstring.replace(
                'http://localhost:8080', self.options.get('app-url', 'http://localhost:8080'))  # noqa

            attrs_node = None
            if 'schema' in args:
                schema = args['schema']

                attrs_node = nodes.inline()
                for location in ('header', 'querystring', 'body'):
                    attributes = schema.get_attributes(location=location)
                    if attributes:
                        attrs_node += nodes.inline(
                            text='Values in the %s:' % location)
                        location_attrs = nodes.bullet_list()

                        for attr in attributes:
                            temp = nodes.list_item()

                            # check for permissions
                            column_name = attr.name
                            if column_name == 'version':
                                column_name = 'v'
                            elif column_name == 'created':
                                column_name = 'c'
                            elif column_name == 'modified':
                                column_name = 'm'

                            # find attr in SQLAlchemy table definition and
                            # check that it has view permission
                            if not getattr(args['klass'], 'model', None):
                                continue
                            columns = args['klass'].model.__table__.columns
                            if column_name in columns.keys():
                                info = getattr(columns[column_name], 'info', None)
                                permission = info.get('colanderalchemy', {}).get('view_permission')
                                if permission != BimtPermissions.view:
                                    continue
                            else:
                                continue

                            # Get attribute data-type
                            if hasattr(attr, 'type'):
                                attr_type = attr.type
                            elif hasattr(attr, 'typ'):
                                attr_type = attr.typ.__class__.__name__
                            else:
                                attr_type = None

                            temp += nodes.strong(text=attr.name)
                            if attr_type is not None:
                                temp += nodes.inline(text=' (%s)' % attr_type)
                            if not attr.required or attr.description:
                                temp += nodes.inline(text=' - ')
                                if not attr.required:
                                    if attr.missing is not None and \
                                            not isinstance(attr.missing, colander._drop):
                                        default = json.dumps(attr.missing)
                                        temp += nodes.inline(
                                            text='(default: %s) ' % default)
                                    else:
                                        temp += nodes.inline(
                                            text='(optional) ')
                                if attr.description:
                                    temp += nodes.inline(text=attr.description)

                            location_attrs += temp

                        attrs_node += location_attrs

            for validator in args.get('validators', ()):
                if validator.__doc__ is not None:
                    docstring += trim(validator.__doc__)

            accept_node = False
            if 'accept' in args:
                accept = to_list(args['accept'])

                if callable(accept):
                    if accept.__doc__ is not None:
                        docstring += accept.__doc__.strip()
                elif len(accept) == 1:
                    accept_node = nodes.strong(
                        text='Accepted content type: {}'.format(accept[0]))
                else:
                    accept_node = nodes.strong(text='Accepted content types:')
                    node_accept_list = nodes.bullet_list()
                    accept_node += node_accept_list

                    for item in accept:
                        temp = nodes.list_item()
                        temp += nodes.inline(text=item)
                        node_accept_list += temp

            node = rst2node(docstring)
            DocFieldTransformer(self).transform_all(node)
            if node is not None:
                method_node += node

            if attrs_node:
                method_node += attrs_node

            if accept_node:
                method_node += accept_node

            renderer = args['renderer']
            if renderer == 'simplejson':
                renderer = 'json'

            response = nodes.paragraph()

            response += nodes.strong(text='Response: %s' % renderer)
            method_node += response

            service_node += method_node

        return service_node