import inspect


def steal_signature_from(original_func, *, steal_docstring=True):
    # noinspection PyUnresolvedReferences
    """
    Makes a decorator that will replace original_func with the decorated argument.

    The decorated argument will have the same apparent signature as the initial
    function, which is useful for defining decorators, etc.

    Example usage::

        >>> def foo(a, b, c, d):
        ...    ...

        >>> @steal_signature_from(foo)
        ... def bar(*args, **kwargs):
        ...    print(foo, args, kwargs)
        ...    return foo(*args, **kwargs)

        >>> inspect.signature(bar)
        (a, b, c, d)

    Parameters:
        original_func:
            The original function to steal from.
        steal_docstring:
            Defaults to True. Specifies whether the docstring should be appended
            to the new function's existing docstring.

    See:
        :func:`steal_docstring_from`

    """

    def decorator(new_func):
        """Decorates the function with the original_func signature."""
        # Update the signature
        orig_sig = inspect.signature(original_func)
        setattr(new_func, "__signature__", orig_sig)

        if steal_docstring:
            new_doc = getattr(new_func, "__doc__") or ""
            new_doc += "\n\n"
            new_doc += inspect.getdoc(original_func) or ""
            new_doc = new_doc.lstrip()
            setattr(new_func, "__doc__", new_doc)

        return new_func

    return decorator