Reputation: 1232
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!
Upvotes: 1
Views: 430
Reputation: 151117
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
(i.e. the original get
) is passed there, and then called on result
:
def done_auth(result, fn):
return fn(result)
But fn
(i.e. get
) takes two arguments. You pass it only one, causing an error.
Upvotes: 2