
    Vh                     t    d dl mZ 	 d dlmZ dZ G d d      Zdde	de	fdZ
y# e$ rZdZeZY dZ["dZ[ww xY w)	    )deepcopyNc                   8    e Zd ZdZd Zed        Zd ZdefdZ	y)BaseWaiterFactorya   
    A helper class used for creating additional waiters.
    Unlike the waiters available directly from botocore these waiters will
    automatically retry on common (temporary) AWS failures.

    This class should be treated as an abstract class and subclassed before use.
    A subclass should:
    - override _BaseWaiterFactory._waiter_model_data to return the data defining
      the waiter

    Usage:
    waiter_factory = BaseWaiterFactory()
    waiter = waiter_factory.get_waiter(client, 'my_waiter_name')
    waiter.wait(**params)
    c                     t         sy | j                  | j                        }t        j                  t	        d|            | _        y )N   )versionwaiters)waiter_config)botocore_waiter_inject_ratelimit_retries_waiter_model_dataWaiterModeldict_model)selfdatas     j/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/amazon/aws/plugins/module_utils/waiter.py__init__zBaseWaiterFactory.__init__)   s<    
 --d.E.EF%11q$7
    c                     t               S )at  
        Subclasses should override this method to return a dictionary mapping
        waiter names to the waiter definition.

        This data is similar to the data found in botocore's waiters-2.json
        files (for example: botocore/botocore/data/ec2/2016-11-15/waiters-2.json)
        with two differences:
        1) Waiter names do not have transformations applied during lookup
        2) Only the 'waiters' data is required, the data is assumed to be
           version 2

        for example:

        @property
        def _waiter_model_data(self):
            return dict(
                tgw_attachment_deleted=dict(
                    operation='DescribeTransitGatewayAttachments',
                    delay=5, maxAttempts=120,
                    acceptors=[
                        dict(state='retry', matcher='pathAll', expected='deleting', argument='TransitGatewayAttachments[].State'),
                        dict(state='success', matcher='pathAll', expected='deleted', argument='TransitGatewayAttachments[].State'),
                        dict(state='success', matcher='path', expected=True, argument='length(TransitGatewayAttachments[]) == `0`'),
                        dict(state='success', matcher='error', expected='InvalidRouteTableID.NotFound'),
                    ]
                ),
            )

        or

        @property
        def _waiter_model_data(self):
            return {
                "instance_exists": {
                    "delay": 5,
                    "maxAttempts": 40,
                    "operation": "DescribeInstances",
                    "acceptors": [
                        {
                            "matcher": "path",
                            "expected": true,
                            "argument": "length(Reservations[]) > `0`",
                            "state": "success"
                        },
                        {
                            "matcher": "error",
                            "expected": "InvalidInstanceID.NotFound",
                            "state": "retry"
                        }
                    ]
                },
            }
        )r   )r   s    r   r   z$BaseWaiterFactory._waiter_model_data5   s    p vr   c                     g d}g }|D ]  }|j                  t        dd|             ! t        |      }|D ]  }||   d   j                  |        |S )N)RequestLimitExceededUnavailableServiceUnavailableInternalFailureInternalErrorTooManyRequestsException
Throttlingretryerror)statematcherexpected	acceptors)appendr   r   extend)r   
model_dataextra_retriesr$   r    _model_datawaiter_names          r   r   z+BaseWaiterFactory._inject_ratelimit_retrieso   su    
 	" 	SET5QR	S z*& 	DK$[188C	D r   r*   c                     t         rt         | j                  j                  }||vrt        d| d|       t	        j
                  || j                  |      S )NzUnable to find waiter z.  Available_waiters: )import_errorr   waiter_namesNotImplementedErrorr   create_waiter_with_client)r   clientr*   r	   s       r   
get_waiterzBaseWaiterFactory.get_waiter   s`     ++**g%%(>{mKabiaj&kll88KK
 	
r   N)
__name__
__module____qualname____doc__r   propertyr   r   strr1    r   r   r   r      s2     

 7 7r*
c 
r   r   timeoutdefault_pausec                 ~    |}| |dz  k  rt        d| dz        }d| |z  z   }|dz
  |z  | k  r|dz  }t        ||      S )a-  
    Generates the waiter_config dict that allows configuring a custom wait_timeout

    Where the pause and the timeouts aren't perfectly divisible, this will default to waiting
    slightly longer than the configured timeout so that we give at least the timeout time for a
    change to happen.
          )DelayMaxAttempts)maxr   )r9   r:   pauseattemptss       r   custom_waiter_configrC      s^     E -!#$Aw!|$Gu$%H1'Ae22r   )r   )copyr   botocore.waiterwaiterr   r,   ImportErrorer   intrC   r8   r   r   <module>rJ      sT    -Ly
 y
x3# 3c 3C  OLs   $ 727