I have the following decorator and class.
def auth(fn):
def check_headers(self):
print 'checking headers...'
#self.headers work done here
def inner(self, *args, **kwargs):
check_headers(self)
fn(self, args, kwargs)
return inner
class Worker(object):
@auth
def work(self, *args, **kwargs):
print 'auth passed'
print args
print kwargs
worker_obj = Worker()
worker_obj.work('arg', kw='kwarg')
Which outputs :
> checking headers...
> auth passed
> (('arg',), {'kw': 'kwarg'})
> {}
But am I expecting this :
> checking headers...
> auth passed
> ('arg',)
> {'kw': 'kwarg'}
How come the args/kwargs are getting put in a tuple when the original method (work()) is being run, post-decoration?
I know that stripping it down to
def auth(fn):
return fn
returns the parameters correctly, but I need to do some work on the worker instance (self) before returning. I surely missed something about decorators.
When you call fn(self, args, kwargs)
, you are passing two positional arguments: the tuple of args
, and the dict of kwargs
. So if you call work(1, x=2)
, you will call func(self, (1,), {'x': 2})
. To expand the origianl args and kwargs into separate arguments, you need to do
fn(self, *args, **kwargs)
This will mean that when you call work(1, x=2)
, then you will also call fn(self, 1, x=2)
.
You can see documentation on this here.