简体   繁体   中英

python decorated function with multiple args (Tornado)

I have written a decorator to authenticate calls. It works fine with only one argument, but with more it doesn't, triggering off a inner() takes exactly 1 argument (2 given) . I have a bit of a callback spaghetti since I'm using Tornado, but I'm not sure what's the best way to do this.

#this works
class FirstHandler(BaseHandler):

    @asynchronous
    @oauth_machine.auth
    def post(self):
        print self.user
        self.finish()

#this now also does
class SecondHandler(BaseHandler):

    @asynchronous
    @oauth_machine.auth
    def get(self, args):
        self.write("ok")
        self.finish()

The decorator function(s)

def auth(fn):
    def inner(self, *args):
        res = get_user_by_credentials(self, fn, args, callback=done_auth)
    return inner

def get_user_by_credentials(self, fn, callback):

    def onFetchUserCredentials(result, error):
        self.user = result
        callback(self, fn, args)

    email = self.get_argument("email")
    password = self.get_argument("password")
    settings.DB.users.find_one({'email': email, 'password': password }, callback=onFetchUserCredentials)

def done_auth(result, fn, args):
    return fn(result, args)

EDIT :

Updated code to working version.

Thanks!

I thought at first that the problem was quite simple, but then you posted a traceback contradicting the original error message. However, I think the problem is still pretty straightforward, assuming that the traceback error is the correct one. Recall that this:

@decorator
def foo(x):
    return x + 1

Is simply syntactic sugar for this:

def foo(x):
    return x + 1
foo = oauth_machine.auth(foo)

So when you use @oauth_machine.auth on get , it's passed via a closure into inner as fn .

def auth(fn):
    def inner(self):
        res = get_user_by_credentials(self, fn, callback=done_auth)
    return inner

It's then passed into get_user_by_credentials , again as fn , which in turn produces another closure, which passes fn to callback .

def get_user_by_credentials(self, fn, callback):

    def onFetchUserCredentials(result, error):
        self.user = result
        callback(self, fn)

callback was defined as done_auth back in inner , so that menas that fn (ie the original get ) is passed there, and then called on result :

def done_auth(result, fn):
    return fn(result)

But fn (ie get ) takes two arguments. You pass it only one, causing an error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM