'Call a function with arguments until it completes without
throwing a Kazoo exception
:param func: Function to call
:param args: Positional arguments to call the function with
:params kwargs: Keyword arguments to call the function with
The function will be called until it doesn\'t throw one of the
retryable exceptions (ConnectionLoss, OperationTimeout, or
ForceRetryError), and optionally retrying on session
expiration.'

def __call__(self, func, *args, **kwargs):

    self.reset()
    while True:
        try:
            if ((self.deadline is not None) and (self._cur_stoptime is None)):
                self._cur_stoptime = (time.time() + self.deadline)
            return func(*args, **kwargs)
        except ConnectionClosedError:
            raise
        except self.retry_exceptions:
            if (self._attempts == self.max_tries):
                raise RetryFailedError('Too    many    retry    attempts')
            self._attempts += 1
            sleeptime = (self._cur_delay + (random.randint(0, self.max_jitter) / 100.0))
            if ((self._cur_stoptime is not None) and ((time.time() + sleeptime) >= self._cur_stoptime)):
                raise RetryFailedError('Exceeded    retry    deadline')
            if self.interrupt:
                while (sleeptime > 0):
                    if (sleeptime < 0.1):
                        self.sleep_func(sleeptime)
                        sleeptime -= sleeptime
                    else:
                        self.sleep_func(0.1)
                        sleeptime -= 0.1
                    if self.interrupt():
                        raise InterruptedError()
            else:
                self.sleep_func(sleeptime)
            self._cur_delay = min((self._cur_delay * self.backoff), self.max_delay)
