Home > database >  How to pass variables with values in decorators?
How to pass variables with values in decorators?

Time:03-15

My task is passing a variable with a values in decorator which would replace the variable to it value as key in dictionary, something like this:

@parameters(param1 =  parameter1)
x = function(param1 = 1, param2 = 2)
extract {paramter1:1, param2:2}

my current code is:

def dump_args(func):
        def wrapper(*args, **kwargs):
            variables = {}
            func_args = signature(func).bind(*args, **kwargs).arguments
            func_args = dict(func_args)
            # print(func_args)
                # to get values that are not passed and defautlt values
            sig = signature(func)
            for param in sig.parameters.values():
                if ( param.default is not param.empty):
                    if param.name not in func_args:
                        if type(param.default) in [int, str, float, bool]:
                            func_args[param.name] = param.default
                    else:
                        if param.default == 0:
                            del func_args[param.name]
            
            print(func_args)
            variables = {**variables, **{key: value for key, value in func_args.items() if type(value) in [int, float, bool, str] and key not in variables}}
            print(variables)
            # return func(*args, **kwargs)
        return wrapper

@dump_args
def test(a, b=4, e=0, c="blah-blah", d= 4.5, val=True):
    pass
dic= {'name': 'sparsh'}
test(1, 'hola', dic, False)

Output is like this: {'a': 1, 'b': 'hola', 'c': False, 'd': 4.5, 'val': True} {'a': 1, 'b': 'hola', 'c': False, 'd': 4.5, 'val': True}

what i want to do is when i put the decorator in below function like

@dump_args(b = stringvalue)
def test(a, b=4, e=0, c="blah-blah", d= 4.5, val=True):
    pass

and this function is called then in the final dictionary the b key will be replaced by integervalue key and output should be like this:

{'a': 1, 'stringvalue': 'hola', 'c': False, 'd': 4.5, 'val': True}
{'a': 1, 'stringvalue': 'hola', 'c': False, 'd': 4.5, 'val': True}

can anyone tell me how to do this. Thanks in advance

CodePudding user response:

There are lots of SO questions and answers for your base question of how to add parameters to decorators: Decorators with parameters? , How do I pass extra arguments to a Python decorator?

In your case, you could wrap your existing decorator in another layer that accepts keyword arguments as well and those keyword args would be available in the scope of your inner wrapper. Here's a simpler case along the lines of your full case that illustrates what I mean:

def dump_factory(**dump_kwargs):
    def dump_args(func):
        def wrapper(**kwargs):
            variables = kwargs
            # check if any of the kwargs from the outer decorator
            # have been set, and replace them here if so
            for ky, val in dump_kwargs.items(): 
                if ky in variables:
                    variables[ky] = val            
            return func(**variables)
        return wrapper
    return dump_args

@dump_factory(b=1)
def test(a =0, b=4, e=0, c="blah-blah", d= 4.5, val=True):
    print(f" b = {b}")

test(b='a')
# b = 1
  • Related