o
    !dj                     @   s   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
 d dlmZ eeZG dd deZG dd deZG d	d
 d
e
ZdS )    N)TransferManager)BaseSubscriber)collections_abcc                   @   s   e Zd Zdd ZdZdS )NoSuchBucketErrorc                 K   s(   | j jdi |}t| | || _d S )N )fmtformat	Exception__init__kwargs)selfr   msgr   r   Dusr/lib/python3.10/site-packages/awscli/customizations/s3uploader.pyr
      s   
zNoSuchBucketError.__init__zaS3 Bucket does not exist. Execute the command to create a new bucket
aws s3 mb s3://{bucket_name}N)__name__
__module____qualname__r
   r   r   r   r   r   r      s    r   c                   @   sp   e Zd ZdZedd Zejdd Z				dddZd	d
 ZdddZ	dd Z
dd Zdd ZdddZdS )
S3Uploaderz
    Class to upload objects to S3 bucket that use versioning. If bucket
    does not already use versioning, this class will turn on versioning.
    c                 C   s   | j S )zO
        Metadata to attach to the object(s) uploaded by the uploader.
        )_artifact_metadata)r   r   r   r   artifact_metadata1   s   zS3Uploader.artifact_metadatac                 C   s&   |d urt |tjstd|| _d S )Nz(Artifact metadata should be in dict type)
isinstancer   Mapping	TypeErrorr   )r   valr   r   r   r   8   s   
NFc                 C   sB   || _ || _|p	d | _|| _|| _|| _|st| j| _d | _d S N)bucket_nameprefix
kms_key_idforce_uploads3transfer_managerr   r   )r   Z	s3_clientr   r   r   r   r   r   r   r   r
   >   s   

zS3Uploader.__init__c              
   C   s   | j rt| j dkrd| j |}| js&| |r&td| | |S z3ddi}| jr7d|d< | j|d< | j	r?| j	|d< t
||}| j|| j|||g}|  | |W S  tjjyz } z|jd	 d
 }|dkrtt| jd|d}~ww )z
        Uploads given file to S3
        :param file_name: Path to the file that will be uploaded
        :param remote_path:  be uploaded
        :return: VersionId of the latest upload
        r   z{0}/{1}z:File with same data already exists at {0}. Skipping uploadZServerSideEncryptionZAES256zaws:kmsZSSEKMSKeyIdZMetadataErrorZCodeZNoSuchBucket)r   N)r   lenr   r   file_existsLOGdebugmake_urlr   r   ProgressPercentager   uploadr   resultbotocore
exceptionsClientErrorresponser   )r   	file_nameremote_pathZadditional_argsZprint_progress_callbackfutureexZ
error_coder   r   r   r'   P   s@   


zS3Uploader.uploadc                 C   s*   |  |}|}|r|d | }| ||S )z
        Makes and returns name of the S3 object based on the file's MD5 sum

        :param file_name: file to upload
        :param extension: String of file extension to append to the object
        :return: S3 URL of the uploaded object
        .)file_checksumr'   )r   r-   	extensionZfilemd5r.   r   r   r   upload_with_dedup   s
   
zS3Uploader.upload_with_dedupc                 C   s2   z| j j| j|d W dS  tjjy   Y dS w )z
        Check if the file we are trying to upload already exists in S3

        :param remote_path:
        :return: True, if file exists. False, otherwise
        )ZBucketKeyTF)r   Zhead_objectr   r)   r*   r+   )r   r.   r   r   r   r"      s   zS3Uploader.file_existsc                 C   s   d | j|S )Nzs3://{0}/{1})r   r   )r   Zobj_pathr   r   r   r%      s   zS3Uploader.make_urlc                 C   s   t |d;}t }d}| }|d ||}t|dkr0|| ||}t|dks || | W  d    S 1 sCw   Y  d S )Nrbi   r   )	openhashlibmd5tellseekreadr!   update	hexdigest)r   r-   Zfile_handler9   
block_sizeZcurposbufr   r   r   r2      s   




$zS3Uploader.file_checksumc                 C   s.   | j jj}d|| j|}|rd||}|S )z
            This link describes the format of Path Style URLs
            http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro
        z{0}/{1}/{2}z{0}?versionId={1})r   metaZendpoint_urlr   r   )r   keyversionbaser(   r   r   r   to_path_style_s3_url   s
   
zS3Uploader.to_path_style_s3_url)NNFNr   )r   r   r   __doc__propertyr   setterr
   r'   r4   r"   r%   r2   rE   r   r   r   r   r   +   s"    



1r   c                   @   s   e Zd Zdd Zdd ZdS )r&   c                 C   s2   || _ || _ttj|| _d| _t	 | _
d S )Nr   )	_filename_remote_pathfloatospathgetsize_size_seen_so_far	threadingLock_lock)r   filenamer.   r   r   r   r
      s
   zProgressPercentage.__init__c                 K   sr   | j , |  j|7  _| j| j d }tjd| j| j| j|f  tj  W d    d S 1 s2w   Y  d S )Nd   z#Uploading to %s  %s / %s  (%.2f%%))rS   rP   rO   sysstderrwriterJ   flush)r   r/   Zbytes_transferredr   Z
percentager   r   r   on_progress   s   "zProgressPercentage.on_progressN)r   r   r   r
   rZ   r   r   r   r   r&      s    r&   )r8   loggingrQ   rL   rV   r)   Zbotocore.exceptionsZs3transfer.managerr   Zs3transfer.subscribersr   Zawscli.compatr   	getLoggerr   r#   r	   r   objectr   r&   r   r   r   r   <module>   s   
 $