def retry(exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]]) \
        -> Any:
    """Retry an operation n times if expected *exceptions* are faced.

    .. note::
        Should be used as a decorator of a class' method as it expects the
        first argument to be a class instance.

        The class which method is going to be decorated should contain a couple
        attributes:

        * ``max_retries``: maximum retry attempts before failing;
        * ``retry_wait``: how long in seconds to wait before retrying.

    :param exceptions: exceptions that could trigger a retry attempt.

    :raises:
        :exc:`RetriesExceeded`: if the maximum number of attempts has been
            exhausted.
    """
    def decorator(func: Callable[..., Any]) -> Any:
        def inner_func(instance: object, *args: Any, **kwargs: Any) -> Any:
            times: int = getattr(instance, "max_retries")
            retry_wait: int = getattr(instance, "retry_wait")
            method_name = f"{instance.__class__.__name__}.{func.__name__}"

            attempt = 1

            while attempt <= times:
                try:
                    return func(instance, *args, **kwargs)
                except exceptions as exc:
                    logging.warning("Attempt %d of %d on method %s failed "
                                    "with %r.",
                                    attempt, times, method_name, exc)
                    attempt += 1

                time.sleep(retry_wait)

            raise RetriesExceeded("Maximum number of retries exceeded for "
                                  f"method {method_name}.")
        return inner_func
    return decorator
Retry an operation n times if expected *exceptions* are faced.

    .. note::
        Should be used as a decorator of a class' method as it expects the
        first argument to be a class instance.

        The class which method is going to be decorated should contain a couple
        attributes:

        * ``max_retries``: maximum retry attempts before failing;
        * ``retry_wait``: how long in seconds to wait before retrying.

    :param exceptions: exceptions that could trigger a retry attempt.

    :raises:
        :exc:`RetriesExceeded`: if the maximum number of attempts has been
            exhausted.
    
patroni/scripts/barman/utils.py