python - 基于类的装饰器作为单例

时间:2017-11-13 14:11:25

标签: python python-3.x singleton python-requests python-decorators

我写了一个基于函数的装饰器来处理我公司Web服务的身份验证:

def company_auth(path=None, method=None):
    """
    Company Webservices authentication decorator
    :param path: relative url of the endpoint;
    :param method: http method used for the call

    usage example:

    @company_auth(path='/api/MO/GetDetails', method='GET')
    def mo_get_details(**kwargs):
        path = kwargs.pop('path')
        headers = kwargs.pop('headers')
        ...

    retrieve a valid token, compute the signature and pass to the inner function
    the headers dict and the path parameter as kw arguments.
    """

    def _signature_wrapper(fn, path, method):
        def wrapper(*args, **kwargs):
            token = get_valid_token()
            signature_dict = {
                'url': path,
                'token': token.token,
                'secret': token.secret,
                'method': method
            }
            make_signature_results = make_signature(**signature_dict)
            headers = {
                'comp-header-date': make_signature_results['date'],
                'comp-header-session-token': signature_dict['token'],
                'comp-header-signature': make_signature_results['signature'],
                'Content-Type': CONTENT_TYPE,
            }
            kwargs['headers'] = headers
            kwargs['path'] = path
            results = fn(*args, **kwargs)
            return results
        return wrapper

    def decorating_fn(fn):
        wrapper = _signature_wrapper(fn, path, method)
        return update_wrapper(wrapper, fn)
    return decorating_fn


def get_valid_token():
    """
    get a valid token from db or generate a new one from company webservices.
    """
    if not APIToken.objects.exists():  # this is a Django model
        return set_new_token()
    api_token = APIToken.objects.first()
    if not api_token.is_valid:
        return set_new_token()
    else:
        return api_token

虽然我通过Django ORM将生成的token / secret值保存在数据库中,但它工作正常。 我想避免这种情况,将其转变为基于类的装饰器,将其实例化为单例并将其导入不同的模块中。我想保留令牌/秘密对的值不在数据库上但在内存中(作为该实例的属性),如:

# Wanted CB Decorator

def CompanyAuth():
    """
    Class Based Company Webservices authentication decorator
    """

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

        def __get__(self, *args, **kwargs):
            ...

        def __call__(self, *args, **kwargs):
            ...


comp_auth = CompanyAuth()
# the singleton can then be imported by other modules and used

它是否可行以及如何实现这一目标?

0 个答案:

没有答案