# 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