o
    !d                     @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	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 ddlmZ ddlm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dlmZ ddl Z!ddl"m#Z# ddl m$Z$ ddl!m%Z% ddlZej&rej'j(ej'_)ej*+ Z,e-dZ.da/dd Z0dd Z1dd Z2dd Z3dd Z4e
j5dd Z6dSddZ7dd Z8dTd"d#Z9G d$d% d%ej'Z:G d&d' d'e:Z;G d(d) d)e<Z=G d*d+ d+e<Z>e
j5d,d- Z?e
j5dUd/d0Z@G d1d2 d2ej'ZAG d3d4 d4eAZBG d5d6 d6ej'ZCG d7d8 d8e<ZDG d9d: d:eEZFG d;d< d<e<ZGd=d> ZH		dVdAdBZIdCdD ZJdEdF ZKdGdH ZLG dIdJ dJej'ZMG dKdL dLeZNG dMdN dNe<ZOG dOdP dPeEZPG dQdR dRe<ZQdS )Wa^  Test utilities for the AWS CLI.

This module includes various classes/functions that help in writing
CLI unit/integration tests.  This module should not be imported by
any module **except** for test code.  This is included in the CLI
package so that code that is not part of the CLI can still take
advantage of all the testing utilities we provide.

    N)pformat)PopenPIPE)mock)StringIO)six)Session)ClientError)WaiterError)AWSResponse)load_plugins)	CLIDriver)EnvironmentVariableszawscli.tests.integrationc                    s    fdd}|S )zDecorator to skip tests that should not be run on windows.

    Example usage:

        @skip_if_windows("Not valid")
        def test_some_non_windows_stuff(self):
            self.assertEqual(...)

    c                    s   t t dv | S )N)DarwinLinux)unittestZskipIfplatformsystem)funcreason 4usr/lib/python3.10/site-packages/awscli/testutils.py	decoratorP   s
   z"skip_if_windows.<locals>.decoratorr   )r   r   r   r   r   skip_if_windowsF   s   
r   c                  C   sF   t j } | j}|dtj}|sg }tj	
| |dt | S )N	data_pathZdata_loader)awscliZ	clidrivercreate_clidriversessionZget_config_variablesplitospathsep_LOADERZsearch_pathsextendZregister_component)driverr   r   r   r   r   r   V   s   
r   c                  C   sb   dd l } td u r/tjtj| j}tj|dd}tj|s-t	d}|d u r-t
d|atS )Nr   binawszCould not find "aws" executable.  Either make sure it is on your PATH, or you can explicitly set this value using "set_aws_cmd()")r   AWS_CMDr    pathdirnameabspath__file__joinisfile_search_path_for_cmd
ValueError)r   Z	repo_rootaws_cmdr   r   r   get_aws_cmda   s   r1   c                 C   sB   t jddt jD ]}t j|| }t j|r|  S qd S )NPATH )r    environgetr   r!   r(   r,   r-   )cmd_namer(   Zfull_cmd_pathr   r   r   r.   s   s   r.   c                 C   s   | a d S N)r'   )r0   r   r   r   set_aws_cmd{   s   r8   c              	   c   s    t  }dttd }tj||}t|d  z(t|| }|V  W d   n1 s/w   Y  W t	
| dS W t	
| dS t	
| w )af  This is a cross platform temporary file creation.

    tempfile.NamedTemporary file on windows creates a secure temp file
    that can't be read by other processes and can't be opened a second time.

    For tests, we generally *want* them to be read multiple times.
    The test fixture writes the temp file contents, the test reads the
    temp file.

    z
tmpfile-%s   wN)tempfilemkdtempstrrandom_charsr    r(   r,   opencloseshutilrmtree)modeZtemporary_directorybasenameZfull_filenamefr   r   r   temporary_file   s   rF   c              
   C   s   |sd}| j d|d}|r|}nt }d|i}|dkr!d|i|d< z|jdi | W |S  tyK } z|jd d	d
kr?n W Y d}~|S d}~ww )zG
    Creates a bucket
    :returns: the name of the bucket created
    	us-west-2s3Zregion_nameBucket	us-east-1ZLocationConstraintZCreateBucketConfigurationErrorCodeZBucketAlreadyOwnedByYouNr   )create_clientrandom_bucket_namecreate_bucketr	   responser5   )r   nameregionclientbucket_nameparamser   r   r   rP      s(   	
rP   c                 C   s   t tt| d dS )zZReturns random hex characters.

    Useful for creating resources with random names.

       ascii)binasciihexlifyr    urandomintdecode)Z	num_charsr   r   r   r>      s   r>   awscli-s3integ-   c                 C   s   | t | S )a  Generate a random S3 bucket name.

    :param prefix: A prefix to use in the bucket name.  Useful
        for tracking resources.  This default value makes it easy
        to see which buckets were created from CLI integ tests.
    :param num_random: Number of random chars to include in the bucket name.

    :returns: The name of a randomly generated bucket name as a string.

    )r>   )prefixZ
num_randomr   r   r   rO      s   rO   c                   @   s    e Zd ZdZdd Zdd ZdS )BaseCLIDriverTestzBase unittest that use clidriver.

    This will load all the default plugins as well so it
    will simulate the behavior the user will see.
    c                 C   sH   t jd ddddd| _td| j| _| j  t | _| jj| _d S )NAWS_DATA_PATHrK   
access_key
secret_keyr3   rc   AWS_DEFAULT_REGIONAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_CONFIG_FILE
os.environ)	r    r4   r   patchenviron_patchstartr   r$   r   selfr   r   r   setUp   s   
zBaseCLIDriverTest.setUpc                 C   s   | j   d S r7   )rm   stopro   r   r   r   tearDown      zBaseCLIDriverTest.tearDownN)__name__
__module____qualname____doc__rq   rs   r   r   r   r   rb      s    rb   c                       sH   e Zd Z fddZ fddZdd Zdd Zd	d
 Zdd Z  Z	S )BaseAWSHelpOutputTestc                    s<   t t|   td| _| j | _t | _	| j	| j_
d S )Nzawscli.help.get_renderer)superry   rq   r   rl   renderer_patchrn   Zrenderer_mockCapturedRendererrendererreturn_valuero   	__class__r   r   rq      s
   zBaseAWSHelpOutputTest.setUpc                    s   t t|   | j  d S r7   )rz   ry   rs   r{   rr   ro   r   r   r   rs      s   zBaseAWSHelpOutputTest.tearDownc                 C   s*   || j jvr| d|| j jf  d S d S )NzFThe expected contents:
%s
were not in the actual rendered contents:
%sr}   rendered_contentsfail)rp   containsr   r   r   assert_contains      
z%BaseAWSHelpOutputTest.assert_containsc                 C   s8   | j j|}||kr| d||| j j|f  d S d S )NzkThe expected contents:
%s
, with the count:
%d
were not in the actual rendered  contents:
%s
with count:
%d)r}   r   countr   )rp   r   r   Zr_countr   r   r   assert_contains_with_count   s   
z0BaseAWSHelpOutputTest.assert_contains_with_countc                 C   s*   || j jv r| d|| j jf  d S d S )NzKThe contents:
%s
were not suppose to be in the actual rendered contents:
%sr   rp   contentsr   r   r   assert_not_contains   r   z)BaseAWSHelpOutputTest.assert_not_containsc                    s   | d}t|}| jj | |   | fdd|D }|d }t|dd  dD ])\}}|dkrB| d||  f  ||k rV| d|| ||d   f  |}q/d S )	Nstarting_fromc                    s   g | ]}  |qS r   )find).0argr   Zstart_indexr   r   
<listcomp>  s    z;BaseAWSHelpOutputTest.assert_text_order.<locals>.<listcomp>r      z/The string %r was not found in the contents: %szBThe string %r came before %r, but was suppose to come after it.
%s)poplistr}   r   assertInr   	enumerater   )rp   argskwargsr   Zarg_indicespreviousiindexr   r   r   assert_text_order  s$   


z'BaseAWSHelpOutputTest.assert_text_order)
ru   rv   rw   rq   rs   r   r   r   r   __classcell__r   r   r   r   ry      s    ry   c                   @   s   e Zd Zdd Zdd ZdS )r|   c                 C   s
   d| _ d S )Nr3   )r   ro   r   r   r   __init__  s   
zCapturedRenderer.__init__c                 C   s   | d| _d S )Nutf-8)r^   r   r   r   r   r   render  s   zCapturedRenderer.renderN)ru   rv   rw   r   r   r   r   r   r   r|     s    r|   c                   @      e Zd Zdd ZdS )CapturedOutputc                 C   s   || _ || _d S r7   )stdoutstderr)rp   r   r   r   r   r   r     s   
zCapturedOutput.__init__N)ru   rv   rw   r   r   r   r   r   r         r   c               	   c   s    t  } t  }td| - td| t|| V  W d    n1 s'w   Y  W d    d S W d    d S 1 s?w   Y  d S )Nz
sys.stderrz
sys.stdout)r   r   r   rl   r   )r   r   r   r   r   capture_output"  s   "r       c                 c   s^    t | }t jrt }||_n|}td| |V  W d    d S 1 s(w   Y  d S )Nz	sys.stdin)r   BytesIOPY3r   Mockbufferrl   )Zinput_bytes
input_dataZmock_objectr   r   r   capture_input+  s   
"r   c                   @   sX   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Z		dddZ	dd Z
dddZdS )BaseAWSCommandParamsTestNc                 C   s   i | _ d | _tjd dddddd| _td| j| _| j  td di d | _	i | _
td	| _d
| _g | _d | _t | _d S )Nrc   rK   rd   re   r3   )rc   rg   rh   ri   rj   ZAWS_SHARED_CREDENTIALS_FILErk      z'botocore.endpoint.Endpoint.make_requestF)last_paramslast_kwargsr    r4   r   rl   rm   rn   r   http_responseparsed_responsemake_request_patchmake_request_is_patchedoperations_calledparsed_responsesr   r$   ro   r   r   r   rq   ;  s$   
zBaseAWSCommandParamsTest.setUpc                 C   (   | j   | jr| j  d| _d S d S NF)rm   rr   r   r   ro   r   r   r   rs   U  s
   


z!BaseAWSCommandParamsTest.tearDownc                 K   s   |  | d S r7   )_store_params)rp   rV   r   r   r   r   before_call\  rt   z$BaseAWSCommandParamsTest.before_callc                 C   s   || _ |d | _d S )Nbody)Zlast_request_dictr   )rp   rV   r   r   r   r   _  s   z&BaseAWSCommandParamsTest._store_paramsc                    sR    j r j  d _  j } jd ur fdd|_n j jf|_d _ d S )NFc                     s    j  jdfS Nr   )r   r   r   )r   r   ro   r   r   <lambda>m  s   z=BaseAWSCommandParamsTest.patch_make_request.<locals>.<lambda>T)	r   r   rr   rn   r   side_effectr   r   r~   )rp   r   r   ro   r   patch_make_requestc  s   



z+BaseAWSCommandParamsTest.patch_make_requestr   c              	   C   s   |  ||\}}}|d ur| || |d urEt| j}	|d ur4|D ]}
z|	|
= W q# ty3   Y q#w ||	krE| dt|t|	f  |||fS )NzGActual params did not match expected params.
Expected:

%s
Actual:

%s
)run_cmdr   copyr   KeyErrorr   r   )rp   cmdrV   expected_rcZstderr_containsZignore_paramsr   r   rcr   keyr   r   r   assert_params_for_cmds  s$   

z.BaseAWSCommandParamsTest.assert_params_for_cmdc                 K   s   || _ | j|| f d S r7   )r   r   appendr   )rp   rV   modelr   r   r   r   before_parameter_build  s   z/BaseAWSCommandParamsTest.before_parameter_buildc           
      C   s   t d| |   | jjd}|d| j |d| j	 t
|ts)| }n|}t &}z| j|}W n tyL } z	|j}W Y d }~nd }~ww W d    n1 sWw   Y  |j }|j }	| ||d||||	|f  |	||fS )NzCalling cmd: %sevent_emitterzbefore-callzbefore-parameter-build.*.*MUnexpected rc (expected: %s, actual: %s) for command: %s
stdout:
%sstderr:
%s)loggingdebugr   r$   r   get_componentregisterr   Zregister_firstr   
isinstancer   r   r   main
SystemExitcoder   getvaluer   assertEqual)
rp   r   r   r   cmdlistcapturedr   rW   r   r   r   r   r   r     s:   


	


z BaseAWSCommandParamsTest.run_cmd)Nr   NNr   )ru   rv   rw   ZmaxDiffrq   rs   r   r   r   r   r   r   r   r   r   r   r   8  s    
r   c                       s(   e Zd Z fddZ fddZ  ZS )BaseAWSPreviewCommandParamsTestc                    s(   t d| _| j  tt|   d S )Nz-awscli.customizations.preview.mark_as_preview)r   rl   preview_patchrn   rz   r   rq   ro   r   r   r   rq     s
   
z%BaseAWSPreviewCommandParamsTest.setUpc                    s   | j   tt|   d S r7   )r   rr   rz   r   rs   ro   r   r   r   rs        
z(BaseAWSPreviewCommandParamsTest.tearDown)ru   rv   rw   rq   rs   r   r   r   r   r   r     s    r   c                   @   s6   e Zd Zdd Zdd Zdi dfddZdd
dZdS )BaseCLIWireResponseTestc                 C   sP   t jd ddddd| _td| j| _| j  td| _d	| _t | _	d S )
Nrc   rK   rd   re   r3   rf   rk   z botocore.endpoint.Endpoint._sendF)
r    r4   r   rl   rm   rn   
send_patchsend_is_patchedr   r$   ro   r   r   r   rq     s   
zBaseCLIWireResponseTest.setUpc                 C   r   r   )rm   rr   r   r   ro   r   r   r   rs     s
   


z BaseCLIWireResponseTest.tearDownr   r   c                 C   s<   | j r| j  d| _ | j }tj|||d|_d| _ d S )NF)status_codeheaderscontentT)r   r   rr   rn   r   r   r~   )rp   r   r   r   r   r   r   r   
patch_send  s   


z"BaseCLIWireResponseTest.patch_sendr   c           	      C   s   t |ts
| }n|}t &}z| j|}W n ty- } z	|j}W Y d }~nd }~ww W d    n1 s8w   Y  |j	 }|j
	 }| ||d|||||f  |||fS )Nr   )r   r   r   r   r$   r   r   r   r   r   r   r   )	rp   r   r   r   r   r   rW   r   r   r   r   r   r     s,   





zBaseCLIWireResponseTest.run_cmdNr   )ru   rv   rw   rq   rs   r   r   r   r   r   r   r     s
    
r   c                   @   s6   e Zd Zdd Zdd ZdddZd	d
 Zdd ZdS )FileCreatorc                 C   s   t  | _d S r7   )r;   r<   rootdirro   r   r   r   r     rt   zFileCreator.__init__c                 C   s"   t j| jrt| j d S d S r7   )r    r(   existsr   rA   rB   ro   r   r   r   
remove_all  s   zFileCreator.remove_allNr:   c                 C   s   t j| j|}t jt j|st t j| t||}|| W d   n1 s0w   Y  t j	|}t 
|||d f |durQt 
|||f |S )a  Creates a file in a tmpdir

        ``filename`` should be a relative path, e.g. "foo/bar/baz.txt"
        It will be translated into a full path in a tmp dir.

        If the ``mtime`` argument is provided, then the file's
        mtime will be set to the provided value (must be an epoch time).
        Otherwise the mtime is left untouched.

        ``mode`` is the mode the file should be opened either as ``w`` or
        `wb``.

        Returns the full path to the file.

        Ni )r    r(   r,   r   isdirr)   makedirsr?   writegetmtimeutime)rp   filenamer   mtimerC   	full_pathrE   Zcurrent_timer   r   r   create_file  s   zFileCreator.create_filec                 C   sp   t j| j|}t jt j|st t j| t|d}|| W d   |S 1 s1w   Y  |S )zAppend contents to a file

        ``filename`` should be a relative path, e.g. "foo/bar/baz.txt"
        It will be translated into a full path in a tmp dir.

        Returns the full path to the file.
        aN)	r    r(   r,   r   r   r)   r   r?   r   )rp   r   r   r   rE   r   r   r   append_file  s   
zFileCreator.append_filec                 C   s   t j| j|S )zzTranslate relative path to full path in temp dir.

        f.full_path('foo/bar.txt') -> /tmp/asdfasd/foo/bar.txt
        )r    r(   r,   r   )rp   r   r   r   r   r      s   zFileCreator.full_path)Nr:   )ru   rv   rw   r   r   r   r   r   r   r   r   r   r     s    
r   c                   @      e Zd ZdS )ProcessTerminatedErrorNru   rv   rw   r   r   r   r   r   (      r   c                   @   s"   e Zd ZdddZedd ZdS )ResultNc                 C   sL   || _ || _|| _td| td| td| |d u r!g }|| _d S )Nzrc: %sz
stdout: %sz
stderr: %s)r   r   r   	INTEG_LOGr   memory_usage)rp   r   r   r   r   r   r   r   r   -  s   
zResult.__init__c                 C   s   t | jS r7   )jsonloadsr   ro   r   r   r   r   8  s   zResult.jsonr7   )ru   rv   rw   r   propertyr   r   r   r   r   r   ,  s    
r   c                 C   s   |  dd} |  dd} | S )N"z\"')replace)commandr   r   r   _escape_quotes=  s   r  FTc                 C   s  t  dkr
t| } dtjv rtjd }ndt  }d|| f }t }t|tj	r1tj
s1||}td| tj }	d|	vrDd|	d< |durJ|}	|du rPt}t|tt|d	|	d
}
|s^|
S d}|sui }|rjd|i}|
jdi |\}}nt|
\}}}t|
j|||||S )a]  Run an aws command.

    This help function abstracts the differences of running the "aws"
    command on different platforms.

    If collect_memory is ``True`` the the Result object will have a list
    of memory usage taken at 2 second intervals.  The memory usage
    will be in bytes.

    If env_vars is None, this will set the environment variables
    to be used by the aws process.

    If wait_for_finish is False, then the Process object is returned
    to the caller.  It is then the caller's responsibility to ensure
    proper cleanup.  This can be useful if you want to test timeout's
    or how the CLI responds to various signals.

    :type input_data: string
    :param input_data: This string will be communicated to the process through
        the stdin of the process.  It essentially allows the user to
        avoid having to use a file handle to pass information to the process.
        Note that this string is not passed on creation of the process, but
        rather communicated to the process.

    :type input_file: a file handle
    :param input_file: This is a file handle that will act as the
        the stdin of the process immediately on creation.  Essentially
        any data written to the file will be read from stdin of the
        process. This is needed if you plan to stream data into stdin while
        collecting memory.
    WindowsZAWS_TEST_COMMANDz	python %sz%s %szRunning command: %srg   rK   NT)r   r   stdinshellenvinputr   )r   r   r  r    r4   r1   get_stdout_encodingr   r   Z	text_typer   encoder   r   r   r   r   communicate_wait_and_collect_memr   
returncoder^   )r  Zcollect_memoryZenv_varsZwait_for_finishr   Z
input_fileZaws_commandZfull_commandZstdout_encodingr  processmemoryr   r   r   r   r   r   r&   G  sD   !




r&   c                  C   s   t tjdd } | d u rd} | S )Nencodingr   )getattrsys
__stdout__)r  r   r   r   r	    s   r	  c                 C   s   t  dkr	t}nt  dkrt}ntdt   g }|  d u r>z|| j}W n	 ty2   Y nw || |  d u s"|  \}}|||fS )Nr   r   z0Can't collect memory for process on platform %s.)	r   r   _get_memory_with_psr/   pollpidr   r   r  )r  Z
get_memoryr  currentr   r   r   r   r   r    s(   

r  c                 C   s`   d  }|t|  t|td}| d }|jdks"tt| t|	 d   d d S )Nzps u -p)r   r   r      i   )
r   r   r=   r   r   r  r  r   r]   
splitlines)r  Zcommand_listpr   r   r   r   r    s   
r  c                   @   s   e Zd ZdZg dZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zd8ddZd9ddZd:ddZdd Zdd Zdd Zd;d!d"Zd#d$ Zd;d%d&Zd;d'd(Zd)d* Zd+d, Zd-d. Z		 d<d/d0Z		 d<d1d2Z		3d=d4d5Zd6d7 ZdS )>BaseS3CLICommandzBase class for aws s3 command.

    This contains convenience functions to make writing these tests easier
    and more streamlined.

    )ZSSECustomerAlgorithmZSSECustomerKeyZSSECustomerKeyMD5ZRequestPayerc                 C   s@   t  | _tj | _i | _d| _| jjd| jd| _| 	  d S )NrG   rH   rI   )
r   filesbotocorer   Zget_sessionregionsrS   rN   rT   extra_setupro   r   r   r   rq     s   zBaseS3CLICommand.setUpc                 C      d S r7   r   ro   r   r   r   r       zBaseS3CLICommand.extra_setupc                 C   s   | j   |   d S r7   )r  r   extra_teardownro   r   r   r   rs     s   
zBaseS3CLICommand.tearDownc                 C   r   r7   r   ro   r   r   r   r"    r!  zBaseS3CLICommand.extra_teardownc                 K   s    | j d}|jdi | d S )NZresponse_parser_factoryr   )r   r   Zset_parser_defaults)rp   r   factoryr   r   r   override_parser  s   z BaseS3CLICommand.override_parserc                 C   s$   | j || j}| jjd|d}|S )NrH   rI   )r  r5   rS   r   rN   )rp   rU   rS   rT   r   r   r   create_client_for_bucket  s   z)BaseS3CLICommand.create_client_for_bucketc                 C   sh   |  || t|tjr| d}| ||}| t|t| ||kr2| 	d||f  d S d S )Nr   z?Contents for %s/%s do not match (but they have the same length))
wait_until_key_existsr   r   r   r   r^   get_key_contentsr   lenr   )rp   bucketr   Zexpected_contentsZactual_contentsr   r   r   assert_key_contents_equal  s   
z*BaseS3CLICommand.assert_key_contents_equalNc                 C   s>   |s| j }t| j||}|| j|< | | j| | | |S r7   )rS   rP   r   r  
addCleanupdelete_bucketwait_bucket_exists)rp   rR   rS   rU   r   r   r   rP     s   

zBaseS3CLICommand.create_bucketr3   c           	         s~     |}|||d}|d ur|| |jdi |}  j|| i }|r5t fdd| D } j|||d |S )N)rJ   KeyBodyc                 3   s&    | ]\}}| j v r||fV  qd S r7   )_PUT_HEAD_SHARED_EXTRAS)r   kvro   r   r   	<genexpr>  s    
z.BaseS3CLICommand.put_object.<locals>.<genexpr>)extra_paramsr   )r%  update
put_objectr+  
delete_keydictitemsr&  )	rp   rU   key_namer   
extra_argsrT   Z	call_argsrQ   Zextra_head_paramsr   ro   r   r6    s&   

zBaseS3CLICommand.put_objectr  c                 C   s   |  | | |}|}	 |d8 }z|j|d W n |jjy5   | |r)Y n|dkr. t| Y nw q| j	|d  d S )NTr   rJ   r   )
remove_all_objectsr%  r,  
exceptionsZNoSuchBucketbucket_not_existstimesleepr  r   )rp   rU   attemptsdelayrT   Zattempts_remainingr   r   r   r,    s"   


zBaseS3CLICommand.delete_bucketc                 C   sb   |  |}|d}|j|d}g }|D ]}|dd |dg D 7 }q|D ]}| || q&d S )NZlist_objectsr<  c                 S   s   g | ]}|d  qS )r.  r   )r   objr   r   r   r   0  s    z7BaseS3CLICommand.remove_all_objects.<locals>.<listcomp>ZContents)r%  Zget_paginatorZpaginater5   r7  )rp   rU   rT   Z	paginatorZpagesZ	key_namesZpager:  r   r   r   r=  *  s   

z#BaseS3CLICommand.remove_all_objectsc                 C   s   |  |}|j||d}d S NrJ   r.  )r%  Zdelete_objectrp   rU   r:  rT   rQ   r   r   r   r7  4  r   zBaseS3CLICommand.delete_keyc                 C   s6   |  || | |}|j||d}|d  dS )NrF  r/  r   )r&  r%  Z
get_objectreadr^   rG  r   r   r   r'  8  s   
z!BaseS3CLICommand.get_key_contents   c                    s8   |   }|dt|dd}| fdd d S )NZbucket_existsT)min_successesdelay_initial_pollc                      s   j  dd u S )Nr<  )waitr   rU   waiterr   r   r   D  s    z5BaseS3CLICommand.wait_bucket_exists.<locals>.<lambda>)r%  
get_waiterConsistencyWaiterrL  )rp   rU   rJ  rT   Zconsistency_waiterr   rM  r   r-  >  s   

z#BaseS3CLICommand.wait_bucket_existsc              
   C   sV   |  |}z	|j|d W dS  ty* } z|jddkr%W Y d }~dS  d }~ww )Nr<  TrM   Z404F)r%  Zhead_bucketr	   rQ   r5   )rp   rU   rT   errorr   r   r   r?  G  s   
z"BaseS3CLICommand.bucket_not_existsc              	   C   0   z| j |||d W dS  ttfy   Y dS w N)rJ  TF)r&  r	   r
   rp   rU   r:  rJ  r   r   r   
key_existsQ     zBaseS3CLICommand.key_existsc              	   C   rR  rS  )wait_until_key_not_existsr	   r
   rT  r   r   r   key_not_existsY  rV  zBaseS3CLICommand.key_not_existsc                 C   s   | j  }|d S )NZBuckets)rT   list_buckets)rp   rQ   r   r   r   rY  a  s   
zBaseS3CLICommand.list_bucketsc                 C   s   |  ||}|d S )NContentType)head_object)rp   rU   r:  parsedr   r   r   content_type_for_keye  s   z%BaseS3CLICommand.content_type_for_keyc                 C   s   |  |}|j||d}|S rE  )r%  r[  rG  r   r   r   r[  i  s   
zBaseS3CLICommand.head_objectc                 C      | j ||||dd d S )NTr   _wait_for_keyrp   rU   r:  r4  rJ  r   r   r   r&  n     

z&BaseS3CLICommand.wait_until_key_existsc                 C   r^  )NFr_  r`  rb  r   r   r   rW  s  rc  z*BaseS3CLICommand.wait_until_key_not_existsTc           
      C   sb   |  |}|r|d}n|d}||d}|d ur || t|D ]
}	|jdi | q$d S )NZobject_existsZobject_not_existsrF  r   )r%  rO  r5  rangerL  )
rp   rU   r:  r4  rJ  r   rT   rN  rV   _r   r   r   ra  x  s   



zBaseS3CLICommand._wait_for_keyc                 C   s^   |  |jdd|j|j|j f  | d|j | d|j | d|j | d|j d S )Nr   zNon zero rc (%s) received: %szError:zfailed:zclient errorzserver error)r   r   r   r   ZassertNotIn)rp   r  r   r   r   assert_no_errors  s   z!BaseS3CLICommand.assert_no_errorsNN)r3   N)r  r  )rI  )NrI  )NrI  T)ru   rv   rw   rx   r0  rq   r  rs   r"  r$  r%  r*  rP   r6  r,  r=  r7  r'  r-  r?  rU  rX  rY  r]  r[  r&  rW  ra  rf  r   r   r   r   r    sB    




	





r  c                   @   r   )StringIOWithFileNoc                 C   s   dS r   r   ro   r   r   r   fileno  s   zStringIOWithFileNo.filenoN)ru   rv   rw   ri  r   r   r   r   rh    r   rh  c                   @   s*   e Zd ZdddZedd Zdd ZdS )	TestEventHandlerNc                 C   s   || _ d| _d| _d S r   )_handler_calledZ__test__)rp   handlerr   r   r   r     s   
zTestEventHandler.__init__c                 C   s   | j S r7   )rl  ro   r   r   r   called  s   zTestEventHandler.calledc                 K   s(   d| _ | jd ur| jdi | d S d S )NTr   )rl  rk  )rp   r   r   r   r   rm    s   
zTestEventHandler.handlerr7   )ru   rv   rw   r   r   rn  rm  r   r   r   r   rj    s
    

rj  c                   @   r   )ConsistencyWaiterExceptionNr   r   r   r   r   ro    r   ro  c                   @   s.   e Zd ZdZ		dddZdd	 Zd
d ZdS )rP  a  
    A waiter class for some check to reach a consistent state.

    :type min_successes: int
    :param min_successes: The minimum number of successful check calls to
    treat the check as stable. Default of 1 success.

    :type max_attempts: int
    :param min_successes: The maximum number of times to attempt calling
    the check. Default of 20 attempts.

    :type delay: int
    :param delay: The number of seconds to delay the next API call after a
    failed check call. Default of 5 seconds.
    r      r  Fc                 C   s   || _ || _|| _|| _d S r7   )rJ  max_attemptsrC  rK  )rp   rJ  rq  rC  rK  r   r   r   r     s   
zConsistencyWaiter.__init__c                 O   s|   d}d}| j rt| j || jk r4|d7 }||i |r)|d7 }|| jkr(dS nt| j || jk s| ||}t|)a  
        Wait until the check succeeds the configured number of times

        :type check: callable
        :param check: A callable that returns True or False to indicate
        if the check succeeded or failed.

        :type args: list
        :param args: Any ordered arguments to be passed to the check.

        :type kwargs: dict
        :param kwargs: Any keyword arguments to be passed to the check.
        r   r   N)rK  r@  rA  rC  rq  rJ  _fail_messagero  )rp   checkr   r   rB  	successesfail_msgr   r   r   rL    s   


zConsistencyWaiter.waitc                 C   s   ||f}d| S )Nz/Failed after %s attempts, only had %s successesr   )rp   rB  rt  Zformat_argsr   r   r   rr    s   zConsistencyWaiter._fail_messageN)r   rp  r  F)ru   rv   rw   rx   r   rL  rr  r   r   r   r   rP    s    
rP  rg  )r_   r`   )r   )FNTNN)Rrx   r    r  r   rA   r@  r   r   r;   r   
contextlibstringrZ   pprintr   
subprocessr   r   r   r   Zawscli.compatr   r   Zbotocore.sessionr   Zbotocore.exceptionsr	   r
   Zbotocore.loadersr  Zbotocore.awsrequestr   Zawscli.clidriverr   Zawscli.pluginr   r   r   ZPY2ZTestCaseZassertItemsEqualZassertCountEqualloadersLoaderr"   	getLoggerr   r'   r   r   r1   r.   r8   contextmanagerrF   rP   r>   rO   rb   ry   objectr|   r   r   r   r   r   r   r   	Exceptionr   r   r  r&   r	  r  r  r  rh  rj  ro  rP  r   r   r   r   <module>   s   	




	3
t5;

E V