Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing function arguments from decorator

I have a Request handler and a decorator, I would like to work with the self object inside the decorator

class MyHandler(webapp.RequestHandler):

    @myDecorator
        def get(self):
            #code

Update: Please notice the difference between the first and second self

class myDecorator(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        #work with self
  1. MyHandler > get ( function ) > self ( argument )
  2. myDecorator > __call__ ( function ) > self ( argument )

the self arguments mentioned above are different. My intention is to access the first self from inside __call__ function, or find a way to do something similar.

Hi can I access MyHandlers self argument from get function inside the decorator?

Update2: I want to implement a decorator to work with a custom login in google app engine:

I have a class ( requestHandler ):

class SomeHandler(webapp.RequestHandler):
    @only_registered_users
    def get(self):
        #do stuff here

And I want to decorate the get function in order to check out if the user is logged in or not:

from util.sessions import Session
import logging

class only_registered_users(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        def decorated_get(self):
        logging.debug("request object:", self.request)
        session = Session()

        if hasattr(session, 'user_key'):
            return self.f(self)
        else:
            self.request.redirect("/login")


    return decorated_get

I know if a user is logged in if has the property 'user_key' in a session Object.

That's the main goal I'm interested in on this specific case

Let me know your suggestions / opinions if I'm doing something wrong!

Thanks!

like image 319
Mc- Avatar asked Jun 24 '11 15:06

Mc-


1 Answers

I'm not entirely clear what it is you want, but if you just want to use the decorated function's arguments, then that is exactly what a basic decorator does. So to access say, self.request from a decorator you could do:

def log_request(fn):
    def decorated_get(self):
        logging.debug("request object:", self.request)
        return fn(self)
    return decorated_get

class MyHandler(webapp. RequestHandler):
    @log_request
    def get(self):
        self.response.out.write('hello world')

If you are trying to access the class the decorated function is attached to, then it's a bit tricker and you'll have to cheat a bit using the inspect module.

import inspect

def class_printer(fn):
    cls = inspect.getouterframes(inspect.currentframe())[1][3]
    def decorated_fn(self, msg):
        fn(self,cls+" says: "+msg)
    return decorated_fn

class MyClass():
    @class_printer
    def say(self, msg):
        print msg

In the example above we fetch the name of the class from the currentframe (during the execution of the decorator) and then store that in the decorated function. Here we are just prepending the class-name to whatever the msg variable is before passing it on to the original say function, but you can use your imagination to do what ever you like once you have the class name.

>>> MyClass().say('hello')
MyClass says: hello
like image 95
Chris Farmiloe Avatar answered Sep 22 '22 15:09

Chris Farmiloe