U
    EZh|                     @   s   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mZmZmZ d dlmZmZmZmZ G dd	 d	ZG d
d dZG dd dZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )    N)BytesIOreadableseekable)FULL_OBJECT_CHECKSUM_ARGS)IN_MEMORY_UPLOAD_TAG)CompleteMultipartUploadTaskCreateMultipartUploadTaskSubmissionTaskTask)ChunksizeAdjusterDeferredOpenFileget_callbacksget_filtered_dictc                   @   s.   e Zd ZdddZdd Zdd Zdd	 Zd
S )AggregatedProgressCallback   c                 C   s   || _ || _d| _dS )a  Aggregates progress updates for every provided progress callback

        :type callbacks: A list of functions that accepts bytes_transferred
            as a single argument
        :param callbacks: The callbacks to invoke when threshold is reached

        :type threshold: int
        :param threshold: The progress threshold in which to take the
            aggregated progress and invoke the progress callback with that
            aggregated progress total
        r   N)
_callbacks
_threshold_bytes_seen)self	callbacks	threshold r   X/home/aprabhat/apps/x.techxrdev.in/venv/lib/python3.8/site-packages/s3transfer/upload.py__init__"   s    z#AggregatedProgressCallback.__init__c                 C   s&   |  j |7  _ | j | jkr"|   d S N)r   r   _trigger_callbacks)r   bytes_transferredr   r   r   __call__2   s    z#AggregatedProgressCallback.__call__c                 C   s   | j dkr|   dS )z@Flushes out any progress that has not been sent to its callbacksr   N)r   r   r   r   r   r   flush7   s    
z AggregatedProgressCallback.flushc                 C   s"   | j D ]}|| jd qd| _d S )N)r   r   )r   r   )r   callbackr   r   r   r   <   s    
z-AggregatedProgressCallback._trigger_callbacksN)r   )__name__
__module____qualname__r   r   r    r   r   r   r   r   r   !   s   
r   c                   @   sL   e Zd ZdZdd ZdddZddd	Zd
d Zdd Zdd Z	dd Z
dS )InterruptReadera  Wrapper that can interrupt reading using an error

    It uses a transfer coordinator to propagate an error if it notices
    that a read is being made while the file is being read from.

    :type fileobj: file-like obj
    :param fileobj: The file-like object to read from

    :type transfer_coordinator: s3transfer.futures.TransferCoordinator
    :param transfer_coordinator: The transfer coordinator to use if the
        reader needs to be interrupted.
    c                 C   s   || _ || _d S r   )_fileobj_transfer_coordinator)r   fileobjtransfer_coordinatorr   r   r   r   P   s    zInterruptReader.__init__Nc                 C   s   | j jr| j j| j|S r   )r'   	exceptionr&   read)r   amountr   r   r   r+   T   s    zInterruptReader.readr   c                 C   s   | j || d S r   )r&   seek)r   wherewhencer   r   r   r-   ^   s    zInterruptReader.seekc                 C   s
   | j  S r   )r&   tellr   r   r   r   r0   a   s    zInterruptReader.tellc                 C   s   | j   d S r   )r&   closer   r   r   r   r1   d   s    zInterruptReader.closec                 C   s   | S r   r   r   r   r   r   	__enter__g   s    zInterruptReader.__enter__c                 O   s   |    d S r   )r1   )r   argskwargsr   r   r   __exit__j   s    zInterruptReader.__exit__)N)r   )r"   r#   r$   __doc__r   r+   r-   r0   r1   r2   r5   r   r   r   r   r%   B   s   


r%   c                   @   sf   e Zd ZdZdddZe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 )UploadInputManageraJ  Base manager class for handling various types of files for uploads

    This class is typically used for the UploadSubmissionTask class to help
    determine the following:

        * How to determine the size of the file
        * How to determine if a multipart upload is required
        * How to retrieve the body for a PutObject
        * How to retrieve the bodies for a set of UploadParts

    The answers/implementations differ for the various types of file inputs
    that may be accepted. All implementations must subclass and override
    public methods from this class.
    Nc                 C   s   || _ || _|| _d S r   )_osutilr'   _bandwidth_limiterr   osutilr)   bandwidth_limiterr   r   r   r   ~   s    zUploadInputManager.__init__c                 C   s   t ddS )a  Determines if the source for the upload is compatible with manager

        :param upload_source: The source for which the upload will pull data
            from.

        :returns: True if the manager can handle the type of source specified
            otherwise returns False.
        zmust implement _is_compatible()NNotImplementedErrorclsZupload_sourcer   r   r   is_compatible   s    
z UploadInputManager.is_compatiblec                 C   s   t ddS )a  Whether the body it provides are stored in-memory

        :type operation_name: str
        :param operation_name: The name of the client operation that the body
            is being used for. Valid operation_names are ``put_object`` and
            ``upload_part``.

        :rtype: boolean
        :returns: True if the body returned by the manager will be stored in
            memory. False if the manager will not directly store the body in
            memory.
        z%must implement store_body_in_memory()Nr=   r   operation_namer   r   r   stores_body_in_memory   s    z(UploadInputManager.stores_body_in_memoryc                 C   s   t ddS )zProvides the transfer size of an upload

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The future associated with upload request
        z&must implement provide_transfer_size()Nr=   r   transfer_futurer   r   r   provide_transfer_size   s    z(UploadInputManager.provide_transfer_sizec                 C   s   t ddS )a  Determines where a multipart upload is required

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The future associated with upload request

        :type config: s3transfer.manager.TransferConfig
        :param config: The config associated to the transfer manager

        :rtype: boolean
        :returns: True, if the upload should be multipart based on
            configuration and size. False, otherwise.
        z*must implement requires_multipart_upload()Nr=   r   rF   configr   r   r   requires_multipart_upload   s    z,UploadInputManager.requires_multipart_uploadc                 C   s   t ddS )a  Returns the body to use for PutObject

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The future associated with upload request

        :type config: s3transfer.manager.TransferConfig
        :param config: The config associated to the transfer manager

        :rtype: s3transfer.utils.ReadFileChunk
        :returns: A ReadFileChunk including all progress callbacks
            associated with the transfer future.
        z$must implement get_put_object_body()Nr=   rE   r   r   r   get_put_object_body   s    z&UploadInputManager.get_put_object_bodyc                 C   s   t ddS )a  Yields the part number and body to use for each UploadPart

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The future associated with upload request

        :type chunksize: int
        :param chunksize: The chunksize to use for this upload.

        :rtype: int, s3transfer.utils.ReadFileChunk
        :returns: Yields the part number and the ReadFileChunk including all
            progress callbacks associated with the transfer future for that
            specific yielded part.
        z)must implement yield_upload_part_bodies()Nr=   )r   rF   	chunksizer   r   r   yield_upload_part_bodies   s    z+UploadInputManager.yield_upload_part_bodiesc                 C   s*   t || j}| jr&| jj|| jdd}|S )NF)Zenabled)r%   r'   r9   Zget_bandwith_limited_stream)r   r(   r   r   r   _wrap_fileobj   s      z UploadInputManager._wrap_fileobjc                 C   s   t |d}|rt|gS g S )Nprogress)r   r   )r   rF   r   r   r   r   _get_progress_callbacks   s    

z*UploadInputManager._get_progress_callbacksc                 C   s   dd |D S )Nc                 S   s   g | ]
}|j qS r   )r    ).0r!   r   r   r   
<listcomp>   s     z;UploadInputManager._get_close_callbacks.<locals>.<listcomp>r   )r   Zaggregated_progress_callbacksr   r   r   _get_close_callbacks   s    z'UploadInputManager._get_close_callbacks)N)r"   r#   r$   r6   r   classmethodrA   rD   rG   rJ   rK   rM   rN   rP   rS   r   r   r   r   r7   n   s   

	r7   c                   @   sd   e Zd ZdZe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d ZdS )UploadFilenameInputManagerzUpload utility for filenamesc                 C   s
   t |tS r   )
isinstancestrr?   r   r   r   rA      s    z(UploadFilenameInputManager.is_compatiblec                 C   s   dS )NFr   rB   r   r   r   rD      s    z0UploadFilenameInputManager.stores_body_in_memoryc                 C   s   |j | j|j jj d S r   )metarG   r8   Zget_file_size	call_argsr(   rE   r   r   r   rG      s    z0UploadFilenameInputManager.provide_transfer_sizec                 C   s   |j j|jkS r   )rX   sizemultipart_thresholdrH   r   r   r   rJ      s    z4UploadFilenameInputManager.requires_multipart_uploadc                 C   sJ   |  |\}}| |}| |}| |}|jj}| jj|||||dS )Nr(   
chunk_sizefull_file_sizer   close_callbacks)&_get_put_object_fileobj_with_full_sizerN   rP   rS   rX   rZ   r8   #open_file_chunk_reader_from_fileobj)r   rF   r(   	full_sizer   r_   rZ   r   r   r   rK      s    


z.UploadFilenameInputManager.get_put_object_bodyc                 c   s   |j j}| ||}td|d D ]j}| |}| |}||d  }| j|j jj|||d\}	}
| 	|	}	| j
j|	||
||d}||fV  q"d S )N   )
start_byte	part_sizer^   r\   )rX   rZ   _get_num_partsrangerP   rS   '_get_upload_part_fileobj_with_full_sizerY   r(   rN   r8   ra   )r   rF   rL   r^   Z	num_partspart_numberr   r_   rd   r(   rb   Zread_file_chunkr   r   r   rM     s*    




z3UploadFilenameInputManager.yield_upload_part_bodiesc                 C   s   t ||| jjd}|S )N)Zopen_function)r   r8   open)r   r(   rd   r   r   r   _get_deferred_open_file2  s      z2UploadFilenameInputManager._get_deferred_open_filec                 C   s"   |j jj}|j j}| |d|fS )Nr   )rX   rY   r(   rZ   rk   r   rF   r(   rZ   r   r   r   r`   8  s    
zAUploadFilenameInputManager._get_put_object_fileobj_with_full_sizec                 K   s    |d }|d }|  |||fS )Nrd   r^   )rk   )r   r(   r4   rd   rb   r   r   r   rh   =  s    zBUploadFilenameInputManager._get_upload_part_fileobj_with_full_sizec                 C   s   t t|jjt| S r   )intmathceilrX   rZ   float)r   rF   re   r   r   r   rf   B  s    z)UploadFilenameInputManager._get_num_partsN)r"   r#   r$   r6   rT   rA   rD   rG   rJ   rK   rM   rk   r`   rh   rf   r   r   r   r   rU      s   
rU   c                   @   s<   e Zd ZdZedd Zdd Zdd Zdd	 Zd
d Z	dS )UploadSeekableInputManagerz&Upload utility for an open file objectc                 C   s   t |ot|S r   r   r?   r   r   r   rA   I  s    z(UploadSeekableInputManager.is_compatiblec                 C   s   |dkrdS dS d S )N
put_objectFTr   rB   r   r   r   rD   M  s    z0UploadSeekableInputManager.stores_body_in_memoryc                 C   sD   |j jj}| }|dd | }|| |j ||  d S )Nr      )rX   rY   r(   r0   r-   rG   )r   rF   r(   Zstart_positionZend_positionr   r   r   rG   S  s    

z0UploadSeekableInputManager.provide_transfer_sizec                 K   s   | |d }t|t|fS )Nre   )r+   r   len)r   r(   r4   datar   r   r   rh   `  s    zBUploadSeekableInputManager._get_upload_part_fileobj_with_full_sizec                 C   s"   |j jj}| |j j }||fS r   )rX   rY   r(   r0   rZ   rl   r   r   r   r`   o  s    
zAUploadSeekableInputManager._get_put_object_fileobj_with_full_sizeN)
r"   r#   r$   r6   rT   rA   rD   rG   rh   r`   r   r   r   r   rq   F  s   
rq   c                       sh   e Zd ZdZd fdd	Zedd Zdd Zd	d
 Zdd Z	dd Z
dd ZdddZdd Z  ZS )UploadNonSeekableInputManagerz7Upload utility for a file-like object that cannot seek.Nc                    s   t  ||| d| _d S )N    )superr   _initial_datar:   	__class__r   r   r   z  s    z&UploadNonSeekableInputManager.__init__c                 C   s   t |S r   )r   r?   r   r   r   rA   ~  s    z+UploadNonSeekableInputManager.is_compatiblec                 C   s   dS )NTr   rB   r   r   r   rD     s    z3UploadNonSeekableInputManager.stores_body_in_memoryc                 C   s   d S r   r   rE   r   r   r   rG     s    z3UploadNonSeekableInputManager.provide_transfer_sizec                 C   sT   |j jd k	r|j j|jkS |j jj}|j}| ||d| _t| j|k rLdS dS d S )NFT)rX   rZ   r[   rY   r(   _readry   rt   )r   rF   rI   r(   r   r   r   r   rJ     s    
z7UploadNonSeekableInputManager.requires_multipart_uploadc                 C   s@   |  |}| |}|jjj}| | j|  ||}d | _|S r   )rP   rS   rX   rY   r(   
_wrap_datary   r+   )r   rF   r   r_   r(   bodyr   r   r   rK     s    


  z1UploadNonSeekableInputManager.get_put_object_bodyc           	      c   s^   |j jj}d}| |}| |}|d7 }| ||}|s<qZ| |||}d }||fV  qd S )Nr   rc   )rX   rY   r(   rP   rS   r|   r}   )	r   rF   rL   Zfile_objectri   r   r_   Zpart_contentZpart_objectr   r   r   rM     s    


  z6UploadNonSeekableInputManager.yield_upload_part_bodiesTc                 C   sx   t | jdkr||S |t | jkrL| jd| }|rH| j|d | _|S |t | j }| j|| }|rtd| _|S )a=  
        Reads a specific amount of data from a stream and returns it. If there
        is any data in initial_data, that will be popped out first.

        :type fileobj: A file-like object that implements read
        :param fileobj: The stream to read from.

        :type amount: int
        :param amount: The number of bytes to read from the stream.

        :type truncate: bool
        :param truncate: Whether or not to truncate initial_data after
            reading from it.

        :return: Generator which generates part bodies from the initial data.
        r   Nrw   )rt   ry   r+   )r   r(   r,   truncateru   Zamount_to_readr   r   r   r|     s    
z#UploadNonSeekableInputManager._readc                 C   s,   |  t|}| jj|t|t|||dS )a  
        Wraps data with the interrupt reader and the file chunk reader.

        :type data: bytes
        :param data: The data to wrap.

        :type callbacks: list
        :param callbacks: The callbacks associated with the transfer future.

        :type close_callbacks: list
        :param close_callbacks: The callbacks to be called when closing the
            wrapper for the data.

        :return: Fully wrapped data.
        r\   )rN   r   r8   ra   rt   )r   ru   r   r_   r(   r   r   r   r}     s    z(UploadNonSeekableInputManager._wrap_data)N)T)r"   r#   r$   r6   r   rT   rA   rD   rG   rJ   rK   rM   r|   r}   __classcell__r   r   rz   r   rv   w  s   

*rv   c                   @   s   e Zd ZdZddgZedg Zdddddd	gZddddd	ddge Zd
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S )UploadSubmissionTaskz.Task for submitting tasks to execute an uploadChecksumTypeZMpuObjectSizeChecksumAlgorithmZSSECustomerKeyZSSECustomerAlgorithmZSSECustomerKeyMD5ZRequestPayerZExpectedBucketOwnerc                 C   sN   t ttg}|jjj}|D ]}||r|  S qtd| dt| ddS )ao  Retrieves a class for managing input for an upload based on file type

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The transfer future for the request

        :rtype: class of UploadInputManager
        :returns: The appropriate class to use for managing a specific type of
            input for uploads.
        zInput z
 of type: z is not supported.N)	rU   rq   rv   rX   rY   r(   rA   RuntimeErrortype)r   rF   Zupload_manager_resolver_chainr(   Zupload_manager_clsr   r   r   _get_upload_input_manager_cls  s    


z2UploadSubmissionTask._get_upload_input_manager_clsNc                 C   sd   |  ||| j|}|jjdkr*|| |||sL| |||||| n| |||||| dS )a  
        :param client: The client associated with the transfer manager

        :type config: s3transfer.manager.TransferConfig
        :param config: The transfer config associated with the transfer
            manager

        :type osutil: s3transfer.utils.OSUtil
        :param osutil: The os utility associated to the transfer manager

        :type request_executor: s3transfer.futures.BoundedExecutor
        :param request_executor: The request executor associated with the
            transfer manager

        :type transfer_future: s3transfer.futures.TransferFuture
        :param transfer_future: The transfer future associated with the
            transfer request that tasks are being submitted for
        N)r   r'   rX   rZ   rG   rJ   _submit_upload_request_submit_multipart_request)r   clientrI   r;   request_executorrF   r<   upload_input_managerr   r   r   _submit3  s:      
 	zUploadSubmissionTask._submitc           
   
   C   sX   |j j}| |j}| |d}	| jj|t| j||||j	|j
|ddd|	d d S )Nrr   )r   r(   bucketkey
extra_argsT)r)   main_kwargsis_finaltag)rX   rY   _extra_put_object_argsr   _get_upload_task_tagr'   submitPutObjectTaskrK   r   r   )
r   r   rI   r;   r   rF   r   rY   Zput_object_extra_argsZput_object_tagr   r   r   r   l  s0    	 	z+UploadSubmissionTask._submit_upload_requestc                 C   s6  |j j}tD ]*}||jkrd|jd< |dd|jd< q| |j}	| j|t| j||j	|j
|	dd}
g }| |j}| |d}|j j}t }||j|}|||}|D ]B\}}|| jj|t| j|||j	|j
||d	d
|
id|d q| |j}| j|t| j||j	|j
|d|
|ddd d S )NZFULL_OBJECTr   Checksum r   )r   r   r   r   )r)   r   upload_part)r   r(   r   r   ri   r   	upload_id)r)   r   pending_main_kwargsr   )r   partsT)r)   r   r   r   )rX   rY   r   r   replace_extra_create_multipart_argsr'   r   r	   r   r   _extra_upload_part_argsr   rZ   r   Zadjust_chunksizeZmultipart_chunksizerM   appendUploadPartTask_extra_complete_multipart_argsr   )r   r   rI   r;   r   rF   r   rY   ZchecksumZcreate_multipart_extra_argsZcreate_multipart_futureZpart_futuresZextra_part_argsZupload_part_tagrZ   ZadjusterrL   Zpart_iteratorri   r(   Zcomplete_multipart_extra_argsr   r   r   r     s    	

   	 z.UploadSubmissionTask._submit_multipart_requestc                 C   s   t || jS r   )r   UPLOAD_PART_ARGSr   r   r   r   r   r     s    z,UploadSubmissionTask._extra_upload_part_argsc                 C   s   t || jS r   )r   COMPLETE_MULTIPART_ARGSr   r   r   r   r     s    z3UploadSubmissionTask._extra_complete_multipart_argsc                 C   s   t || jdS N)Zblocklisted_keys)r   CREATE_MULTIPART_BLOCKLISTr   r   r   r   r     s     z1UploadSubmissionTask._extra_create_multipart_argsc                 C   s   t || jdS r   )r   PUT_OBJECT_BLOCKLISTr   r   r   r   r     s     z+UploadSubmissionTask._extra_put_object_argsc                 C   s   d }| |rt}|S r   )rD   r   )r   r   rC   r   r   r   r   r     s    
z)UploadSubmissionTask._get_upload_task_tag)N)r"   r#   r$   r6   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s<   


 
9'cr   c                   @   s   e Zd ZdZdd ZdS )r   z Task to do a nonmultipart uploadc              	   C   s,   |}|j f |||d| W 5 Q R X dS )aP  
        :param client: The client to use when calling PutObject
        :param fileobj: The file to upload.
        :param bucket: The name of the bucket to upload to
        :param key: The name of the key to upload to
        :param extra_args: A dictionary of any extra arguments that may be
            used in the upload.
        )BucketKeyBodyN)rr   )r   r   r(   r   r   r   r~   r   r   r   _main  s    	zPutObjectTask._mainNr"   r#   r$   r6   r   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )r   z+Task to upload a part in a multipart uploadc              	   C   st   |"}|j f |||||d|}	W 5 Q R X |	d }
|
|d}d|krp|d  }d| }||	krp|	| ||< |S )a  
        :param client: The client to use when calling PutObject
        :param fileobj: The file to upload.
        :param bucket: The name of the bucket to upload to
        :param key: The name of the key to upload to
        :param upload_id: The id of the upload
        :param part_number: The number representing the part of the multipart
            upload
        :param extra_args: A dictionary of any extra arguments that may be
            used in the upload.

        :rtype: dict
        :returns: A dictionary representing a part::

            {'Etag': etag_value, 'PartNumber': part_number}

            This value can be appended to a list to be used to complete
            the multipart upload.
        )r   r   ZUploadId
PartNumberr   ETag)r   r   r   r   )r   upper)r   r   r(   r   r   r   ri   r   r~   responseetagZpart_metadataZalgorithm_nameZchecksum_memberr   r   r   r   "  s$    

zUploadPartTask._mainNr   r   r   r   r   r     s   r   )rn   ior   Zs3transfer.compatr   r   Zs3transfer.constantsr   Zs3transfer.futuresr   Zs3transfer.tasksr   r	   r
   r   Zs3transfer.utilsr   r   r   r   r   r%   r7   rU   rq   rv   r   r   r   r   r   r   r   <module>   s$   !,{]1   