def unwrap(obj):
    """
        Unwrap a wrapped object. Different from 'inspect.unwrap' in that it will
        also unwrap method objects into the function they wrap. If the object wraps
        no other objects, it will be returned unchanged
    :param obj: Object to unwrap
    :return: Unwrapped object
    """
    while hasattr(obj, "__func__") or hasattr(obj, "__wrapped__"):
        if getattr(obj, "__wrapped__", None) is not None:
            obj = obj.__wrapped__
        elif getattr(obj, "__func__", None) is not None:
            obj = obj.__func__
    return obj