U
    ”Ê¹ju  ã                   @   s@   d Z ddlZddlZddlmZ ddlmZ G dd„ deƒZdS )zGit LFS related utilitiesé    N)ÚAbstractContextManager)ÚBinaryIOc                   @   sp   e Zd ZdZeeedœdd„Zdd„ Zdd„ Zded
œdd„Z	edœdd„Z
ejfeeedœdd„Zdd„ ZdS )ÚSliceFileObja¥  
    Utility context manager to read a *slice* of a seekable file-like object as a seekable, file-like object.

    This is NOT thread safe

    Inspired by stackoverflow.com/a/29838711/593036

    Credits to @julien-c

    Args:
        fileobj (`BinaryIO`):
            A file-like object to slice. MUST implement `tell()` and `seek()` (and `read()` of course).
            `fileobj` will be reset to its original position when exiting the context manager.
        seek_from (`int`):
            The start of the slice (offset from position 0 in bytes).
        read_limit (`int`):
            The maximum number of bytes to read from the slice.

    Attributes:
        previous_position (`int`):
            The previous position

    Examples:

    Reading 200 bytes with an offset of 128 bytes from a file (ie bytes 128 to 327):
    ```python
    >>> with open("path/to/file", "rb") as file:
    ...     with SliceFileObj(file, seek_from=128, read_limit=200) as fslice:
    ...         fslice.read(...)
    ```

    Reading a file in chunks of 512 bytes
    ```python
    >>> import os
    >>> chunk_size = 512
    >>> file_size = os.getsize("path/to/file")
    >>> with open("path/to/file", "rb") as file:
    ...     for chunk_idx in range(ceil(file_size / chunk_size)):
    ...         with SliceFileObj(file, seek_from=chunk_idx * chunk_size, read_limit=chunk_size) as fslice:
    ...             chunk = fslice.read(...)

    ```
    ©ÚfileobjÚ	seek_fromÚ
read_limitc                 C   s   || _ || _|| _d S ©Nr   )Úselfr   r   r   © r   úY/var/www/html/bwave/python/venv/lib/python3.8/site-packages/huggingface_hub/utils/_lfs.pyÚ__init__D   s    zSliceFileObj.__init__c                 C   sF   | j  ¡ | _| j  dtj¡}t| j|| j ƒ| _	| j  | jt
j¡ | S )Nr   )r   ÚtellÚ_previous_positionÚseekÚosÚSEEK_ENDÚminr   r   Ú_lenÚioÚSEEK_SET)r
   Zend_of_streamr   r   r   Ú	__enter__I   s
    zSliceFileObj.__enter__c                 C   s   | j  | jtj¡ d S r	   )r   r   r   r   r   )r
   Úexc_typeÚ	exc_valueÚ	tracebackr   r   r   Ú__exit__Q   s    zSliceFileObj.__exit__éÿÿÿÿ©Únc                 C   sB   |   ¡ }|| jkrdS | j| }| j |dk r2|nt||ƒ¡}|S )Nó    r   )r   r   r   Úreadr   )r
   r   ÚposZremaining_amountÚdatar   r   r   r    T   s    

zSliceFileObj.read)Úreturnc                 C   s   | j  ¡ | j S r	   )r   r   r   ©r
   r   r   r   r   \   s    zSliceFileObj.tell)ÚoffsetÚwhencer#   c                 C   s¤   | j }|| j }|tjtjfkrR|tjkr2|| n|| }t|t||ƒƒ}tj}n>|tjkr€| j 	¡ }t|| t||| ƒƒ}nt
d|› d�ƒ‚| j ||¡| j  S )Nzwhence value z is not supported)r   r   r   r   r   Úmaxr   ÚSEEK_CURr   r   Ú
ValueErrorr   )r
   r%   r&   ÚstartÚendZcur_posr   r   r   r   _   s    


zSliceFileObj.seekc                 c   s   | j dd�V  d S )Ni  @ r   )r    r$   r   r   r   Ú__iter__m   s    zSliceFileObj.__iter__N)r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úintr   r   r   r    r   r   r   r   r,   r   r   r   r   r      s   ,r   )r0   r   r   Ú
contextlibr   Útypingr   r   r   r   r   r   Ú<module>   s
   