Artem Dumanov
Artem Dumanov

Reputation: 423

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.

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

Answers (2)

Artem Dumanov
Artem Dumanov

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

Slam
Slam

Reputation: 8572

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

Upvotes: 1

Related Questions