o
    Àyð`)V  ã                   @   sÀ  d dl Z d dlmZ d dl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 dlmZmZmZ d dlmZmZmZ d d	lmZmZ d d
lmZmZ d dlmZ d dlm Z m!Z! d dl"m#Z#m$Z$m%Z% d dl&m'Z'm(Z( e  )e*¡Z+G dd„ dƒZ,ddde' d de( ddfdd„Z-G dd„ de.ƒZ/G dd„ de!ƒZ0G dd„ de ƒZ1G dd„ dƒZ2G dd„ de2ƒZ3G d d!„ d!eƒZ4G d"d#„ d#ƒZ5G d$d%„ d%ƒZ6G d&d'„ d'ƒZ7G d(d)„ d)ƒZ8dS )*é    N)ÚBytesIO)ÚUNSIGNED)ÚConfig)Úurlsplit)ÚNoCredentialsError)ÚS3ClientÚS3RequestTypeÚS3RequestTlsMode)ÚClientBootstrapÚDefaultHostResolverÚEventLoopGroup)ÚClientTlsContextÚTlsContextOptions)ÚAwsCredentialsProviderÚAwsCredentials)ÚTransferNotDoneError)ÚBaseTransferFutureÚBaseTransferMeta)ÚCallArgsÚOSUtilsÚget_callbacks)ÚGBÚMBc                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚCRTCredentialProviderAdapterc                 C   s   || _ d | _t ¡ | _d S ©N)Ú_botocore_credential_providerÚ_loaded_credentialsÚ	threadingÚLockÚ_lock)ÚselfÚbotocore_credential_provider© r"   ú0/usr/lib/python3/dist-packages/s3transfer/crt.pyÚ__init__'   s   z%CRTCredentialProviderAdapter.__init__c                 C   s   |   ¡  ¡ }t|j|j|jƒS r   )Ú_get_credentialsÚget_frozen_credentialsr   Ú
access_keyÚ
secret_keyÚtoken)r    Úcredentialsr"   r"   r#   Ú__call__,   s   ÿz%CRTCredentialProviderAdapter.__call__c                 C   sX   | j � | jd u r| j ¡ }|d u rtƒ ‚|| _| jW  d   ƒ S 1 s%w   Y  d S r   )r   r   r   Úload_credentialsr   )r    Úloaded_credsr"   r"   r#   r%   1   s   
ÿ$ùz-CRTCredentialProviderAdapter._get_credentialsN)Ú__name__Ú
__module__Ú__qualname__r$   r+   r%   r"   r"   r"   r#   r   &   s    r   é   é   Tc              	   C   s    t |ƒ}t|ƒ}t||ƒ}	d}
d}|rtjntj}|dur4tƒ }|r)|j|d� nd|_t	|ƒ}| 
¡ }|r?t|ƒ}t |¡}
|d t }t|	| |
||||d�S )aî  
    :type region: str
    :param region: The region used for signing

    :type botocore_credential_provider:
        Optional[botocore.credentials.CredentialResolver]
    :param botocore_credential_provider: Provide credentials for CRT
        to sign the request if not set, the request will not be signed

    :type num_threads: Optional[int]
    :param num_threads: Number of worker threads generated. Default
        is the number of processors in the machine.

    :type target_throughput: Optional[int]
    :param target_throughput: Throughput target in Bytes.
        Default is 0.625 GB/s (which translates to 5 Gb/s).

    :type part_size: Optional[int]
    :param part_size: Size, in Bytes, of parts that files will be downloaded
        or uploaded in.

    :type use_ssl: boolean
    :param use_ssl: Whether or not to use SSL.  By default, SSL is used.
        Note that not all services support non-ssl connections.

    :type verify: Optional[boolean/string]
    :param verify: Whether or not to verify SSL certificates.
        By default SSL certificates are verified.  You can provide the
        following values:

        * False - do not validate SSL certificates.  SSL will still be
            used (unless use_ssl is False), but SSL certificates
            will not be verified.
        * path/to/cert/bundle.pem - A filename of the CA cert bundle to
            use. Specify this argument if you want to use a custom CA cert
            bundle instead of the default one on your system.
    N)Úca_filepathFr2   )Ú	bootstrapÚregionÚcredential_providerÚ	part_sizeÚtls_modeÚtls_connection_optionsÚthroughput_target_gbps)r   r   r
   r	   ÚENABLEDÚDISABLEDr   Ú&override_default_trust_store_from_pathÚverify_peerr   Únew_connection_optionsr   r   Únew_delegater   r   )r5   r!   Únum_threadsÚtarget_throughputr7   Úuse_sslÚverifyÚevent_loop_groupÚhost_resolverr4   Úproviderr9   r8   Útls_ctx_optionsÚclient_tls_optionÚcredentails_provider_adapterÚtarget_gbpsr"   r"   r#   Úcreate_s3_crt_client<   sD   -

ÿÿÿÿùrL   c                   @   sŒ   e Zd Zddd„Zdd„ Zdd„ Z		ddd	„Z		dd
d„Z		ddd„Zddd„Z	dd„ Z
dd„ Zdd„ Zddd„Zdd„ Zdd„ ZdS ) ÚCRTTransferManagerNc                 C   s@   |du rt ƒ | _|| _t|| jƒ| _g | _t d¡| _d| _	dS )aF  A transfer manager interface for Amazon S3 on CRT s3 client.

        :type crt_s3_client: awscrt.s3.S3Client
        :param crt_s3_client: The CRT s3 client, handling all the
            HTTP requests and functions under then hood

        :type crt_request_serializer: s3transfer.crt.BaseCRTRequestSerializer
        :param crt_request_serializer: Serializer, generates unsigned crt HTTP
            request.

        :type osutil: s3transfer.utils.OSUtils
        :param osutil: OSUtils object to use for os-related behavior when
            using with transfer manager.
        Né€   r   )
r   Ú_osutilÚ_crt_s3_clientÚS3ClientArgsCreatorÚ_s3_args_creatorÚ_future_coordinatorsr   Ú	SemaphoreÚ
_semaphoreÚ_id_counter)r    Úcrt_s3_clientÚcrt_request_serializerÚosutilr"   r"   r#   r$   �   s   ÿ
zCRTTransferManager.__init__c                 C   s   | S r   r"   ©r    r"   r"   r#   Ú	__enter__¦   s   zCRTTransferManager.__enter__c                 G   s   d}|rd}|   |¡ d S )NFT©Ú	_shutdown)r    Úexc_typeÚ	exc_valueÚargsÚcancelr"   r"   r#   Ú__exit__©   s   zCRTTransferManager.__exit__c                 C   s6   |d u ri }|d u ri }t |||||d�}|  d|¡S )N©ÚbucketÚkeyÚfileobjÚ
extra_argsÚsubscribersÚ
get_object©r   Ú_submit_transfer)r    rd   re   rf   rg   rh   Úcallargsr"   r"   r#   Údownload¯   s   ÿzCRTTransferManager.downloadc                 C   s6   |d u ri }|d u ri }t |||||d�}|  d|¡S )Nrc   Ú
put_objectrj   )r    rf   rd   re   rg   rh   rl   r"   r"   r#   Úupload¹   s   þzCRTTransferManager.uploadc                 C   s4   |d u ri }|d u ri }t ||||d�}|  d|¡S )N)rd   re   rg   rh   Údelete_objectrj   )r    rd   re   rg   rh   rl   r"   r"   r#   ÚdeleteÄ   s   þzCRTTransferManager.deleteFc                 C   s   |   |¡ d S r   r\   ©r    ra   r"   r"   r#   ÚshutdownÏ   ó   zCRTTransferManager.shutdownc                 C   s    | j D ]
}| ¡ s| ¡  qd S r   )rS   Údonera   ©r    Úcoordinatorr"   r"   r#   Ú_cancel_transfersÒ   s
   
€þz$CRTTransferManager._cancel_transfersc                 C   ó   | j D ]}| ¡  qd S r   )rS   Úresultrv   r"   r"   r#   Ú_finish_transfers×   ó   

ÿz$CRTTransferManager._finish_transfersc                 C   ry   r   )rS   Ú%wait_until_on_done_callbacks_completerv   r"   r"   r#   Ú_wait_transfers_doneÛ   r|   z'CRTTransferManager._wait_transfers_donec                 C   sz   |r|   ¡  z1z|  ¡  W n ty   |   ¡  Y n ty"   Y nw W |  ¡  d S W |  ¡  d S W |  ¡  d S |  ¡  w r   )rx   r{   ÚKeyboardInterruptÚ	Exceptionr~   rr   r"   r"   r#   r]   ß   s   ÿüüþzCRTTransferManager._shutdownc                 K   ó   | j  ¡  d S r   )rU   Úrelease©r    Úkwargsr"   r"   r#   Ú_release_semaphoreì   rt   z%CRTTransferManager._release_semaphorec              
   C   s  | j g}t| jd�}t| j|ƒ|dœ}td	i |¤Ž}t|ƒ}| |¡ z$| j ¡  | j	 
|d¡}|ƒ  | j	 |||||¡}	| jjd	i |	¤Ž}
W n& tym } z| |d¡ | j	j
|d|d�}||d� W Y d }~n
d }~ww | |
¡ | j |¡ |  jd7  _|S )
N)Útransfer_id)Úmetarw   ÚqueuedTru   )Úafter_subscribers)Úerroré   r"   )r…   ÚCRTTransferCoordinatorrV   ÚCRTTransferMetaÚCRTTransferFutureÚAfterDoneHandlerÚappendrU   ÚacquirerR   Úget_crt_callbackÚget_make_request_argsrP   Úmake_requestr€   Úset_exceptionÚset_s3_requestrS   )r    Úrequest_typeÚ	call_argsÚon_done_after_callsrw   Ú
componentsÚfutureÚ	afterdoneÚ	on_queuedÚcrt_callargsÚcrt_s3_requestÚeÚon_doner"   r"   r#   rk   ï   s>   
þ

ÿþÿ€ü
z#CRTTransferManager._submit_transferr   ©NN©F)r.   r/   r0   r$   r[   rb   rm   ro   rq   rs   rx   r{   r~   r]   r…   rk   r"   r"   r"   r#   rM   ‹   s(    

ÿ

ÿ
ÿ

rM   c                   @   s>   e Zd ZdZddd„Zedd„ ƒZedd„ ƒZed	d
„ ƒZdS )r�   z*Holds metadata about the CRTTransferFutureNc                 C   s   || _ || _i | _d S r   )Ú_transfer_idÚ
_call_argsÚ_user_context)r    r†   r˜   r"   r"   r#   r$     s   
zCRTTransferMeta.__init__c                 C   ó   | j S r   )r¥   rZ   r"   r"   r#   r˜     ó   zCRTTransferMeta.call_argsc                 C   r§   r   )r¤   rZ   r"   r"   r#   r†     r¨   zCRTTransferMeta.transfer_idc                 C   r§   r   )r¦   rZ   r"   r"   r#   Úuser_context   r¨   zCRTTransferMeta.user_contextr¢   )	r.   r/   r0   Ú__doc__r$   Úpropertyr˜   r†   r©   r"   r"   r"   r#   r�     s    


r�   c                   @   sD   e Zd Zddd„Zedd„ ƒZdd„ Zddd	„Zd
d„ Zdd„ Z	dS )rŽ   Nc                 C   s    || _ |du rtƒ | _ || _dS )aZ  The future associated to a submitted transfer request via CRT S3 client

        :type meta: s3transfer.crt.CRTTransferMeta
        :param meta: The metadata associated to the transfer future.

        :type coordinator: s3transfer.crt.CRTTransferCoordinator
        :param coordinator: The coordinator associated to the transfer future.
        N)Ú_metar�   Ú_coordinator)r    r‡   rw   r"   r"   r#   r$   &  s   	
zCRTTransferFuture.__init__c                 C   r§   r   )r¬   rZ   r"   r"   r#   r‡   4  r¨   zCRTTransferFuture.metac                 C   s
   | j  ¡ S r   )r­   ru   rZ   r"   r"   r#   ru   8  ó   
zCRTTransferFuture.donec                 C   ó   | j  |¡ d S r   )r­   rz   ©r    Útimeoutr"   r"   r#   rz   ;  ó   zCRTTransferFuture.resultc                 C   r�   r   )r­   ra   rZ   r"   r"   r#   ra   >  rt   zCRTTransferFuture.cancelc                 C   s$   |   ¡ stdƒ‚| jj|dd� dS )z!Sets the exception on the future.z?set_exception can only be called once the transfer is complete.T)ÚoverrideN)ru   r   r­   r•   )r    Ú	exceptionr"   r"   r#   r•   A  s
   ÿzCRTTransferFuture.set_exceptionr¢   r   )
r.   r/   r0   r$   r«   r‡   ru   rz   ra   r•   r"   r"   r"   r#   rŽ   %  s    


rŽ   c                   @   s   e Zd Zdd„ ZdS )ÚBaseCRTRequestSerializerc                 C   s   t dƒ‚)al  Serialize CRT HTTP requests.

        :type transfer_type: string
        :param transfer_type: the type of transfer made,
            e.g 'put_object', 'get_object', 'delete_object'

        :type future: s3transfer.crt.CRTTransferFuture

        :rtype: awscrt.http.HttpRequest
        :returns: An unsigned HTTP request to be used for the CRT S3 client
        zserialize_http_request())ÚNotImplementedError)r    Útransfer_typer›   r"   r"   r#   Úserialize_http_requestK  s   z/BaseCRTRequestSerializer.serialize_http_requestN)r.   r/   r0   r¸   r"   r"   r"   r#   rµ   J  s    rµ   c                   @   sV   e Zd Zddd„Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ ZdS )ÚBotocoreCRTRequestSerializerNc                 C   sp   || _ |du r	i }|  ||¡ |jdi |¤Ž| _| jjj d| j¡ | jjj d| j¡ | jjj d| j	¡ dS )aÂ  Serialize CRT HTTP request using botocore logic
        It also takes into account configuration from both the session
        and any keyword arguments that could be passed to
        `Session.create_client()` when serializing the request.

        :type session: botocore.session.Session

        :type client_kwargs: Optional[Dict[str, str]])
        :param client_kwargs: The kwargs for the botocore
            s3 client initialization.
        Nzrequest-created.s3.*zafter-call.s3.*zbefore-send.s3.*r"   )
Ú_sessionÚ_resolve_client_configÚcreate_clientÚ_clientr‡   ÚeventsÚregisterÚ_capture_http_requestÚ+_change_response_to_serialized_http_requestÚ_make_fake_http_response)r    ÚsessionÚclient_kwargsr"   r"   r#   r$   [  s   
ÿ
þ
ÿz%BotocoreCRTRequestSerializer.__init__c                 C   sP   d }|  ¡ r
|  ¡ }d|v r|d }ttd�}|r| |¡}||d< d|d< d S )NÚconfig)Úsignature_versionÚs3Úservice_name)Úget_default_client_configr   r   Úmerge)r    rÃ   rÄ   Úuser_provided_configÚclient_configr"   r"   r#   r»   t  s   

z3BotocoreCRTRequestSerializer._resolve_client_configc           
      C   s¸   t |jƒ}|j}|jrd||jf }g }|j ¡ D ]\}}t|tƒr*| ||f¡ q| |t|dƒf¡ qt	j
 |¡}d }|jrOt|jdƒrJ|j}nt|jƒ}t	j
j|j|||d�}	|	S )Nz%s?%szutf-8Úseek)ÚmethodÚpathÚheadersÚbody_stream)r   ÚurlrÏ   ÚqueryrÐ   ÚitemsÚ
isinstanceÚstrr�   ÚawscrtÚhttpÚHttpHeadersÚbodyÚhasattrr   ÚHttpRequestrÎ   )
r    Úaws_requestÚ	url_partsÚcrt_pathÚheaders_listÚnameÚvalueÚcrt_headersÚcrt_body_streamÚcrt_requestr"   r"   r#   Ú_crt_request_from_aws_request�  s,   


üz:BotocoreCRTRequestSerializer._crt_request_from_aws_requestc                 C   sT   |   |¡}|j d¡d u rt|jƒ}|j d|j¡ |j d¡d ur(|j d¡ |S )NÚhostzContent-MD5)ræ   rÐ   Úgetr   rÒ   ÚsetÚnetlocÚremove)r    Úbotocore_http_requestrå   rÞ   r"   r"   r#   Ú_convert_to_crt_http_request�  s   ÿ
z9BotocoreCRTRequestSerializer._convert_to_crt_http_requestc                 K   s   ||j d< d S )NÚhttp_request)Úcontext©r    Úrequestr„   r"   r"   r#   rÀ   ©  rt   z2BotocoreCRTRequestSerializer._capture_http_requestc                 K   s   |d }|  ¡ |d< d S )Nrî   ÚHTTPRequest)Úprepare)r    rï   Úparsedr„   rñ   r"   r"   r#   rÁ   ¬  s   zHBotocoreCRTRequestSerializer._change_response_to_serialized_http_requestc                 K   s   t j d di tdƒ¡S )NéÈ   ó    )ÚbotocoreÚ
awsrequestÚAWSResponseÚFakeRawResponserð   r"   r"   r#   rÂ   ±  s   üz5BotocoreCRTRequestSerializer._make_fake_http_responsec                 C   s&   t | j|ƒd|j|jdœ|j¤Žd S )N)ÚBucketÚKeyrò   r"   )Úgetattrr½   rd   re   rg   )r    Úclient_methodr˜   r"   r"   r#   Ú_get_botocore_http_request¹  s   ÿþþz7BotocoreCRTRequestSerializer._get_botocore_http_requestc                 C   s   |   ||jj¡}|  |¡}|S r   )rÿ   r‡   r˜   rí   )r    r·   r›   rì   rå   r"   r"   r#   r¸   ¾  s
   ÿ
z3BotocoreCRTRequestSerializer.serialize_http_requestr   )r.   r/   r0   r$   r»   ræ   rí   rÀ   rÁ   rÂ   rÿ   r¸   r"   r"   r"   r#   r¹   Z  s    
r¹   c                   @   s   e Zd Zddd„ZdS )rú   é   Nc                 c   s   � 	 |   |¡}|sd S |V  qr   )Úread)r    ÚamtÚdecode_contentÚchunkr"   r"   r#   ÚstreamÆ  s   €
üzFakeRawResponse.stream)r   N)r.   r/   r0   r  r"   r"   r"   r#   rú   Å  s    rú   c                   @   sd   e Zd ZdZddd„Zedd„ ƒZdd„ Zdd	d
„Zddd„Z	dd„ Z
ddd„Zdd„ Zdd„ ZdS )rŒ   z-A helper class for managing CRTTransferFutureNc                 C   s0   || _ || _t ¡ | _d | _d | _t ¡ | _d S r   )	r†   Ú_s3_requestr   r   r   Ú
_exceptionÚ_crt_futureÚEventÚ_done_event)r    r†   Ú
s3_requestr"   r"   r#   r$   Ñ  s   
zCRTTransferCoordinator.__init__c                 C   r§   r   )r  rZ   r"   r"   r#   r  Ù  r¨   z!CRTTransferCoordinator.s3_requestc                 C   r�   r   )r
  ré   rZ   r"   r"   r#   Úset_done_callbacks_completeÝ  rt   z2CRTTransferCoordinator.set_done_callbacks_completec                 C   r¯   r   )r
  Úwaitr°   r"   r"   r#   r}   à  r²   z<CRTTransferCoordinator.wait_until_on_done_callbacks_completeFc                 C   sN   | j � |  ¡ r
|r|| _W d   ƒ d S W d   ƒ d S 1 s w   Y  d S r   )r   ru   r  )r    r´   r³   r"   r"   r#   r•   ã  s   þ"ÿz$CRTTransferCoordinator.set_exceptionc                 C   s   | j r
| j  ¡  d S d S r   )r  ra   rZ   r"   r"   r#   ra   è  s   ÿzCRTTransferCoordinator.cancelc              	   C   sp   | j r| j ‚z$z| j |¡ W n ty   |  ¡  ‚ w W | jr#d | _| j |¡ d S | jr1d | _| j |¡ w r   )r  r  rz   r   ra   r  r°   r"   r"   r#   rz   ì  s   þÿþzCRTTransferCoordinator.resultc                 C   s   | j d u rdS | j  ¡ S )NF)r  ru   rZ   r"   r"   r#   ru   ù  s   

zCRTTransferCoordinator.donec                 C   s   || _ | j j| _d S r   )r  Úfinished_futurer  )r    r  r"   r"   r#   r–   þ  s   z%CRTTransferCoordinator.set_s3_requestr¢   r   r£   )r.   r/   r0   rª   r$   r«   r  r  r}   r•   ra   rz   ru   r–   r"   r"   r"   r#   rŒ   Î  s    




rŒ   c                   @   s(   e Zd Zdd„ Zdd„ Z	ddd„ZdS )	rQ   c                 C   s   || _ || _d S r   )Ú_request_serializerÚ	_os_utils)r    rX   Úos_utilsr"   r"   r#   r$     s   
zS3ClientArgsCreator.__init__c              
   C   s°   d }d }t t| ¡ tjƒ}g }	|tjkr+|j}
| j |
¡}t||
|| jƒ}|	 	|¡ n|tj
kr>|j}| j |¡}||jd< | j ||¡}|||||  |d|	|¡|  |d¡dœS )NÚContentLengthru   Úprogress)rñ   ÚtypeÚrecv_filepathÚsend_filepathr¡   Úon_progress)rý   r   ÚupperÚDEFAULTÚ
GET_OBJECTrf   r  Úget_temp_filenameÚRenameTempFileHandlerr�   Ú
PUT_OBJECTÚget_file_sizerg   r  r¸   r’   )r    r—   r˜   rw   r›   r™   r  r  Ús3_meta_request_typeÚon_done_before_callsÚfinal_filepathÚfile_ondone_callÚdata_lenrå   r"   r"   r#   r“     s@   ý

ÿ

ÿþ
øz)S3ClientArgsCreator.get_make_request_argsNc                    s   ‡ ‡‡‡fdd„}|S )Nc                     sf   g }ˆd ur
|ˆ7 }|t ˆˆƒ7 }ˆ d ur|ˆ 7 }|D ]}ˆdkr)|| d d� q|| i |¤Ž qd S )Nr  r   )Úbytes_transferred)r   )r`   r„   Úcallbacks_listÚcallback©r‰   Úbefore_subscribersÚcallback_typer›   r"   r#   Úinvoke_all_callbacks.  s   ùzBS3ClientArgsCreator.get_crt_callback.<locals>.invoke_all_callbacksr"   )r    r›   r)  r(  r‰   r*  r"   r'  r#   r’   +  s   z$S3ClientArgsCreator.get_crt_callbackr¢   )r.   r/   r0   r$   r“   r’   r"   r"   r"   r#   rQ     s
    $ÿrQ   c                   @   ó   e Zd Zdd„ Zdd„ ZdS )r  c                 C   s   || _ || _|| _|| _d S r   )r­   Ú_final_filenameÚ_temp_filenamerO   )r    rw   Úfinal_filenameÚtemp_filenamerY   r"   r"   r#   r$   B  s   
zRenameTempFileHandler.__init__c              
   K   sx   |d }|r| j  | j¡ d S z| j  | j| j¡ W d S  ty; } z| j  | j¡ | j |¡ W Y d }~d S d }~ww )NrŠ   )rO   Úremove_filer-  Úrename_filer,  r€   r­   r•   )r    r„   rŠ   r    r"   r"   r#   r+   H  s   
ÿ€ýzRenameTempFileHandler.__call__N©r.   r/   r0   r$   r+   r"   r"   r"   r#   r  A  s    r  c                   @   r+  )r�   c                 C   s
   || _ d S r   )r­   rv   r"   r"   r#   r$   W  r®   zAfterDoneHandler.__init__c                 K   r�   r   )r­   r  rƒ   r"   r"   r#   r+   Z  rt   zAfterDoneHandler.__call__Nr2  r"   r"   r"   r#   r�   V  s    r�   )9ÚloggingÚior   r   Úbotocore.awsrequestr÷   Úbotocore.sessionr   Úbotocore.configr   Úbotocore.compatr   Úbotocore.exceptionsr   Úawscrt.httpr×   Ú	awscrt.s3r   r   r	   Ú	awscrt.ior
   r   r   r   r   Úawscrt.authr   r   Ús3transfer.exceptionsr   Ús3transfer.futuresr   r   Ús3transfer.utilsr   r   r   Ús3transfer.constantsr   r   Ú	getLoggerr.   Úloggerr   rL   ÚobjectrM   r�   rŽ   rµ   r¹   rú   rŒ   rQ   r  r�   r"   r"   r"   r#   Ú<module>   sL   


úO %k	5>