"""
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