o
    .&ßaÈ5  ã                   @   s$  d dl Z d dlZd dlZd dlmZ d dlmZmZmZm	Z	m
Z
 e e¡Zde	e
eegiZdd„ Zdd„ Zd%d	d
„Zd%dd„Zd%dd„Zdd„ Zdd„ Zdd„ ZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd „ d eƒZG d!d"„ d"eƒZG d#d$„ d$eƒZdS )&é    N)Úcrc32)ÚChecksumErrorÚEndpointConnectionErrorÚReadTimeoutErrorÚConnectionErrorÚConnectionClosedErrorÚGENERAL_CONNECTION_ERRORc                 C   s:   | dkr	t   ¡ } n
| dkrtd|  ƒ‚| ||d   }|S )a1  Calculate time to sleep based on exponential function.

    The format is::

        base * growth_factor ^ (attempts - 1)

    If ``base`` is set to 'rand' then a random number between
    0 and 1 will be used as the base.
    Base must be greater than 0, otherwise a ValueError will be
    raised.

    Úrandr   z0The 'base' param must be greater than 0, got: %sé   )ÚrandomÚ
ValueError)ÚbaseÚgrowth_factorÚattemptsÚtime_to_sleep© r   ú7/usr/lib/python3/dist-packages/botocore/retryhandler.pyÚdelay_exponential'   s   
ÿr   c                 C   s   t jt| |d�S )z§Create an exponential delay function based on the attempts.

    This is used so that you only have to pass it the attempts
    parameter to calculate the delay.

    ©r   r   )Ú	functoolsÚpartialr   r   r   r   r   Ú!create_exponential_delay_function=   s   ÿr   c                 C   s$   t | |d�}t| |d�}t||d�S )N)Úoperation_name)ÚcheckerÚaction)Ú create_checker_from_retry_configÚcreate_retry_action_from_configÚRetryHandler)Úconfigr   r   r   r   r   r   Úcreate_retry_handlerH   s   ÿÿr   c                 C   s0   | d d }|d dkrt |d |d d�S d S )NÚ__default__ÚdelayÚtypeÚexponentialr   r   r   )r   )r   r   Údelay_configr   r   r   r   P   s   þÿr   c                 C   sü   g }d }g }d| v r5| d   dg ¡}| d d }|D ]}|| }| t|ƒ¡ t|ƒ}|d ur4| |¡ q|d urc|   |¡d urc| | d }	|	D ]}| t|	| ƒ¡ t|	| ƒ}|d urb| |¡ qHt|ƒdkrqt|d |d�S t|ƒ}
t|
|t|ƒd�S )Nr    ÚpoliciesÚmax_attemptsr
   r   )r&   )r&   Úretryable_exceptions)	ÚgetÚappendÚ_create_single_checkerÚ_extract_retryable_exceptionÚextendÚlenÚMaxAttemptsDecoratorÚMultiCheckerÚtuple)r   r   Úcheckersr&   r'   r%   ÚkeyÚcurrent_configÚretry_exceptionÚoperation_policiesÚmulti_checkerr   r   r   r   \   s<   
€ÿ
€þr   c                 C   s2   d| d v rt | d d ƒS d| d v rtƒ S d S )NÚresponseÚapplies_whenÚsocket_errors)Ú_create_single_response_checkerÚExceptionRaiser)r   r   r   r   r*   {   s   
ÿÿr*   c                 C   s\   d| v rt | d | d d�}|S d| v rt| d d�}|S d| v r*t| d d�}|S tdƒ‚)NÚservice_error_codeÚhttp_status_code)Ústatus_codeÚ
error_code)r>   Ú	crc32body)ÚheaderzUnknown retry policy)ÚServiceErrorCodeCheckerÚHTTPStatusCodeCheckerÚCRC32Checkerr   )r7   r   r   r   r   r:   ƒ   s   þøÿûÿr:   c                 C   sN   | d }d|  di ¡v rtgS d|v r%g }|d D ]	}| t| ¡ q|S d S )Nr8   r@   r7   r9   )r(   r   r,   ÚEXCEPTION_MAP)r   r8   Ú
exceptionsÚnamer   r   r   r+   “   s   ür+   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )r   a¯  Retry handler.

    The retry handler takes two params, ``checker`` object
    and an ``action`` object.

    The ``checker`` object must be a callable object and based on a response
    and an attempt number, determines whether or not sufficient criteria for
    a retry has been met.  If this is the case then the ``action`` object
    (which also is a callable) determines what needs to happen in the event
    of a retry.

    c                 C   ó   || _ || _d S ©N)Ú_checkerÚ_action)Úselfr   r   r   r   r   Ú__init__¬   ó   
zRetryHandler.__init__c                 K   s8   |   |||¡r| j|d�}t d|¡ |S t d¡ dS )z›Handler for a retry.

        Intended to be hooked up to an event handler (hence the **kwargs),
        this will process retries appropriately.

        )r   zRetry needed, action of: %szNo retry needed.N)rJ   rK   ÚloggerÚdebug)rL   r   r7   Úcaught_exceptionÚkwargsÚresultr   r   r   Ú__call__°   s
   zRetryHandler.__call__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rM   rT   r   r   r   r   r   ž   s    r   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚBaseCheckerz Base class for retry checkers.

    Each class is responsible for checking a single criteria that determines
    whether or not a retry should not happen.

    c                 C   s0   |dur
|   ||¡S |dur|  ||¡S tdƒ‚)aÄ  Determine if retry criteria matches.

        Note that either ``response`` is not None and ``caught_exception`` is
        None or ``response`` is None and ``caught_exception`` is not None.

        :type attempt_number: int
        :param attempt_number: The total number of times we've attempted
            to send the request.

        :param response: The HTTP response (if one was received).

        :type caught_exception: Exception
        :param caught_exception: Any exception that was caught while trying to
            send the HTTP response.

        :return: True, if the retry criteria matches (and therefore a retry
            should occur.  False if the criteria does not match.

        Nz,Both response and caught_exception are None.)Ú_check_responseÚ_check_caught_exceptionr   )rL   Úattempt_numberr7   rQ   r   r   r   rT   Å   s   ÿzBaseChecker.__call__c                 C   ó   d S rI   r   ©rL   r\   r7   r   r   r   rZ   ã   ó   zBaseChecker._check_responsec                 C   r]   rI   r   ©rL   r\   rQ   r   r   r   r[   æ   r_   z#BaseChecker._check_caught_exceptionN)rU   rV   rW   rX   rT   rZ   r[   r   r   r   r   rY   ¾   s
    rY   c                   @   s*   e Zd ZdZd	dd„Zdd„ Zdd„ ZdS )
r.   a“  Allow retries up to a maximum number of attempts.

    This will pass through calls to the decorated retry checker, provided
    that the number of attempts does not exceed max_attempts.  It will
    also catch any retryable_exceptions passed in.  Once max_attempts has
    been exceeded, then False will be returned or the retryable_exceptions
    that was previously being caught will be raised.

    Nc                 C   s   || _ || _|| _d S rI   )rJ   Ú_max_attemptsÚ_retryable_exceptions)rL   r   r&   r'   r   r   r   rM   ô   s   
zMaxAttemptsDecorator.__init__c                 C   sX   |   |||¡}|r*|| jkr(|d ur d|d v r d|d d d< t d|¡ dS |S dS )NÚResponseMetadatar
   TÚMaxAttemptsReachedz0Reached the maximum number of retry attempts: %sF)Ú_should_retryra   rO   rP   )rL   r\   r7   rQ   Úshould_retryr   r   r   rT   ù   s   ÿ
ÿzMaxAttemptsDecorator.__call__c              
   C   sh   | j r-|| jk r-z|  |||¡W S  | j y, } ztjd|dd� W Y d }~dS d }~ww |  |||¡S )Nz,retry needed, retryable exception caught: %sT)Úexc_info)rb   ra   rJ   rO   rP   )rL   r\   r7   rQ   Úer   r   r   re   	  s   
ÿ€ýz"MaxAttemptsDecorator._should_retryrI   )rU   rV   rW   rX   rM   rT   re   r   r   r   r   r.   ê   s
    
	r.   c                   @   ó   e Zd Zdd„ Zdd„ ZdS )rC   c                 C   ó
   || _ d S rI   )Ú_status_code)rL   r>   r   r   r   rM     ó   
zHTTPStatusCodeChecker.__init__c                 C   s&   |d j | jkrt d| j¡ dS dS )Nr   z5retry needed: retryable HTTP status code received: %sTF)r>   rk   rO   rP   r^   r   r   r   rZ     s   þz%HTTPStatusCodeChecker._check_responseN©rU   rV   rW   rM   rZ   r   r   r   r   rC     ó    rC   c                   @   ri   )rB   c                 C   rH   rI   )rk   Ú_error_code)rL   r>   r?   r   r   r   rM   '  rN   z ServiceErrorCodeChecker.__init__c                 C   sJ   |d j | jkr#|d  di ¡ d¡}|| jkr#t d| j| j¡ dS dS )Nr   r
   ÚErrorÚCodez>retry needed: matching HTTP status and error code seen: %s, %sTF)r>   rk   r(   ro   rO   rP   )rL   r\   r7   Úactual_error_coder   r   r   rZ   +  s   
þz'ServiceErrorCodeChecker._check_responseNrm   r   r   r   r   rB   &  ó    rB   c                   @   ri   )r/   c                 C   rj   rI   ©Ú	_checkers)rL   r1   r   r   r   rM   7  rl   zMultiChecker.__init__c                 C   s(   | j D ]}||||ƒ}|r|  S qdS )NFrt   )rL   r\   r7   rQ   r   Úchecker_responser   r   r   rT   :  s   
ÿÿzMultiChecker.__call__N)rU   rV   rW   rM   rT   r   r   r   r   r/   6  rn   r/   c                   @   ri   )rD   c                 C   rj   rI   )Ú_header_name)rL   rA   r   r   r   rM   D  s   
zCRC32Checker.__init__c                 C   sv   |d }|j  | j¡}|d u rt d| j¡ d S t|d jƒd@ }|t|ƒks9t dt|ƒ|¡ tdt|ƒ|d�‚d S )Nr   z?crc32 check skipped, the %s header is not in the http response.l   ÿÿ z>retry needed: crc32 check failed, expected != actual: %s != %sr   )Úchecksum_typeÚexpected_checksumÚactual_checksum)	Úheadersr(   rw   rO   rP   r   ÚcontentÚintr   )rL   r\   r7   Úhttp_responseÚexpected_crcÚactual_crc32r   r   r   rZ   H  s"   ÿþþüzCRC32Checker._check_responseNrm   r   r   r   r   rD   C  rs   rD   c                   @   s   e Zd ZdZdd„ ZdS )r;   z`Raise any caught exceptions.

    This class will raise any non None ``caught_exception``.

    c                 C   s   |‚rI   r   r`   r   r   r   r[   _  s   z'ExceptionRaiser._check_caught_exceptionN)rU   rV   rW   rX   r[   r   r   r   r   r;   Y  s    r;   rI   ) r   r   ÚloggingÚbinasciir   Úbotocore.exceptionsr   r   r   r   r   Ú	getLoggerrU   rO   rE   r   r   r   r   r   r*   r:   r+   Úobjectr   rY   r.   rC   rB   r/   rD   r;   r   r   r   r   Ú<module>   s6   
þÿ


 ,.