# first attempt def deco_first(f): def inner(*args, **kwargs): return f(*args, **kwargs) inner.__name__ = f.__name__ inner.__doc__ = f.__doc__ inner.__qualname__ = f.__qualname__ return inner # second attempt from functools import update_wrapper def deco_second(f): def inner(*args, **kwargs): return f(*args, **kwargs) update_wrapper(inner, f) return inner # third attempt def my_wraps(original): def deco(wrapper): update_wrapper(wrapper, original) return wrapper return deco from functools import partial def partial_wraps(original): return partial(update_wrapper, wrapped=original) # def deco_third(f): # def inner(*args, **kwargs): # return f(*args, **kwargs) # # deco = my_wraps(f) # inner = deco(inner) # return inner def deco_third(f): @partial_wraps(f) def inner(*args, **kwargs): return f(*args, **kwargs) return inner # third attempt from functools import wraps def deco_fourth(f): @wraps(f) def inner(*args, **kwargs): return f(*args, **kwargs) return inner @deco_third def foo(a, b, c): """ Foo function docstring """ return a + b + c