Source code for micro.rest.decorators

"""
This is decorators for marking methods as REST endpoints.

See docs/decorators.rst for details.
"""
import logging
from string import Template

from micro.web import http, middleware

from . import swag
from .metadata import RestMetadata
from .validation import ValidationMiddleware


logger = logging.getLogger(__name__)


class TemplatedDocstring:
    """
    Callable that returns the docstring for an object after filling in the template variables.
    """

    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def __call__(self, f):
        template = Template(f.__doc__)
        f.__doc__ = template.substitute(self.kwargs)
        return f

templated_docstring = TemplatedDocstring


[docs]class Rest: """ Callable that provides validation, authentication and support for REST endpoints. """ @templated_docstring(SwaggerSchema=swag.SWAGGER_SCHEMA)
[docs] def __init__(self, content_type=(http.CONTENT_TYPE_JSON,), swagger_instance=swag.swagger, swagger_config={} ): """ :param content_type: Accepted content-type of REST API method, or iterable of accepted content types :param swagger_instance: Instance of Swagger metadata aggregator :type swagger_instance: :class:`micro.rest.swag.Swagger` :param swagger_config: A dictionary conforming the following Orderly schema: .. code:: $SwaggerSchema If ``swagger_config`` parameter is not passed, the metadata for endpoint will be parsed from endpoint docstring, using :ref:`micro.rest.metadata` :type swagger_config: dict :return: """ self.content_types = content_type if hasattr(content_type, '__iter__') else (content_type, ) self.swagger_instance = swagger_instance self.metadata = swagger_config
def __call__(self, f): """ Mark a decorated function as a REST API endpoint :param f: :return: """ doc = f.__doc__ endpoint = f.route.name if not doc: raise RuntimeError("Undocumented REST API method {!r}".format(f)) middleware.install_for_endpoint(ValidationMiddleware, endpoint) if not self.metadata: swag.register_endpoint(f, content_types=self.content_types, swagger_instance=self.swagger_instance) else: swag.register_metadata(f, self.metadata, content_types=self.content_types, swagger_instance=self.swagger_instance) return f
rest = Rest