
    Pel9                     Z   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j                  e      Zdeee
e	giZd Zd ZddZddZdd	Zd
 Zd Zd Z G d d      Z G d d      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Zy)    N)crc32)ChecksumErrorConnectionClosedErrorConnectionErrorEndpointConnectionErrorReadTimeoutErrorGENERAL_CONNECTION_ERRORc                 v    | dk(  rt        j                          } n| dk  rt        d|        | ||dz
  z  z  }|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   z.The 'base' param must be greater than 0, got:    )random
ValueError)basegrowth_factorattemptstime_to_sleeps       7/usr/lib/python3/dist-packages/botocore/retryhandler.pydelay_exponentialr   +   sO     v~}}	<TFC
 	
 Mhl;<M    c                 :    t        j                  t        | |      S )zCreate 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   s     r   !create_exponential_delay_functionr   B   s     M r   c                 P    t        | |      }t        | |      }t        ||      S )N)operation_name)checkeraction) create_checker_from_retry_configcreate_retry_action_from_configRetryHandler)configr   r   r   s       r   create_retry_handlerr#   N   s1    .~G -~F 77r   c                 J    | d   d   }|d   dk(  rt        |d   |d         S y )N__default__delaytypeexponentialr   r   r   )r   )r"   r   delay_configs      r   r    r    X   sB    
 -(1LF},0f%&7
 	
 -r   c                    g }d }g }d| v rb| d   j                  dg       }| d   d   }|D ]@  }||   }|j                  t        |             t        |      }|0|j	                  |       B |_| j                  |      N| |   d   }	|	D ]A  }|j                  t        |	|                t        |	|         }|1|j	                  |       C t        |      dk(  rt        |d   |      S t        |      }
t        |
|t        |            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_checkers              r   r   r   e   sB   HL-(,,Z<m,^< 	=C%c]NOO2>BC:>JO*$++O<	= !fjj&@&L#N3J?% 	=COO23Ec3JKL:"3'O *$++O<	= 8}#HQKlKK$X.#%!&';!<
 	
r   c                 V    d| d   v rt        | d   d         S d| d   v r
t               S y )Nresponseapplies_whensocket_errors)_create_single_response_checkerExceptionRaiser)r"   s    r   r0   r0      sF    VN++.>":.
 	
 
F>2	2   
3r   c                     d| v rt        | d   | d         }|S d| v rt        | d         }|S d| v rt        | d         }|S t        d      )Nservice_error_codehttp_status_code)status_code
error_code)rF   	crc32body)headerzUnknown retry policy)ServiceErrorCodeCheckerHTTPStatusCodeCheckerCRC32Checkerr   )r>   r   s     r   rA   rA      s    x') !34 45
 N 
x	'' !34
 N 
	 h{&;< N /00r   c                     | d   }d|j                  di       v rt        gS d|v r&g }|d   D ]  }|j                  t        |           |S y )Nr?   rH   r>   r@   )r.   r   r2   EXCEPTION_MAP)r"   r?   
exceptionsnames       r   r1   r1      sh    .)Ll&&z266	L	(
 1 	3DmD12	3	 
)r   c                       e Zd ZdZd Zd Zy)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                      || _         || _        y N)_checker_action)selfr   r   s      r   __init__zRetryHandler.__init__   s    r   c                 :   |||d}t        | j                  t              r*|d   d   j                  d      }|j	                  d|i        | j                  d
i |r*| j                  |      }t        j                  d|       |S t        j                  d       y	)zHandler for a retry.

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

        )attempt_numberr>   caught_exceptionrequest_dictcontextretriesretries_context)r   zRetry needed, action of: %szNo retry needed.N )
isinstancerT   r4   r.   updaterU   loggerdebug)rV   r   r>   rZ   kwargschecker_kwargsr^   results           r   __call__zRetryHandler.__call__   s     '  0

 dmm%9:$^4Y?CCINO!!#4o"FG4==*>*\\8\4FLL6?M'(r   N)__name__
__module____qualname____doc__rW   rg   r_   r   r   r!   r!      s    )r   r!   c                   "    e Zd ZdZd Zd Zd Zy)BaseCheckerzBase class for retry checkers.

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

    c                 h    || j                  ||      S || j                  ||      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.

        z,Both response and caught_exception are None.)_check_response_check_caught_exceptionr   )rV   rY   r>   rZ   s       r   rg   zBaseChecker.__call__   sJ    , ''AA)// 0  KLLr   c                      y rS   r_   rV   rY   r>   s      r   ro   zBaseChecker._check_response       r   c                      y rS   r_   rV   rY   rZ   s      r   rp   z#BaseChecker._check_caught_exception   rs   r   N)rh   ri   rj   rk   rg   ro   rp   r_   r   r   rm   rm      s    M>r   rm   c                   $    e Zd ZdZddZd Zd Zy)r4   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                 .    || _         || _        || _        y rS   )rT   _max_attempts_retryable_exceptions)rV   r   r,   r-   s       r   rW   zMaxAttemptsDecorator.__init__  s    )%9"r   c                     |r)t        |j                  dd      | j                        |d<   | j                  |||      }|r<|| j                  k\  r+|d|d   v rd|d   d   d<   t        j                  d|       y|S y)	Nmaxr   ResponseMetadatar   TMaxAttemptsReachedz0Reached the maximum number of retry attempts: %sF)r{   r.   rx   _should_retryrb   rc   )rV   rY   r>   rZ   r^   should_retrys         r   rg   zMaxAttemptsDecorator.__call__  s     %(##E1-t/A/A&OE" ))H&6
 !3!33',>(1+,M  QK 23, F" ##r   c                     | j                   r#|| j                  k  r	 | j                  |||      S | j                  |||      S # | j                   $ r"}t        j	                  d|d       Y d }~yd }~ww xY w)Nz,retry needed, retryable exception caught: %sT)exc_info)ry   rx   rT   rb   rc   )rV   rY   r>   rZ   es        r   r~   z"MaxAttemptsDecorator._should_retry0  s    %%.4;M;M*M
}}"H.>  ==;KLL -- B!  
 s   A A4A//A4rS   )rh   ri   rj   rk   rW   rg   r~   r_   r   r   r4   r4     s    :
8Mr   r4   c                       e Zd Zd Zd Zy)rK   c                     || _         y rS   )_status_code)rV   rF   s     r   rW   zHTTPStatusCodeChecker.__init__D  s
    'r   c                 ~    |d   j                   | j                  k(  r!t        j                  d| j                         yy)Nr   z5retry needed: retryable HTTP status code received: %sTF)rF   r   rb   rc   rr   s      r   ro   z%HTTPStatusCodeChecker._check_responseG  s:    A;""d&7&77LLG!! r   Nrh   ri   rj   rW   ro   r_   r   r   rK   rK   C  s    (r   rK   c                       e Zd Zd Zd Zy)rJ   c                      || _         || _        y rS   )r   _error_code)rV   rF   rG   s      r   rW   z ServiceErrorCodeChecker.__init__S  s    '%r   c                     |d   j                   | j                  k(  r_|d   j                  di       j                  d      }|| j                  k(  r,t        j                  d| j                  | j                         yy)Nr   r   ErrorCodez>retry needed: matching HTTP status and error code seen: %s, %sTF)rF   r   r.   r   rb   rc   )rV   rY   r>   actual_error_codes       r   ro   z'ServiceErrorCodeChecker._check_responseW  ss    A;""d&7&77 ( < @ @ H D$4$44%%$$	 r   Nr   r_   r   r   rJ   rJ   R  s    &r   rJ   c                       e Zd Zd Zd Zy)r5   c                     || _         y rS   	_checkers)rV   r7   s     r   rW   zMultiChecker.__init__f  s	    !r   c                 F    | j                   D ]  } ||||      }|s|c S  y)NFr   )rV   rY   r>   rZ   r   checker_responses         r   rg   zMultiChecker.__call__i  s8    ~~ 	(G&*:   ''	( r   N)rh   ri   rj   rW   rg   r_   r   r   r5   r5   e  s    "r   r5   c                       e Zd Zd Zd Zy)rL   c                     || _         y rS   )_header_name)rV   rI   s     r   rW   zCRC32Checker.__init__t  s
    "r   c                 ^   |d   }|j                   j                  | j                        }|!t        j	                  d| j                         y t        |d   j                        dz  }|t        |      k(  s7t        j	                  dt        |      |       t        dt        |      |      y )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.   r   rb   rc   r   contentintr   )rV   rY   r>   http_responseexpected_crcactual_crc32s         r   ro   zCRC32Checker._check_responsex  s     $,,001B1BCLL(!! !!!4!45
BL3|#44% 	 $")&),&7$0  5r   Nr   r_   r   r   rL   rL   s  s    #r   rL   c                       e Zd ZdZd Zy)rB   z`Raise any caught exceptions.

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

    c                     |rS   r_   ru   s      r   rp   z'ExceptionRaiser._check_caught_exception  s
     r   N)rh   ri   rj   rk   rp   r_   r   r   rB   rB     s    r   rB   rS   )r   loggingr   binasciir   botocore.exceptionsr   r   r   r   r   	getLoggerrh   rb   rN   r   r   r#   r    r   r0   rA   r1   r!   rm   r4   rK   rJ   r5   rL   rB   r_   r   r   <module>r      s         
		8	$ 	!.	8


D!$&) &)R+ +\<M; <M~K k &; ; <k r   