from typing import Any, Optional

from botocore.exceptions import ConnectionError as ConnectionError
from botocore.exceptions import ConnectTimeoutError as ConnectTimeoutError
from botocore.exceptions import HTTPClientError as HTTPClientError
from botocore.exceptions import ReadTimeoutError as ReadTimeoutError
from botocore.retries import quota as quota
from botocore.retries import special as special
from botocore.retries.base import BaseRetryableChecker as BaseRetryableChecker
from botocore.retries.base import BaseRetryBackoff as BaseRetryBackoff

DEFAULT_MAX_ATTEMPTS: int

def register_retry_handler(client: Any, max_attempts: Any = ...) -> Any: ...

class RetryHandler:
    def __init__(
        self, retry_policy: Any, retry_event_adapter: Any, retry_quota: Any
    ) -> None: ...
    def needs_retry(self, **kwargs: Any) -> Any: ...

class RetryEventAdapter:
    def create_retry_context(self, **kwargs: Any) -> Any: ...
    def adapt_retry_response_from_context(self, context: Any) -> None: ...

class RetryContext:
    attempt_number: Any = ...
    operation_model: Any = ...
    parsed_response: Any = ...
    http_response: Any = ...
    caught_exception: Any = ...
    request_context: Any = ...
    def __init__(
        self,
        attempt_number: Any,
        operation_model: Optional[Any] = ...,
        parsed_response: Optional[Any] = ...,
        http_response: Optional[Any] = ...,
        caught_exception: Optional[Any] = ...,
        request_context: Optional[Any] = ...,
    ) -> None: ...
    def get_error_code(self) -> Any: ...
    def add_retry_metadata(self, **kwargs: Any) -> None: ...
    def get_retry_metadata(self) -> Any: ...

class RetryPolicy:
    def __init__(self, retry_checker: Any, retry_backoff: Any) -> None: ...
    def should_retry(self, context: Any) -> Any: ...
    def compute_retry_delay(self, context: Any) -> Any: ...

class ExponentialBackoff(BaseRetryBackoff):
    def __init__(self, max_backoff: int = ..., random: Any = ...) -> None: ...
    def delay_amount(self, context: Any) -> Any: ...

class MaxAttemptsChecker(BaseRetryableChecker):
    def __init__(self, max_attempts: Any) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class TransientRetryableChecker(BaseRetryableChecker):
    def __init__(
        self,
        transient_error_codes: Optional[Any] = ...,
        transient_status_codes: Optional[Any] = ...,
        transient_exception_cls: Optional[Any] = ...,
    ) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class ThrottledRetryableChecker(BaseRetryableChecker):
    def __init__(self, throttled_error_codes: Optional[Any] = ...) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class ModeledRetryableChecker(BaseRetryableChecker):
    def __init__(self) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class ModeledRetryErrorDetector:
    TRANSIENT_ERROR: str = ...
    THROTTLING_ERROR: str = ...
    def detect_error_type(self, context: Any) -> Any: ...

class ThrottlingErrorDetector:
    def __init__(self, retry_event_adapter: Any) -> None: ...
    def is_throttling_error(self, **kwargs: Any) -> Any: ...

class StandardRetryConditions(BaseRetryableChecker):
    def __init__(self, max_attempts: Any = ...) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class OrRetryChecker(BaseRetryableChecker):
    def __init__(self, checkers: Any) -> None: ...
    def is_retryable(self, context: Any) -> Any: ...

class RetryQuotaChecker:
    def __init__(self, quota: Any) -> None: ...
    def acquire_retry_quota(self, context: Any) -> Any: ...
    def release_retry_quota(
        self, context: Any, http_response: Any, **kwargs: Any
    ) -> None: ...
