Reputation: 423
I have a class based decorator. The problem is that I need to be able to have access to wraped function args and kwargs but now I can't and I don't understand why. It should be easy but it's not for me.
class limit:
def __call__(self, fn):
@wraps(fn)
# the idea to use signature like (request, *args, **kwargs) is bad. I must accept *args and **kwargs only
def wrapper(*args, **kwargs):
# pdb breakpoint is here
user = kwargs.get('user') or kwargs.get('request').user // ERROR
return fn(*args, **kwargs)
return wrapper
Let's have a look at pdb. That's ****CENSORED**** crazy.
(Pdb) args
args = (<User: dua>,)
kwargs = {}
(Pdb) kwargs
{}
(Pdb) args.args
args = (<User: dua>,)
kwargs = {}
(Pdb) args.args.args.args
args = (<User: dua>,)
kwargs = {}
(Pdb) args.get('user')
args = (<User: dua>,)
kwargs = {}
(Pdb) type(args)
<class 'tuple'>
(Pdb)
The question is how can I get access to args, kwargs and treat args as list and kwargs as dict.
P.S. I don't know why it args and kwargs looks like that. Why they do look like that?
As mentioned at the answer args
is command of pdb. User repr(args)
to see args.
Next question is possible signatures of function: 1) def fn(request, ...) 2) def fn(self, a, b, c, etc, user) 3) def fn(user)
Are there a way to deal with all of them with one decorator?
Upvotes: 2
Views: 1902
Reputation: 423
I ended up with this solution:
def wrapper(*args, **kwargs):
user = None
fn_signature_args = inspect.getfullargspec(fn).args
# looking for a user in kwargs
if 'user' in kwargs:
user = kwargs['user']
# looking for a user as positional argument
elif 'user' in fn_signature_args:
index = fn_signature_args.index('user')
user = args[index]
# looking for a user as self or request attribute
elif fn_signature_args[0] in ('request', 'self'):
user = args[0].user
Upvotes: 0