Return the parent function of a wrapped function (wrapped with
    :class:`functools.partial` and :class:`add_args`).

    :param func:
        Wrapped function.
    :type func: callable

    :param input_id:
        Index of the first input of the wrapped function.
    :type input_id: int

    :return:
        Parent function.
    :rtype: callable

def parent_func(func, input_id=None):
    """
    Return the parent function of a wrapped function (wrapped with
    :class:`functools.partial` and :class:`add_args`).

    :param func:
        Wrapped function.
    :type func: callable

    :param input_id:
        Index of the first input of the wrapped function.
    :type input_id: int

    :return:
        Parent function.
    :rtype: callable
    """
    if isinstance(func, functools.partial):
        if input_id is not None:
            # noinspection PyTypeChecker
            input_id += len(func.args)
        return parent_func(func.func, input_id=input_id)

    elif isinstance(func, add_args):
        if input_id is not None:
            input_id -= func.n
        return parent_func(func.func, input_id=input_id)

    if input_id is None:
        return func
    else:
        return func, input_id