0

i want to get the parameter names of a function while it is in a decorator function, I keep getting the function wrapper parameters that is inside the decorator and not the parameters of the original method

_component_name_does_not_exist_error is the decorator and create_queue_to_component is the method, i want to get at least the names component_name and queue_name

def _component_name_does_not_exist_error(func):
    def function_wrapper(self, component_name):
        if not self._does_component_exist(component_name):
            return self._create_response(
                False,
                f"Component named {component_name} doesn't exist"
            )
        return func

    return function_wrapper

@_component_name_does_not_exist_error
def create_queue_to_component(self, component_name,
                              queue_name, queue_size=1):
    if self.components[component_name].does_queue_exist(queue_name):
        return self._create_response(
            False,
            f"Queue named {queue_name} already exist"
        )

    self.components[component_name].create_queue(queue_name=queue_name,
                                                 queue_size=queue_size)
    return self._create_response(
        True,
        f"The Queue {queue_name} has been created"
    )

i tried using these methods with no luck, all return component_name without the queue_name (to make the code below more clear, pipeline_manager is an object of the class containing the methods)

def get_method_parameters(self):
    print(inspect.signature(self.pipeline_manager.create_queue_to_component))
    print(self.pipeline_manager.create_queue_to_component.__code__.co_varnames)
    print(inspect.getfullargspec(self.pipeline_manager.create_queue_to_component))

Thank you for reading this and for your help :)

Guy Mayo
  • 23
  • 6
  • At what point do you need these arguments? You can get them inside the decorator, but not outside, as the function is replaced the wrapper (and that has only the argument `component_name`). – MrBean Bremen Mar 29 '20 at 12:39

2 Answers2

0

Use functools.wraps from functools module

import functools

def _component_name_does_not_exist_error(func):
    @functools.wraps(func)
    def function_wrapper(self, component_name):
        if not self._does_component_exist(component_name):
            return self._create_response(
                False,
                f"Component named {component_name} doesn't exist"
            )
        return func

    return function_wrapper

Then

print(inspect.signature(self.pipeline_manager.create_queue_to_component))

Gives you what I think you want, which is the argument names of the create_queue_to_component function.

This answer describes functools.wraps very nicely.

wstk
  • 1,040
  • 8
  • 14
  • Thank you for you answer, you are right, i do get the right argument names but when i am tring to execute the method i get an error TypeError: function_wrapper() takes 2 positional arguments but 4 were given – Guy Mayo Mar 29 '20 at 12:48
  • `def function_wrapper(component_name, *args)`. Adding the `*args` allows decorated function to have other arguments – wstk Mar 29 '20 at 13:32
  • I changed it to `def function_wrapper(self, component_name, *args, **kwargs)` and it works but not for all of the cases. Using this decorator on another function that has a its component_name parameter at the third index of the parameters will cause a big problem. If you have an idea for solving that it will be great. – Guy Mayo Mar 29 '20 at 13:53
  • Can you pass `component_name` as a keyword argument? – wstk Mar 29 '20 at 14:06
0
def _component_name_does_not_exist_error(func):
    @functools.wraps(func)
    def function_wrapper(self, *args, **kwargs):
        if not self._does_component_exist(kwargs['component_name']):
            return self._create_response(
                False,
                f"Component named {kwargs['component_name']} doesn't exist"
            )
        return func(self, *args, **kwargs)

    return function_wrapper

This works for me (Thank you @wstk for suggesting your answer and helping me reaching the answer)

Guy Mayo
  • 23
  • 6