In [2]:
from functools import update_wrapper

class PermissionDenied(Exception):
    pass

class PermissionedMethod(object):
    def __init__(self, *permissions):
        self._permissions = [p() for p in permissions]
        self._method = None
    
    def __call__(self, method):
        if self._method is not None:
            raise TypeError("Method already loaded")
        
        def permissioner(inst, request, *args, **kwargs):
            for permission in self._permissions:
                if not permission.has_permission(request, inst):
                    raise PermissionDenied(message=getattr(permission, 'message', None))
                    
            else:
                return method(inst, request, *args, **kwargs)
        
        self._method = update_wrapper(permissioner, method)
        update_wrapper(self, method)        
        return self
    
    def __get__(self, inst, cls):
        if inst is None:
            return self
        return lambda req, *args, **kwargs: self._method(inst, req, *args, **kwargs)

In [3]:
class Permission(object):
    def has_permission(self, request, view):
        print("Permssioned!")
        return True

In [4]:
class SomeView(object):
    @PermissionedMethod(Permission)
    def something(self, request, *args, **kwargs):
        return (self, request, args, kwargs)

In [5]:
SomeView.something


Out[5]:
<__main__.PermissionedMethod at 0x7fdf50174518>

In [6]:
sv = SomeView()

In [7]:
sv.something(1)


Permssioned!
Out[7]:
(<__main__.SomeView at 0x7fdf5016ab70>, 1, (), {})

In [ ]: