<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def retry_loop(retries, delay_in_seconds, conditions, function):
 """ Actually performs the retry loop used by the retry decorator and handler functions. Failures for retrying are defined by the RetryConditions passed in. If the maximum number of retries has been reached then it raises the most recent error or a ValueError on the most recent result value. Args: retries (Integral):
 Maximum number of times to retry. delay_in_seconds (Integral):
 Number of seconds to wait between retries. conditions (list):
 A list of retry conditions the can trigger a retry on a return value or exception. function (function):
 The function to wrap. Returns: value: The return value from function """

    if not isinstance(retries, Integral):
        raise TypeError(retries)

    if delay_in_seconds < 0:
        raise TypeError(delay_in_seconds)

    attempts = 0
    value = None
    err = None
    while attempts <= retries:
        try:
            value = function()
            for condition in conditions:
                if condition.on_value(value):
                    break
            else:
                return value
        except Exception as exc:
            err = exc
            for condition in conditions:
                if condition.on_exception(exc):
                    break
            else:
                raise

        attempts += 1
        sleep(delay_in_seconds)
    else:
        if err:
            raise err
        else:
            raise ValueError(
                "Max retries ({}) reached and return the value is still {}."
                .format(attempts, value)
            )

    return value