AidarDzhumagulov
AidarDzhumagulov

Reputation: 111

How to filter the **kwargs before passing them to a function?

I have a decorator:

def decorator(func):
     @wraps(func)
     def wrapper(*args, **kwargs):
         print('something', **kwargs)

         # kwargs.pop('task_id', None)

         func(*args, **kwargs)
        
         print('something', **kwargs)
    
     return wrapper 

I need to filter the kwargs in such a way that they can be passed to the calling function without the task_id, but not removed. Since after I will need to fully use kwargs. Does anyone know how can this be done?

Upvotes: 2

Views: 1223

Answers (3)

Tomerikoo
Tomerikoo

Reputation: 19404

When inside the function (wrapper), kwargs is just a dict. So you can remove a key while returning a new dictionary:

def decorator(func):
     @wraps(func)
     def wrapper(*args, **kwargs):
         print('something', **kwargs)

         func(*args, **{kw: kwargs[kw] for kw in kwargs if kw != "task_id"})
        
         print('something', **kwargs)
    
     return wrapper 

Upvotes: 1

KiraLT
KiraLT

Reputation: 2607

You can add task_id as a separate keyword argument, so it will be automatically excluded from other kwargs:

def decorator(func):
     @wraps(func)
     def wrapper(*args, task_id=None, **kwargs):
         func(*args, **kwargs)
    
     return wrapper 

Upvotes: 3

AidarDzhumagulov
AidarDzhumagulov

Reputation: 111

I have one variant, but it looks so bad. So I did:

def decorator(func):
     @wraps(func)
     def wrapper(*args, **kwargs):

         print('something', **kwargs)
         new_kwargs = kwargs,copy()
         new_kwargs.pop('task_id', None)

         func(*args, **new_kwargs)
        
         print('something', **kwargs)
    
     return wrapper 

If anyone have better variant, it will be good.

Upvotes: 0

Related Questions