简体   繁体   中英

Get access to kwargs and args at the wrapper of decorator

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.

PS 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?


Your pdb output is not really relevant, args here acts like interactive pdb command.

For the sake of simplicity, either use repr(args) or temporary rename *args argument

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

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