Decorator to handle generic waiting situations.

    Will handle StaleElementReferenceErrors.

    :param msg: Error message
    :param exceptions: Extra exceptions to handle
    :param timeout: time to keep trying (default: 10 seconds)
    :return: the result of the decorated function

def wait(msg='', exceptions=None, timeout=10):
    """
    Decorator to handle generic waiting situations.

    Will handle StaleElementReferenceErrors.

    :param msg: Error message
    :param exceptions: Extra exceptions to handle
    :param timeout: time to keep trying (default: 10 seconds)
    :return: the result of the decorated function
    """
    exc = [StaleElementReferenceException]
    if exceptions is not None:
        try:
            exc.extend(iter(exceptions))
        except TypeError:  # exceptions is not iterable
            exc.append(exceptions)
    exc = tuple(exc)

    if not msg:
        msg = "Could not recover from Exception(s): {}".format(', '.join([e.__name__ for e in exc]))

    def wrapper(func):
        def wait_handler(*args, **kwargs):
            import time

            poll_freq = 0.5
            end_time = time.time() + timeout
            while time.time() <= end_time:
                try:
                    value = func(*args, **kwargs)
                    if value:
                        return value
                except exc as e:
                    LOGGER.debug(e)
                    pass  # continue

                time.sleep(poll_freq)
                poll_freq *= 1.25
            raise RuntimeError(msg)
        return wait_handler
    return wrapper