
    )                        d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlmZ ddl	m
Z
 ddlmZ dd	lmZ ddlZd
Z G d de
j"                        Z G d de
j"                        Z G d de
j"                        Z G d d ej*                  ej,                  e            Z G d de      Z G d de      Z	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 ddZd Zy)z-Utilities to support long running operations.    )absolute_import)division)unicode_literalsN)encoding)
exceptions)progress_tracker)retryzThe operations may still be underway remotely and may still succeed; use gcloud list and describe commands or https://console.developers.google.com/ to check resource state.c                       e Zd Zy)TimeoutErrorN__name__
__module____qualname__     )lib/googlecloudsdk/api_lib/util/waiter.pyr   r   &       r   r   c                       e Zd Zy)AbortWaitErrorNr   r   r   r   r   r   *   r   r   r   c                       e Zd Zy)OperationErrorNr   r   r   r   r   r   .   r   r   r   c                   |    e Zd ZdZej
                  d        Zej
                  d        Zej
                  d        Zy)OperationPollera  Interface for defining operation which can be polled and waited on.

  This construct manages operation_ref, operation and result abstract objects.
  Operation_ref is an identifier for operation which is a proxy for result
  object. OperationPoller has three responsibilities:
    1. Given operation object determine if it is done.
    2. Given operation_ref fetch operation object
    3. Given operation object fetch result object
  c                      y)zGiven result of Poll determines if result is done.

    Args:
      operation: object representing operation returned by Poll method.

    Returns:

    Tr   self	operations     r   IsDonezOperationPoller.IsDone=        r   c                      y)zRetrieves operation given its reference.

    Args:
      operation_ref: str, some id for operation.

    Returns:
      object which represents operation.
    Nr   )r   operation_refs     r   PollzOperationPoller.PollI   r   r   c                      y)zGiven operation message retrieves result it represents.

    Args:
      operation: object, representing operation returned by Poll method.
    Returns:
      some object created by given operation.
    Nr   r   s     r   	GetResultzOperationPoller.GetResultU   s     r   N)	r   r   r   __doc__abcabstractmethodr   r"   r$   r   r   r   r   r   2   sU     	 	 	 	  r   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)CloudOperationPollerzlManages a longrunning Operations.

  See https://cloud.google.com/speech/reference/rpc/google.longrunning
  c                      || _         || _        y)a  Sets up poller for cloud operations.

    Args:
      result_service: apitools.base.py.base_api.BaseApiService, api service for
        retrieving created result of initiated operation.
      operation_service: apitools.base.py.base_api.BaseApiService, api service
        for retrieving information about ongoing operation.

      Note that result_service and operation_service Get request must have
      single attribute called 'name'.
    N)result_serviceoperation_service)r   r+   r,   s      r   __init__zCloudOperationPoller.__init__g   s     )D.Dr   c                 t    |j                   r,|j                  rt        |j                  j                        yyz
Overrides.TFdoneerrorr   messager   s     r   r   zCloudOperationPoller.IsDonev   +    ~~	Y__4455r   c                     | j                   j                  d      }| j                   j                   ||j                                     S zOverrides.

    Args:
      operation_ref: googlecloudsdk.core.resources.Resource.

    Returns:
      fetched operation message.
    Getname)r,   GetRequestTyper7   RelativeNamer   r!   request_types      r   r"   zCloudOperationPoller.Poll~   sD     ))88?L!!%%-44679 9r   c                     | j                   j                  d      }t        j                  |j                        }| j                   j                   ||d               S )zOverrides.

    Args:
      operation: api_name_messages.Operation.

    Returns:
      result of result_service.Get request.
    r7   r9   r8   )r+   r:   r   MessageToPyValueresponser7   )r   r   r=   response_dicts       r   r$   zCloudOperationPoller.GetResult   sQ     &&55e<L--i.@.@AM""<]65J#KLLr   Nr   r   r   r%   r-   r   r"   r$   r   r   r   r)   r)   a   s    
/9Mr   r)   c                   *    e Zd ZdZddZd Zd Zd Zy)CloudOperationPollerNoResourceszManages longrunning Operations for Cloud API that creates no resources.

  See https://cloud.google.com/speech/reference/rpc/google.longrunning
  Nc                 *    || _         |xs d | _        y)a3  Sets up poller for cloud operations.

    Args:
      operation_service: apitools.base.py.base_api.BaseApiService, api service
        for retrieving information about ongoing operation.

        Note that the operation_service Get request must have a
        single attribute called 'name'.
      get_name_func: the function to use to get the name from the operation_ref.
        This is to allow polling with non-traditional operation resource names.
        If the resource name is compatible with gcloud parsing, use
        `lambda x: x.RelativeName()`.
    c                 "    | j                         S N)r;   )xs    r   <lambda>z:CloudOperationPollerNoResources.__init__.<locals>.<lambda>   s    0@r   N)r,   get_name)r   r,   get_name_funcs      r   r-   z(CloudOperationPollerNoResources.__init__   s     /D!A&@DMr   c                 t    |j                   r,|j                  rt        |j                  j                        yyr/   r0   r   s     r   r   z&CloudOperationPollerNoResources.IsDone   r4   r   c                     | j                   j                  d      }| j                   j                   || j                  |                  S r6   )r,   r:   r7   rJ   r<   s      r   r"   z$CloudOperationPollerNoResources.Poll   sD     ))88?L!!%%$--679 9r   c                     |j                   S )zOverrides to get the response from the completed operation.

    Args:
      operation: api_name_messages.Operation.

    Returns:
      the 'response' field of the Operation.
    )r@   r   s     r   r$   z)CloudOperationPollerNoResources.GetResult   s     r   rG   rB   r   r   r   rD   rD      s    B"9	r   rD   c                 0   dj                  |      }	 |st        j                  ||      n|5 |rt        |       fd}t	        | |||||	|
||	      }ddd       | j                        S # 1 sw Y   xY w# t
        j                  $ r$ t        dj                  ||dz  t                    t
        j                  $ rQ}t        dj                  ||j                  j                  dz  |j                  j                  t                    d}~ww xY w)aA  Waits for poller.Poll and displays pending operation spinner.

  Args:
    poller: OperationPoller, poller to use during retrials.
    operation_ref: object, passed to operation poller poll method.
    message: str, string to display for default progress_tracker.
    custom_tracker: ProgressTracker, progress_tracker to use for display.
    tracker_update_func: func(tracker, result, status), tracker update function.
    pre_start_sleep_ms: int, Time to wait before making first poll request.
    max_retrials: int, max number of retrials before raising RetryException.
    max_wait_ms: int, number of ms to wait before raising WaitException.
    exponential_sleep_multiplier: float, factor to use on subsequent retries.
    jitter_ms: int, random (up to the value) additional sleep between retries.
    wait_ceiling_ms: int, Maximum wait between retries.
    sleep_ms: int or iterable: for how long to wait between trials.

  Returns:
    poller.GetResult(operation).

  Raises:
    AbortWaitError: if ctrl-c was pressed.
    TimeoutError: if retryer has finished without being done.
  z!Aborting wait for operation {0}.
)aborted_messagec                 @    r | |       y j                          y rG   )Tick)resultstatustrackertracker_update_funcs     r   _StatusUpdatezWaitFor.<locals>._StatusUpdate   s    
gvv
6
,,.r   Nz2Operation {0} has not finished in {1} seconds. {2}  zIOperation {0} has not finished in {1} seconds after max {2} retrials. {3})formatr   ProgressTracker_SleepMsPollUntilDoner	   WaitExceptionr   _TIMEOUT_MESSAGEMaxRetrialsExceptionstatetime_passed_msretrialr$   )pollerr!   r3   custom_trackerrV   pre_start_sleep_msmax_retrialsmax_wait_msexponential_sleep_multiplier	jitter_mswait_ceiling_mssleep_msrP   rW   r   erU   s       `           @r   WaitForrm      s!   F 9??N/#  
	)	)
!/
03:	#$  
-{
&	?
M#i
0> 
		)	$$?
0 
0$ 
		 G
<	{d24D	EG G 
	#	# #
	&	&&$. 
"# ##s0   A< 'A0A< 0A95A< <ADADDc	                      t        j                  ||||||      }	 fd}
|	j                   j                  |f|
|      }|S )a  Waits for poller.Poll to complete.

  Note that this *does not* print nice messages to stderr for the user; most
  callers should use WaitFor instead for the best UX unless there's a good
  reason not to print.

  Args:
    poller: OperationPoller, poller to use during retrials.
    operation_ref: object, passed to operation poller poll method.
    max_retrials: int, max number of retrials before raising RetryException.
    max_wait_ms: int, number of ms to wait before raising WaitException.
    exponential_sleep_multiplier: float, factor to use on subsequent retries.
    jitter_ms: int, random (up to the value) additional sleep between retries.
    wait_ceiling_ms: int, Maximum wait between retries.
    sleep_ms: int or iterable: for how long to wait between trials.
    status_update: func(result, state) called right after each trial.

  Returns:
    The return value from poller.Poll.
  )rf   rg   rh   ri   rj   status_update_funcc                 (    j                  |        S rG   )r   )r   unused_staterc   s     r   
_IsNotDonez!PollUntilDone.<locals>._IsNotDone?  s    }}Y'''r   )funcargsshould_retry_ifrk   )r	   RetryerRetryOnResultr"   )rc   r!   rf   rg   rh   ri   rj   rk   status_updateretryerrr   r   s   `           r   r\   r\     s\    : MM#?%&('( ##;; 	 $ ) 
r   c                 4    t        j                  | dz         y )NrX   )timesleep)milisecondss    r   r[   r[   K  s    **[4 r   )
NNNrX   N@w ffffff?rX       )Nr~   r   rX   r   r   N)r%   
__future__r   r   r   r&   r{   apitools.base.pyr   googlecloudsdk.corer   googlecloudsdk.core.consoler   googlecloudsdk.core.utilr	   sixr^   Errorr   r   r   with_metaclassABCMetaobjectr   r)   rD   rm   r\   r[   r   r   r   <module>r      s     4 &  ' 
  % * 8 * 
F :## Z%% Z%% ,(c((f= ,^5M? 5Mp7o 7x  $#),"D%P  $%/2 "( $.b!r   