Python class decorator for classes

We've been thinking this week in a good solution to separate credentials logic from our functional modules, and we've realised that decorators could be it. I came to this idea looking Tornado and Django's solution.

There are a lot of good posts and discussions about python decorators, but I needed to look deeper than most of tutorials.

There are many tutorials describing what a decorator is, so I won't enter in it, anyway there's a good classification (spanish) which I will refer to now.

According to the classification, the implementation approach is a bit different in these cases:

  • Decorator without parameters
  • Decorator with parameters
  • Decorator class without parameters
  • Decorator class with parameters
  • And what I needed...
  • Decorator class with parameters for another class methods

Why a class instead of a simple function?

Because I needed to separate initialization from execution. If you know how to use a decorator you will understand my approach easy.

Finally my class:


class CheckPerm(object):
    '''Check permissions by a type'''
    def __init__(self, type):
        self.type = type

    def __get__(self, obj, type=None):
        ''' We need this to get the class of the function'''
        return self.__class__(self.func.__get__(obj, type))

    def __call__(self, func):
        self.func = func

        def wrap(*args, **kw):
            if self.type == 'one':
                result = self.check_one(args)
            elif self.type == 'two':
                result = self.check_two(args)

            if not result:
                return {"status": "1",
                        "error": "You dont have permissions"}

            return self.func(*args, **kw)
        return wrap

    def check_one(self, args):
        ''' Just for the example'''
        pass

    def check_two(self, args):
        ''' Just for the example'''
        pass

In the __init__ function I take the decorator parameter (type).

The __get__ function is necessary for not to lose our function class.

When we __call__ the function, we take it in our decorator, we check parameters (with hypothetical check_one and check_two functions) and return the execution of the function or our custom error.

In __call__ function we need this wrap to catch function parameters.

Now we can call our decorator like...


class myClass():

    @CheckPerm('one')
    def my_function(self, my_arg):
        pass

And that's all, hope it helps you understand better a solution for this need. :-)

Javier Aguirre

Read more posts by this author.

comments powered by Disqus