
    '(                         S r SSKJr  SSKrSSKrSSKJr  SrSrSr	Sr
 " S S	\5      r " S
 S\5      rS r " S S\5      rg)a  Decorators for applying timeout arguments to functions.

These decorators are used to wrap API methods to apply either a
Deadline-dependent (recommended), constant (DEPRECATED) or exponential
(DEPRECATED) timeout argument.

For example, imagine an API method that can take a while to return results,
such as one that might block until a resource is ready:

.. code-block:: python

    def is_thing_ready(timeout=None):
        response = requests.get('https://example.com/is_thing_ready')
        response.raise_for_status()
        return response.json()

This module allows a function like this to be wrapped so that timeouts are
automatically determined, for example:

.. code-block:: python

    timeout_ = timeout.ExponentialTimeout()
    is_thing_ready_with_timeout = timeout_(is_thing_ready)

    for n in range(10):
        try:
            is_thing_ready_with_timeout({'example': 'data'})
        except:
            pass

In this example the first call to ``is_thing_ready`` will have a relatively
small timeout (like 1 second). If the resource is available and the request
completes quickly, the loop exits. But, if the resource isn't yet available
and the request times out, it'll be retried - this time with a larger timeout.

In the broader context these decorators are typically combined with
:mod:`google.api_core.retry` to implement API methods with a signature that
matches ``api_method(request, timeout=None, retry=None)``.
    )unicode_literalsN)datetime_helpersg      @g      >@g       @c                   F    \ rS rSrSrS\R                  4S jrS rS r	Sr
g)TimeToDeadlineTimeoutF   a  A decorator that decreases timeout set for an RPC based on how much time
has left till its deadline. The deadline is calculated as
``now + initial_timeout`` when this decorator is first called for an rpc.

In other words this decorator implements deadline semantics in terms of a
sequence of decreasing timeouts t0 > t1 > t2 ... tn >= 0.

Args:
    timeout (Optional[float]): the timeout (in seconds) to applied to the
        wrapped function. If `None`, the target function is expected to
        never timeout.
Nc                     Xl         X l        g N)_timeout_clock)selftimeoutclocks      *lib/third_party/google/api_core/timeout.py__init__TimeToDeadlineTimeout.__init__T   s        c                    ^ ^^ T R                  5       R                  5       m[        R                  " T5      UUU 4S j5       nU$ )Apply the timeout decorator.

Args:
    func (Callable): The function to apply the timeout argument to.
        This function must accept a timeout keyword argument.

Returns:
    Callable: The wrapped function.
c                     > TR                   bS  TR                  5       R                  5       nUT-
  S:  a  TnUT-
  nTR                   U-
  nUS:  a  TR                   nXAS'   T" U 0 UD6$ )#Wrapped function that adds timeout.gMbP?   r   )r
   r   	timestamp)argskwargsnow_timestamptime_since_first_attemptremaining_timeoutfirst_attempt_timestampfuncr   s        r   func_with_timeout9TimeToDeadlineTimeout.__call__.<locals>.func_with_timeoute   s     }}( $ 7 7 9
 !#::UB$;M+8;R+R($(MM4L$L! %q((,%$5y!(((r   )r   r   	functoolswraps)r   r   r    r   s   `` @r   __call__TimeToDeadlineTimeout.__call__X   s=     #'++-"9"9";			) 
	)< ! r   c                 8    SR                  U R                  5      $ )Nz&<TimeToDeadlineTimeout timeout={:.1f}>formatr
   r   s    r   __str__TimeToDeadlineTimeout.__str__   s    7>>t}}MMr   )r   r
   )__name__
__module____qualname____firstlineno____doc__r   utcnowr   r$   r*   __static_attributes__ r   r   r   r   F   s&      $+;+B+B ,!\Nr   r   c                   .    \ rS rSrSrSS jrS rS rSrg)	ConstantTimeout   ah  A decorator that adds a constant timeout argument.

DEPRECATED: use ``TimeToDeadlineTimeout`` instead.

This is effectively equivalent to
``functools.partial(func, timeout=timeout)``.

Args:
    timeout (Optional[float]): the timeout (in seconds) to applied to the
        wrapped function. If `None`, the target function is expected to
        never timeout.
Nc                     Xl         g r	   r
   )r   r   s     r   r   ConstantTimeout.__init__   s    r   c                 J   ^ ^ [         R                  " T5      UU 4S j5       nU$ )r   c                  2   > TR                   US'   T" U 0 UD6$ r   r   r8   )r   r   r   r   s     r   r    3ConstantTimeout.__call__.<locals>.func_with_timeout   s#     !%F9(((r   )r"   r#   )r   r   r    s   `` r   r$   ConstantTimeout.__call__   s(     
		) 
	)
 ! r   c                 8    SR                  U R                  5      $ )Nz <ConstantTimeout timeout={:.1f}>r'   r)   s    r   r*   ConstantTimeout.__str__   s    188GGr   r8   r	   )	r,   r-   r.   r/   r0   r   r$   r*   r2   r3   r   r   r5   r5      s     !&Hr   r5   c              #     #    Ub+  [         R                  " 5       [        R                  " US9-   nO[        R                  R                  nU n [         R                  " 5       n[        UU[        XF-
  R                  5      5      v   XR-  nM?  7f)a6  A generator that yields exponential timeout values.

Args:
    initial (float): The initial timeout.
    maximum (float): The maximum timeout.
    multiplier (float): The multiplier applied to the timeout.
    deadline (float): The overall deadline across all invocations.

Yields:
    float: A timeout value.
)seconds)r   r1   datetime	timedeltamaxminfloatrB   )initialmaximum
multiplierdeadlinedeadline_datetimer   nows          r   _exponential_timeout_generatorrN      s      ,3358J8J9
 
 %--11G
%%'$*334
 	
 & s   BBc                   <    \ rS rSrSr\\\\4S jr	S r
S rS rSrg)	ExponentialTimeout   a  A decorator that adds an exponentially increasing timeout argument.

DEPRECATED: the concept of incrementing timeout exponentially has been
deprecated. Use ``TimeToDeadlineTimeout`` instead.

This is useful if a function is called multiple times. Each time the
function is called this decorator will calculate a new timeout parameter
based on the the number of times the function has been called.

For example

.. code-block:: python

Args:
    initial (float): The initial timeout to pass.
    maximum (float): The maximum timeout for any one call.
    multiplier (float): The multiplier applied to the timeout for each
        invocation.
    deadline (Optional[float]): The overall deadline across all
        invocations. This is used to prevent a very large calculated
        timeout from pushing the overall execution time over the deadline.
        This is especially useful in conjunction with
        :mod:`google.api_core.retry`. If ``None``, the timeouts will not
        be adjusted to accommodate an overall deadline.
c                 4    Xl         X l        X0l        X@l        g r	   )_initial_maximum_multiplier	_deadline)r   rH   rI   rJ   rK   s        r   r   ExponentialTimeout.__init__   s      %!r   c                 V    [        U R                  U R                  U R                  US9$ )zReturn a copy of this timeout with the given deadline.

Args:
    deadline (float): The overall deadline across all invocations.

Returns:
    ExponentialTimeout: A new instance with the given deadline.
)rH   rI   rJ   rK   )rP   rS   rT   rU   )r   rK   s     r   with_deadline ExponentialTimeout.with_deadline   s+     "MMMM''	
 	
r   c                    ^^ [        U R                  U R                  U R                  U R                  5      m[
        R                  " T5      UU4S j5       nU$ )r   c                  0   > [        T5      US'   T" U 0 UD6$ r<   )next)r   r   r   timeoutss     r   r    6ExponentialTimeout.__call__.<locals>.func_with_timeout  s#     !%XF9(((r   )rN   rS   rT   rU   rV   r"   r#   )r   r   r    r^   s    ` @r   r$   ExponentialTimeout.__call__
  sO     2MM4==$*:*:DNN
 
		) 
	)
 ! r   c                 z    SR                  U R                  U R                  U R                  U R                  5      $ )NzW<ExponentialTimeout initial={:.1f}, maximum={:.1f}, multiplier={:.1f}, deadline={:.1f}>)r(   rS   rT   rU   rV   r)   s    r   r*   ExponentialTimeout.__str__   s1    228&t}}d.>.>3	
r   )rV   rS   rT   rU   N)r,   r-   r.   r/   r0   _DEFAULT_INITIAL_TIMEOUT_DEFAULT_MAXIMUM_TIMEOUT_DEFAULT_TIMEOUT_MULTIPLIER_DEFAULT_DEADLINEr   rY   r$   r*   r2   r3   r   r   rP   rP      s)    8 )(."
"
 !,
r   rP   )r0   
__future__r   rC   r"   google.api_corer   rc   rd   re   rf   objectr   r5   rN   rP   r3   r   r   <module>rj      sg   &P (   ,  !   ANF ANH%Hf %HP'BS
 S
r   