Executes a method until the retry limit or validation_fn returns True.

  The method is always called once so the effective lower limit for 'limit' is
  1.  Passing in a number less than 1 will still result it the method being
  called once.

  Args:
    method: The method to execute should take no arguments.
    limit: The number of times to try this method.  Must be >0.
    validation_fn: The validation function called on the function result to
        determine whether to keep looping.
    sleep_s: The time to sleep in between invocations.
    catch_exceptions: Tuple of exception types to catch and count as failures.
  Returns:
      Whatever the method last returned, implicit False would indicate the
        method never succeeded.

def retry_until_valid_or_limit_reached(method, limit, validation_fn, sleep_s=1,
                                       catch_exceptions=()):
  """Executes a method until the retry limit or validation_fn returns True.

  The method is always called once so the effective lower limit for 'limit' is
  1.  Passing in a number less than 1 will still result it the method being
  called once.

  Args:
    method: The method to execute should take no arguments.
    limit: The number of times to try this method.  Must be >0.
    validation_fn: The validation function called on the function result to
        determine whether to keep looping.
    sleep_s: The time to sleep in between invocations.
    catch_exceptions: Tuple of exception types to catch and count as failures.
  Returns:
      Whatever the method last returned, implicit False would indicate the
        method never succeeded.
  """
  assert limit > 0, 'Limit must be greater than 0'

  def _execute_method(helper):
    try:
      return method()
    except catch_exceptions:
      if not helper.remaining:
        raise
      return None

  helper = RetryHelper(limit - 1)
  result = _execute_method(helper)
  while not validation_fn(result) and helper.retry_if_possible():
    time.sleep(sleep_s)
    result = _execute_method(helper)
  return result