o
    h	A                     @   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rzd
dl*m+Z+ e ,e-Z.e/dZ0dZ1dddZ2eG dd dZ3e"			dEdee3 dee4 de4de4dee4 dee4 deee4e4f  deee5 ee5 f fddZ6G d d! d!eZ7G d"d# d#eZ8			dEd$d%d&edee4 deee4e4f  dee4 ddfd'd(Z9d)e5fd*d+Z:d,e5fd-d.Z;d/e5fd0d1Z<d$d%d2e4ddfd3d4Z=d$d%d5ed6e>d2e4ddf
d7d8Z?d5ed9e3d6e>dee4 fd:d;Z@d<ee d=e4de8fd>d?ZAd$d%d@ee4 d6e>dee fdAdBZBd$d%d@ee4 d6e>dee fdCdDZCdS )Fz.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defddZ	edefd	d
Z
edef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   s\   t |}t|d}|dd d }t|}W d    n1 s"w   Y  | |||dS )Nrb   r    r   r!   )r   ioopenpeekr   )clsr"   r    filer!   sha r,   g/var/www/html/construction_image-detection-poc/venv/lib/python3.10/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)   r/   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)   r3   r!   r+   r    r,   r,   r-   from_fileobj\   s   
zUploadInfo.from_fileobjN)__name__
__module____qualname____doc__bytes__annotations__intclassmethodstrr.   r2   r   r8   r,   r,   r,   r-   r   <   s   
 r   upload_infostoken	repo_typerepo_idrevisionendpointheadersreturnc                 C   s   |dur|nt j}d}|t jv rt j| }| d| | d}dddgdd	 | D d
d}	|dur9dt|i|	d< i tt|d|pDi }t j|||	d}
t|
 |
	 }|
dd}t|tsft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

    Returns:
        `LfsBatchInfo`: 2-tuple:
            - First element is the list of upload instructions from the server
            - Second element is an list of errors, if any

    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    ).0rL   r,   r,   r-   
<listcomp>   s    z'post_lfs_batch_info.<locals>.<listcomp>r   )	operation	transfersobjects	hash_algonameref)rC   rH   jsonrV   zMalformed response from serverc                 S   s   g | ]
}d |vrt |qS error)_validate_batch_actionsrR   objr,   r,   r-   rS          c                 S   s   g | ]
}d |v rt |qS r\   )_validate_batch_errorr_   r,   r,   r-   rS      ra   )r   ENDPOINTREPO_TYPES_URL_PREFIXESr   LFS_HEADERSr   r   postr   r[   get
isinstancelist
ValueError)rB   rC   rD   rE   rF   rG   rH   
url_prefix	batch_urlpayloadresp
batch_inforV   r,   r,   r-   post_lfs_batch_infof   s<   (


rp   c                   @   s   e Zd ZU eed< eed< dS )PayloadPartT
partNumberetagN)r9   r:   r;   r?   r>   rA   r,   r,   r,   r-   rq      s   
 rq   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.rP   partsN)r9   r:   r;   r<   rA   r>   r
   rq   r,   r,   r,   r-   rt      s   
 rt   rT   r   lfs_batch_actionc              	   C   sH  t | |d}|du rtd| j d dS |d d }t| |d d}|dur2t| |di }|d}	t|d	 |d
}
|	durjzt|	}	W n tt	fy`   td|	 dw t
| ||	|
d nt| |
d |durt| 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 uploadrL   verifyheader
chunk_sizehref)rG   zTMalformed response from LFS batch endpoint: `chunk_size` should be an integer. Got 'z'.)rT   ry   rz   
upload_url)rT   r|   )rC   rH   rO   rZ   z: Upload successful)r^   rg   loggerdebugpath_in_repo_validate_lfs_actionr   r?   rj   	TypeError_upload_multi_part_upload_single_partr   rf   r   upload_infor   rQ   r    r   )rT   rv   rC   rH   rG   rw   upload_actionverify_actionry   rz   r|   
verify_urlverify_respr,   r,   r-   
lfs_upload   sB   



r   
lfs_actionc                 C   s:   t | dtr| ddu st | dtstd| S ).validates response from the LFS batch endpointr{   ry   Nz"lfs_action is improperly formatted)rh   rg   rA   dictrj   )r   r,   r,   r-   r     s
   r   lfs_batch_actionsc                 C   sp   t | dtrt | dtstd| di d}| di d}|dur.t| |dur6t| | S )r   rP   r    z)lfs_batch_actions is improperly formattedrw   rL   rx   N)rh   rg   rA   r?   rj   r   )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s2td| S )r   rP   r    z'lfs_batch_error is improperly formattedr]   messagecode)rh   rg   rA   r?   rj   r   )r   
error_infor,   r,   r-   rb     s    
rb   r|   c                 C   sJ   | j dd}td||dd}t| W d   dS 1 sw   Y  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	with_tqdmPUTi  i  i  i  r/   retry_on_status_codesN)as_filer   r   )rT   r|   r3   responser,   r,   r-   r   -  s   
"r   ry   rz   c                 C   s   t || j|d}tj}tjr!t| jts!t| jts!t	d d}|r*t
| ||dnt| ||d}t j|t|| jj td}t| dS )z@
    Uploads file using HF multipart LFS transfer protocol.
    )ry   r   rz   zlhf_transfer is enabled but does not support uploading from bytes or BinaryIO, falling back to regular uploadF)rT   sorted_parts_urlsrz   )r[   rH   N)_get_sorted_parts_urlsr   r   HF_HUB_ENABLE_HF_TRANSFERrh   path_or_fileobjrA   r   warningswarn_upload_parts_hf_transfer_upload_parts_iterativelyr   rf   _get_completion_payloadr   rQ   re   r   )rT   ry   rz   r|   r   use_hf_transferresponse_headerscompletion_resr,   r,   r-   r   C  s,   

r   r   c                 C   sN   dd t dd |  D dd dD }t|}|t|j| kr%td|S )Nc                 S   s   g | ]\}}|qS r,   r,   )rR   _r|   r,   r,   r-   rS   g  s    z*_get_sorted_parts_urls.<locals>.<listcomp>c                 S   s2   g | ]\}}|  rt|d krt|d|fqS )r   
   )isdigitr1   r?   )rR   part_numr|   r,   r,   r-   rS   j  s    c                 S   s   | d S )Nr   r,   )tr,   r,   r-   <lambda>o  s    z(_get_sorted_parts_urls.<locals>.<lambda>)keyz0Invalid server response to upload large LFS file)sorteditemsr1   r   r    rj   )ry   r   rz   sorted_part_upload_urls	num_partsr,   r,   r-   r   f  s   r   r   rP   c                 C   sf   g }t | D ]'\}}|d}|d u s|dkr#td| d|d  ||d |d q||dS )Nrs   rJ   zInvalid etag (`z`) returned for part r   )rr   rs   )rP   ru   )	enumeraterg   rj   append)r   rP   ru   part_numberry   rs   r,   r,   r-   r   x  s   

r   r   c           	   
   C   s   g }| j dd=}t|D ]/\}}t||| |d}td||dd}t| ||j W d    n1 s7w   Y  qW d    |S 1 sHw   Y  |S )NTr   )	seek_from
read_limitr   r   r   )r   r   r   r   r   r   rH   )	rT   r   rz   rH   r3   part_idxpart_upload_urlfileobj_slicepart_upload_resr,   r,   r-   r     s*   
r   c           
      C   s  zddl m} W n ty   tdw dt|jv }|s#td | j	j
}| j}t|dkr9d|dd   }td	d
|d|tt dd;}z|d| j||dddd|r\d|jini }W n tyr }	 ztd|	d }	~	ww |sz|| |W  d    S 1 sw   Y  d S )Nr   )multipart_uploadzFast 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`.callbackzYou 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)unit
unit_scaletotalinitialdescdisablerX            )	file_path
parts_urlsrz   	max_filesparallel_failuresmax_retriesz~An error occurred while uploading using `hf_transfer`. Consider disabling HF_HUB_ENABLE_HF_TRANSFER for better error handling.r,   )hf_transferr   ImportErrorrj   inspect	signature
parametersr   r   r   r    r   r1   r   r   r}   getEffectiveLevelr   update	ExceptionRuntimeError)
rT   r   rz   r   supports_callbackr   r   progressoutputer,   r,   r-   r     sb   

	
$r   )NNN)Dr<   r   r&   rer   dataclassesr   mathr   os.pathr   pathlibr   typingr   r   r   r	   r
   r   r   r   urllib.parser   huggingface_hubr   utilsr   r   r   r   r   r   r   r   
utils._lfsr   	utils.shar   r   
utils.tqdmr   _commit_apir   
get_loggerr9   r}   compile	OID_REGEXLFS_MULTIPART_UPLOAD_COMMANDre   r   rA   r   rp   rq   rt   r   r   r^   rb   r   r?   r   r   r   r   r   r,   r,   r,   r-   <module>   s   ((


)N

F
#
