/ / Obtenga argumentos del decorador de Python en tiempo de ejecución - python, python-2.7, introspection, python-decorators

Obtenga argumentos del decorador de Python en tiempo de ejecución: python, python-2.7, introspection, python-decorators

¿Hay alguna forma de obtener los argumentos de¿Una función decoradora en tiempo de ejecución? El proyecto en el que estoy trabajando es enorme y sería un gran esfuerzo reescribir el código afectado. Necesito una solución dinámica para enumerar todas las "categorías" asignadas a una lista de funciones. Para esto quiero evitar las soluciones super hacky. como regexing a través de todos mis módulos. ¿Se puede hacer esto inspeccionando los marcos de la pila de llamadas?

En nuestro entorno, las funciones son métodos de objetos, y también usamos decoradores encadenados. Para facilitar la comprensión, armé este fragmento de código.

Si esto no es posible, puedo armar otro decorador para partes del proyecto, aunque eso agregaría mucha más complejidad. Pero cualquier sugerencia para resolver mi problema es bienvenida.

def check(*args):
# do something project relevant, so just return True
return True

def decorate(*categories):
def wrap(f):
def wrap_check_categories(*args, **kwargs):
if check(*categories):
return f(*args, **kwargs)
else:
raise Exception
return wrap_check_categories
return wrap

def get_categories(f):
"""Returns decorator parameters"""
# ... do some magic here
raise NotImplementedError

@decorate("foo", "bar")
def fancy_func(*args, **kwargs):
return args, kwargs

def main():
## should output ["foo", "bar"]
print get_categories(fancy_func)

if __name__ == "__main__":
main()

Respuestas

2 para la respuesta № 1

Modifique el decorador para almacenar las categorías en un atributo (por ejemplo, _args) de la función decorada:

def check(*args):
# do something project relevant, so just return True
return True

def decorate(*categories):
def wrap(f):
def wrap_check_categories(*args, **kwargs):
if check(*categories):
return f(*args, **kwargs)
else:
raise Exception
wrap_check_categories._args = categories    # <-- store the categories
return wrap_check_categories
return wrap

def get_categories(f):
"""Returns decorator parameters"""
# ... do some magic here
return f._args

@decorate("foo", "bar")
def fancy_func(*args, **kwargs):
return args, kwargs

def main():
## should output ["foo", "bar"]
print get_categories(fancy_func)

if __name__ == "__main__":
main()

rendimientos

("foo", "bar")