decorator.py 1.85 KB
from functools import wraps
from logging import getLogger
import venusian
from .structure import (
    HEADER_FIELDS,
    RC_OK,
)
from .validation import (
    field_validation,
    header_validation,
)
from .view import create_response


# View decorator
class json_method:
    def __init__(self, **kw):
        self.kw = kw

    def __call__(self, func):
        kw = self.kw.copy()
        # add_view() tidak bisa menerima parameter berikut ini
        depth = kw.pop('_depth', 0)
        service_code = kw.pop('service_code', None)
        fields = kw.pop('fields', None)

        def callback(context, name, ob):
            config = context.config.with_package(info.module)
            config.add_view(
                view=ob, renderer='json', request_method='POST', **kw)

        info = venusian.attach(
                func, callback, category='pyramid', depth=depth + 1)
        if info.scope == 'class':
            # ensure that attr is set if decorating a class method
            kw.setdefault('attr', func.__name__)

        kw['_info'] = info.codeinfo  # fbo action_method

        @wraps(func)
        def wrapper(cls):
            request = cls.request
            log = getLogger(func.__name__)
            log.info(
                'from %s headers %s request %s', request.client_addr,
                dict(request.headers), request.json_body)
            if request.authenticated_userid:
                log.info('user_id %s', request.authenticated_userid)
            header_validation(request.headers, HEADER_FIELDS)
            params = field_validation(request.json_body, fields)
            r = func(cls, params)
            resp = create_response(service_code, RC_OK, 'Berhasil', r, request)
            log.info(
                'to %s headers %s response %s', request.client_addr,
                dict(resp.headers), r)
            return resp
        return wrapper