U
    ”Ê¹j|B  ã                   @   s�  d 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
 ddlmZ ddlmZmZmZmZmZmZ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mZm Z m!Z!m"Z" d
dl#m$Z$ d
dl%m&Z&m'Z' d
dl(m)Z) erôd
dl*m+Z+ e  ,e-¡Z.e /d¡Z0dZ1dddœZ2eG dd„ dƒƒZ3e"d;ee3 ee4 e4e4ee4 ee4 eee4e4f  eee4  eee5 ee5 ee4 f dœ	dd„ƒZ6G dd„ deƒZ7G dd„ deƒZ8d<deee4 eee4e4f  ee4 ddœdd „Z9e5d!œd"d#„Z:e5d$œd%d&„Z;e5d'œd(d)„Z<de4dd*œd+d,„Z=dee>e4dd-œd.d/„Z?ee3e>ee4 d0œd1d2„Z@ee e4e8d3œd4d5„ZAdee4 e>ee d6œd7d8„ZBdee4 e>ee d6œd9d:„ZCdS )=z.Git LFS related type definitions and utilitiesé    N)Ú	dataclass)Úceil)Úgetsize)ÚPath)ÚTYPE_CHECKINGÚBinaryIOÚDictÚIterableÚListÚOptionalÚTupleÚ	TypedDict)Úunquote)Ú	constantsé   )Úbuild_hf_headersÚfix_hf_endpoint_in_urlÚget_sessionÚhf_raise_for_statusÚhttp_backoffÚloggingÚtqdmÚvalidate_hf_hub_args)ÚSliceFileObj)Úsha256Úsha_fileobj)Úis_tqdm_disabled)ÚCommitOperationAddz^[0-9a-f]{40}$zlfs-multipart-uploadzapplication/vnd.git-lfs+json)ÚAcceptzContent-Typec                   @   s`   e Zd ZU dZeed< eed< eed< eedœdd„ƒZ	eedœd	d
„ƒZ
eedœdd„ƒZdS )Ú
UploadInfoad  
    Dataclass holding required information to determine whether a blob
    should be uploaded to the hub using the LFS protocol or the regular protocol

    Args:
        sha256 (`bytes`):
            SHA256 hash of the blob
        size (`int`):
            Size in bytes of the blob
        sample (`bytes`):
            First 512 bytes of the blob
    r   ÚsizeÚsample)Úpathc              	   C   sH   t |ƒ}t |d¡� }| d¡d d… }t|ƒ}W 5 Q R X | |||d�S )NÚrbé   ©r    r   r!   )r   ÚioÚopenÚpeekr   )Úclsr"   r    Úfiler!   Úsha© r,   úR/var/www/html/bwave/python/venv/lib/python3.8/site-packages/huggingface_hub/lfs.pyÚ	from_pathO   s
    zUploadInfo.from_path©Údatac                 C   s&   t |ƒ ¡ }| t|ƒ|d d… |d�S )Nr$   )r    r!   r   )r   ÚdigestÚlen)r)   r0   r+   r,   r,   r-   Ú
from_bytesW   s    zUploadInfo.from_bytes)Úfileobjc                 C   sD   |  d¡}| dtj¡ t|ƒ}| ¡ }| dtj¡ | |||d�S )Nr$   r   r%   )ÚreadÚseekr&   ÚSEEK_SETr   Útell)r)   r4   r!   r+   r    r,   r,   r-   Úfrom_fileobj\   s    
zUploadInfo.from_fileobjN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚbytesÚ__annotations__ÚintÚclassmethodÚstrr.   r3   r   r9   r,   r,   r,   r-   r   <   s   
r   )	Úupload_infosÚtokenÚ	repo_typeÚrepo_idÚrevisionÚendpointÚheadersÚ	transfersÚreturnc                 C   s  |dk	r|nt j}d}|t jkr*t j| }|› d|› |› d�}	d|dk	rL|nddgdd	„ | D ƒd
dœ}
|dk	r~dt|ƒi|
d< tt|d�|pŽi –}tƒ j|	||
d�}t|ƒ | 	¡ }| 
dd¡}t|tƒsÒtdƒ‚| 
d¡}t|tƒrê|nd}dd	„ |D ƒdd	„ |D ƒ|fS )aÍ  
    Requests the LFS batch endpoint to retrieve upload instructions

    Learn more: https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md

    Args:
        upload_infos (`Iterable` of `UploadInfo`):
            `UploadInfo` for the files that are being uploaded, typically obtained
            from `CommitOperationAdd.upload_info`
        repo_type (`str`):
            Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`.
        repo_id (`str`):
            A namespace (user or an organization) and a repo name separated
            by a `/`.
        revision (`str`, *optional*):
            The git revision to upload to.
        headers (`dict`, *optional*):
            Additional headers to include in the request
        transfers (`list`, *optional*):
            List of transfer methods to use. Defaults to ["basic", "multipart"].

    Returns:
        `LfsBatchInfo`: 3-tuple:
            - First element is the list of upload instructions from the server
            - Second element is a list of errors, if any
            - Third element is the chosen transfer adapter if provided by the server (e.g. "basic", "multipart", "xet")

    Raises:
        [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)
            If an argument is invalid or the server response is malformed.
        [`HTTPError`](https://requests.readthedocs.io/en/latest/api/#requests.HTTPError)
            If the server returned an error.
    NÚ ú/z.git/info/lfs/objects/batchÚuploadÚbasicÚ	multipartc                 S   s   g | ]}|j  ¡ |jd œ‘qS )©Úoidr    )r   Úhexr    )Ú.0rN   r,   r,   r-   Ú
<listcomp>š   s   ýþz'post_lfs_batch_info.<locals>.<listcomp>r   )Ú	operationrJ   ÚobjectsZ	hash_algoÚnameÚref)rD   ©rI   ÚjsonrW   zMalformed response from serverZtransferc                 S   s   g | ]}d |krt |ƒ‘qS ©Úerror)Ú_validate_batch_actions©rT   Úobjr,   r,   r-   rU   ·   s      c                 S   s   g | ]}d |krt |ƒ‘qS r\   )Ú_validate_batch_errorr_   r,   r,   r-   rU   ¸   s      )r   ZENDPOINTZREPO_TYPES_URL_PREFIXESr   ÚLFS_HEADERSr   r   Úpostr   r[   ÚgetÚ
isinstanceÚlistÚ
ValueErrorrB   )rC   rD   rE   rF   rG   rH   rI   rJ   Z
url_prefixZ	batch_urlÚpayloadÚrespZ
batch_inforW   Zchosen_transferr,   r,   r-   Úpost_lfs_batch_infof   s<    ,

ûöý

ýrj   c                   @   s   e Zd ZU eed< eed< dS )ÚPayloadPartTÚ
partNumberÚetagN)r:   r;   r<   r@   r?   rB   r,   r,   r,   r-   rk   ½   s   
rk   c                   @   s&   e Zd ZU dZeed< ee ed< dS )ÚCompletionPayloadTz?Payload that will be sent to the Hub when uploading multi-part.rR   ÚpartsN)r:   r;   r<   r=   rB   r?   r
   rk   r,   r,   r,   r-   rn   Â   s   
rn   r   )rV   Úlfs_batch_actionrD   rI   rH   rK   c              	   C   sP  t |ƒ | d¡}|dkr2t d| j› d�¡ dS |d d }t|ƒ |d  d¡}|dk	rdt|ƒ | di ¡}| d¡}	t|d	 |d
�}
|	dk	rÚzt|	ƒ}	W n( tt	fk
rÆ   td|	› d�ƒ‚Y nX t
| ||	|
d� nt| |
d� |dk	�r:t|ƒ t|d	 |ƒ}tƒ j|t||d�| jj ¡ | jjdœd�}t|ƒ t | j› d�¡ dS )aw  
    Handles uploading a given object to the Hub with the LFS protocol.

    Can be a No-op if the content of the file is already present on the hub large file storage.

    Args:
        operation (`CommitOperationAdd`):
            The add operation triggering this upload.
        lfs_batch_action (`dict`):
            Upload instructions from the LFS batch endpoint for this object. See [`~utils.lfs.post_lfs_batch_info`] for
            more details.
        headers (`dict`, *optional*):
            Headers to include in the request, including authentication and user agent headers.

    Raises:
        [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)
            If `lfs_batch_action` is improperly formatted
        [`HTTPError`](https://requests.readthedocs.io/en/latest/api/#requests.HTTPError)
            If the upload resulted in an error
    ÚactionsNzContent of file z. is already present upstream - skipping uploadrN   ÚverifyÚheaderÚ
chunk_sizeÚhref)rH   zTMalformed response from LFS batch endpoint: `chunk_size` should be an integer. Got 'z'.)rV   rs   rt   Ú
upload_url)rV   rv   )rD   rI   rQ   rZ   z: Upload successful)r^   rd   ÚloggerÚdebugÚpath_in_repoÚ_validate_lfs_actionr   r@   rg   Ú	TypeErrorÚ_upload_multi_partÚ_upload_single_partr   rc   r   Úupload_infor   rS   r    r   )rV   rp   rD   rI   rH   rq   Úupload_actionÚverify_actionrs   rt   rv   Z
verify_urlZverify_respr,   r,   r-   Ú
lfs_uploadÉ   s@    


ÿ


ýr�   ©Z
lfs_actionc                 C   s:   t |  d¡tƒr.|  d¡dks6t |  d¡tƒs6tdƒ‚| S )ú.validates response from the LFS batch endpointru   rs   Nz"lfs_action is improperly formatted)re   rd   rB   Údictrg   r‚   r,   r,   r-   rz     s    ÿþþrz   )Úlfs_batch_actionsc                 C   sp   t |  d¡tƒr t |  d¡tƒs(tdƒ‚|  di ¡ d¡}|  di ¡ d¡}|dk	r\t|ƒ |dk	rlt|ƒ | S )rƒ   rR   r    z)lfs_batch_actions is improperly formattedrq   rN   rr   N)re   rd   rB   r@   rg   rz   )r…   r   r€   r,   r,   r-   r^     s     r^   )Úlfs_batch_errorc                 C   sh   t |  d¡tƒr t |  d¡tƒs(tdƒ‚|  d¡}t |tƒr\t | d¡tƒr\t | d¡tƒsdtdƒ‚| S )rƒ   rR   r    z'lfs_batch_error is improperly formattedr]   ÚmessageÚcode)re   rd   rB   r@   rg   r„   )r†   Ú
error_infor,   r,   r-   ra   '  s     
ÿþýra   )rV   rv   rK   c              	   C   s2   | j dd��}td||d�}t|ƒ W 5 Q R X dS )a¤  
    Uploads `fileobj` as a single PUT HTTP request (basic LFS transfer protocol)

    Args:
        upload_url (`str`):
            The URL to PUT the file to.
        fileobj:
            The file-like object holding the data to upload.

    Returns: `requests.Response`

    Raises:
     [`HTTPError`](https://requests.readthedocs.io/en/latest/api/#requests.HTTPError)
        If the upload resulted in an error.
    T©Z	with_tqdmÚPUTr/   N)Úas_filer   r   )rV   rv   r4   Úresponser,   r,   r-   r}   5  s    r}   )rV   rs   rt   rv   rK   c                 C   sŽ   t || j|d�}tj}tjrBt| jtƒsBt| jtƒsBt 	d¡ d}|rTt
| ||d�nt| ||d�}tƒ j|t|| jj ¡ ƒtd�}t|ƒ dS )z@
    Uploads file using HF multipart LFS transfer protocol.
    )rs   r~   rt   zlhf_transfer is enabled but does not support uploading from bytes or BinaryIO, falling back to regular uploadF)rV   Úsorted_parts_urlsrt   )r[   rI   N)Ú_get_sorted_parts_urlsr~   r   ZHF_HUB_ENABLE_HF_TRANSFERre   Úpath_or_fileobjrB   r   ÚwarningsÚwarnÚ_upload_parts_hf_transferÚ_upload_parts_iterativelyr   rc   Ú_get_completion_payloadr   rS   rb   r   )rV   rs   rt   rv   rŽ   Zuse_hf_transferÚresponse_headersZcompletion_resr,   r,   r-   r|   K  s,    ÿ
þ
ýÿÿýýr|   )rs   r~   rt   rK   c                 C   sN   dd„ t dd„ |  ¡ D ƒdd„ d�D ƒ}t|ƒ}|t|j| ƒkrJtdƒ‚|S )Nc                 S   s   g | ]\}}|‘qS r,   r,   )rT   Ú_rv   r,   r,   r-   rU   o  s   ÿz*_get_sorted_parts_urls.<locals>.<listcomp>c                 S   s2   g | ]*\}}|  ¡ rt|ƒd krt|dƒ|f‘qS )r   é
   )Úisdigitr2   r@   )rT   Zpart_numrv   r,   r,   r-   rU   r  s    þc                 S   s   | d S )Nr   r,   )Útr,   r,   r-   Ú<lambda>w  ó    z(_get_sorted_parts_urls.<locals>.<lambda>)Úkeyz0Invalid server response to upload large LFS file)ÚsortedÚitemsr2   r   r    rg   )rs   r~   rt   Zsorted_part_upload_urlsZ	num_partsr,   r,   r-   r�   n  s    þúþr�   )r–   rR   rK   c                 C   sf   g }t | ƒD ]N\}}| d¡}|d ks.|dkrFtd|› d|d › �ƒ‚| |d |dœ¡ q||dœS )Nrm   rL   zInvalid etag (`z`) returned for part r   )rl   rm   )rR   ro   )Ú	enumeraterd   rg   Úappend)r–   rR   ro   Zpart_numberrs   rm   r,   r,   r-   r•   €  s    
þÿr•   )rV   rŽ   rt   rK   c           	      C   sr   g }| j dd��X}t|ƒD ]H\}}t||| |d��(}td||d�}t|ƒ | |j¡ W 5 Q R X qW 5 Q R X |S )NTrŠ   )Z	seek_fromZ
read_limitr‹   r/   )rŒ   r    r   r   r   r¡   rI   )	rV   rŽ   rt   rI   r4   Zpart_idxZpart_upload_urlZfileobj_sliceZpart_upload_resr,   r,   r-   r”   �  s    ý"r”   c           
      C   s   zddl m} W n tk
r,   tdƒ‚Y nX dt |¡jk}|sLt d¡ | j	j
}| j}t|ƒdkrxd|dd … › �}td	d
|d|tt ¡ ƒdd��€}z0|f | j||ddddœ|r¾d|jini —Ž}W n, tk
rô }	 ztdƒ|	‚W 5 d }	~	X Y nX |�s| |¡ |W  5 Q R £ S Q R X d S )Nr   )Úmultipart_uploadzªFast uploading using 'hf_transfer' is enabled (HF_HUB_ENABLE_HF_TRANSFER=1) but 'hf_transfer' package is not available in your environment. Try `pip install hf_transfer`.Úcallbackz”You are using an outdated version of `hf_transfer`. Consider upgrading to latest version to enable progress bars using `pip install -U hf_transfer`.é(   u   (â€¦)iØÿÿÿÚBTzhuggingface_hub.lfs_upload)ÚunitZ
unit_scaleÚtotalÚinitialÚdescÚdisablerX   é€   é   é   )Ú	file_pathZ
parts_urlsrt   Z	max_filesZparallel_failuresÚmax_retriesz~An error occurred while uploading using `hf_transfer`. Consider disabling HF_HUB_ENABLE_HF_TRANSFER for better error handling.)Zhf_transferr¢   ÚImportErrorrg   ÚinspectÚ	signatureÚ
parametersr‘   r’   r~   r    ry   r2   r   r   rw   ÚgetEffectiveLevelr�   ÚupdateÚ	ExceptionÚRuntimeError)
rV   rŽ   rt   r¢   Zsupports_callbackr§   r©   ÚprogressÚoutputÚer,   r,   r-   r“   ¡  sZ    ÿ
ÿ
ùúù
	ÿý
r“   )NNNN)NNN)Dr=   r±   r&   Úrer‘   Údataclassesr   Úmathr   Úos.pathr   Úpathlibr   Útypingr   r   r   r	   r
   r   r   r   Úurllib.parser   Zhuggingface_hubr   Úutilsr   r   r   r   r   r   r   r   Z
utils._lfsr   Z	utils.shar   r   Z
utils.tqdmr   Z_commit_apir   Z
get_loggerr:   rw   ÚcompileZ	OID_REGEXZLFS_MULTIPART_UPLOAD_COMMANDrb   r   rB   r„   rj   rk   rn   r�   rz   r^   ra   r}   r@   r|   r�   r•   r”   r“   r,   r,   r,   r-   Ú<module>   sŽ   ((


þ)    ø
÷V
   ûúF
#  þ  þ