o
    pf\E                     @   s  d Z ddlmZm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 dd
lmZm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  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ej'rddlm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddlm2Z2 ddl3m4Z4 ej5dddZ6G dd deZ7G dd de&Z8ej9G dd de&Z:ej9G dd deZ;dS ) z(Manage the filesystem in a Zip archive.
    )print_functionunicode_literalsN)datetime   )errors)	url_quote)FS)	write_zip)ResourceTypeSeek)Info)
RawWrapper)MemoryFS)open_fs)dirnameforcedirnormpathrelpath)Permissions)datetime_to_epoch)WrapFS)
AnyBinaryIO
CollectionDictListOptionalSupportsIntTextTupleUnion)RawInfo)SubFSR	ReadZipFS)boundc                       sn   e Zd Z fddZejdk r,dddZdddZd	d
 Zdd Z	e
jfddZ  ZS e
jfddZ  ZS )_ZipExtFilec                    s>   |j  | _ }||j| _d| _tt| ||d| d S )Nr   r)	_zipgetinfo	file_size_end_possuperr&   __init__open)selffsnamer(   	__class__ A/home/ertert/spirit/venv/lib/python3.10/site-packages/fs/zipfs.pyr.   0   s   z_ZipExtFile.__init__)      c                 C   .   | j |d u r	dn|}|  jt|7  _|S Nr9   )_freadr,   lenr0   sizebufr5   r5   r6   r=   >      z_ZipExtFile.readc                 C   r:   r;   )r<   read1r,   r>   r?   r5   r5   r6   rC   D   rB   z_ZipExtFile.read1c                 C      | j S N)r,   r0   r5   r5   r6   tellJ      z_ZipExtFile.tellc                 C   s   dS )NTr5   rF   r5   r5   r6   seekableN   s   z_ZipExtFile.seekablec                 C   s   t |}|tjkr|| j7 }|tjks|tjkr$|dk r#td|n#|tjkr:|dkr4td||| j7 }ntd|tjtjtj|| jk rW| j	
| j| _d| _| || j  | jS )af  Change stream position.

            Change the stream position to the given byte offset. The
            offset is interpreted relative to the position indicated by
            ``whence``.

            Arguments:
                offset (int): the offset to the new position, in bytes.
                whence (int): the position reference. Possible values are:
                    * `Seek.set`: start of stream (the default).
                    * `Seek.current`: current position; offset may be negative.
                    * `Seek.end`: end of stream; offset must be negative.

            Returns:
                int: the new absolute position.

            Raises:
                ValueError: when ``whence`` is not known, or ``offset``
                    is invalid.

            Note:
                Zip compression does not support seeking, so the seeking
                is emulated. Seeking somewhere else than the current position
                will need to either:
                    * reopen the file and restart decompression
                    * read and discard data to advance in the file

            r   Negative seek position {}Positive seek position {}+Invalid whence ({}, should be {}, {} or {}))intr   currentr,   set
ValueErrorformatendr+   r(   r/   r2   r<   r=   )r0   offsetwhence_whencer5   r5   r6   seekQ   s*   



z_ZipExtFile.seekc                 C   s   t |}|  }|tjkr|dk rtd|n1|tjkr,|| dk r+td|n|tjkr=|dkr<td|ntd|tjtjtj| j	||S )a  Change stream position.

            Change the stream position to the given byte offset. The
            offset is interpreted relative to the position indicated by
            ``whence``.

            Arguments:
                offset (int): the offset to the new position, in bytes.
                whence (int): the position reference. Possible values are:
                    * `Seek.set`: start of stream (the default).
                    * `Seek.current`: current position; offset may be negative.
                    * `Seek.end`: end of stream; offset must be negative.

            Returns:
                int: the new absolute position.

            Raises:
                ValueError: when ``whence`` is not known, or ``offset``
                    is invalid.

            r   rJ   rK   rL   )
rM   rG   r   rO   rP   rQ   rN   rR   r<   rV   )r0   rS   rT   rU   r,   r5   r5   r6   rV      s(   


)r9   )__name__
__module____qualname__r.   sysversion_infor=   rC   rG   rI   r   rO   rV   __classcell__r5   r5   r3   r6   r&   /   s    


7r&   c                   @   sB   e Zd ZdZdejddfddZejrdejddfddZ	d	S d	S )
ZipFSa.  Read and write zip files.

    There are two ways to open a `ZipFS` for the use cases of reading
    a zip file, and creating a new one.

    If you open the `ZipFS` with  ``write`` set to `False` (the default)
    then the filesystem will be a read-only filesystem which maps to
    the files and directories within the zip file. Files are
    decompressed on the fly when you open them.

    Here's how you might extract and print a readme from a zip file::

        with ZipFS('foo.zip') as zip_fs:
            readme = zip_fs.readtext('readme.txt')

    If you open the `ZipFS` with ``write`` set to `True`, then the `ZipFS`
    will be an empty temporary filesystem. Any files / directories you
    create in the `ZipFS` will be written in to a zip file when the `ZipFS`
    is closed.

    Here's how you might write a new zip file containing a ``readme.txt``
    file::

        with ZipFS('foo.zip', write=True) as new_zip:
            new_zip.writetext(
                'readme.txt',
                'This zip file was written by PyFilesystem'
            )


    Arguments:
        file (str or io.IOBase): An OS filename, or an open file object.
        write (bool): Set to `True` to write a new zip file, or `False`
            (default) to read an existing zip file.
        compression (int): Compression to use (one of the constants
            defined in the `zipfile` module in the stdlib).
        temp_fs (str or FS): An FS URL or an FS instance to use to
            store data prior to zipping. Defaults to creating a new
            `~fs.tempfs.TempFS`.

    Futf-8temp://__ziptemp__c                 C   s    |r
t ||||dS t||dS )N)compressionencodingtemp_fs)ra   )
WriteZipFSr$   )clsfilewriter`   ra   rb   r5   r5   r6   __new__   s
   zZipFS.__new__c                 C   s   d S rE   r5   )r0   re   rf   r`   ra   rb   r5   r5   r6   r.      s   	zZipFS.__init__N)
rW   rX   rY   __doc__zipfileZIP_DEFLATEDrg   typingTYPE_CHECKINGr.   r5   r5   r5   r6   r]      s    .
r]   c                       sf   e Zd ZdZejddf fdd	Zdd Zdd	 Zd
d Z	dd Z
 fddZ			dddZ  ZS )rc   zA writable zip file.r^   r_   c                    sH   || _ || _|| _|| _t|| _t| j | _t	t
| | j d S rE   )_filer`   ra   _temp_fs_urlr   _temp_fsdictgetmeta_metar-   rc   r.   )r0   re   r`   ra   rb   r3   r5   r6   r.     s   
zWriteZipFS.__init__c                 C   s   d}| | j| j| j| jS )Nz?WriteZipFS({!r}, compression={!r}, encoding={!r}, temp_fs={!r}))rQ   rm   r`   ra   rn   )r0   tr5   r5   r6   __repr__  s   zWriteZipFS.__repr__c                 C      d | jS )Nz<zipfs-write '{}'>rQ   rm   rF   r5   r5   r6   __str__     zWriteZipFS.__str__c                 C   s
   | j |fS rE   ro   r0   pathr5   r5   r6   delegate_path  s   
zWriteZipFS.delegate_pathc                 C   rD   rE   ry   rF   r5   r5   r6   delegate_fs!  rH   zWriteZipFS.delegate_fsc                    s>   |   sz|   W | j  n| j  w tt|   d S rE   )isclosedr	   ro   closer-   rc   rF   r3   r5   r6   r   %  s
   
zWriteZipFS.closeNc                 C   s4   |   st| j|p| j|p| j|p| jd dS dS )a5  Write zip to a file.

        Arguments:
            file (str or io.IOBase, optional): Destination file, may be
                a file name or an open file handle.
            compression (int, optional): Compression to use (one of the
                constants defined in the `zipfile` module in the stdlib).
            encoding (str, optional): The character encoding to use
                (default uses the encoding defined in
                `~WriteZipFS.__init__`).

        Note:
            This is called automatically when the ZipFS is closed.

        )r`   ra   N)r~   r	   ro   rm   r`   ra   )r0   re   r`   ra   r5   r5   r6   r	   .  s   
zWriteZipFS.write_zip)NNN)rW   rX   rY   rh   ri   rj   r.   rt   rw   r|   r}   r   r	   r\   r5   r5   r3   r6   rc      s    rc   c                       s   e Zd ZdZddddddddZejjd( fdd	Zdd	 Z	d
d Z
dd Zedd Zd)ddZdd Zdd Z		d*ddZd+ddZdd Zdd  Z fd!d"Zd#d$ Zd,d&d'Z  ZS )-r$   zA readable zip file.FT)case_insensitivenetwork	read_onlysupports_renamethread_safeunicode_pathsvirtualr^   c                    s2   t t|   || _|| _t|d| _d | _d S )Nr'   )	r-   r$   r.   rm   ra   ri   ZipFiler(   _directory_fs)r0   re   ra   r3   r5   r6   r.   [  s
   
zReadZipFS.__init__c                 C   ru   )NzReadZipFS({!r})rv   rF   r5   r5   r6   rt   d  rx   zReadZipFS.__repr__c                 C   ru   )Nz<zipfs '{}'>rv   rF   r5   r5   r6   rw   h  rx   zReadZipFS.__str__c                 C   s6   t t|}| j|rt|}tjr|| jS |S )z"Convert a path to a zip file name.)	r   r   
_directoryisdirr   sixPY2encodera   rz   r5   r5   r6   _path_to_zip_namel  s   zReadZipFS._path_to_zip_namec                 C   s   |    | jE | jdu rBt  | _}| j D ])}|}tjr&|| j	d}|
dr3|j|dd q|jt|dd || q| jW  d   S 1 sOw   Y  dS )zC`MemoryFS`: a filesystem with the same folder hierarchy as the zip.Nreplace/T)recreate)check_lockr   r   r(   namelistr   r   decodera   endswithmakedirsr   create)r0   _fszip_nameresource_namer5   r5   r6   r   v  s   

$zReadZipFS._directoryNc                    sD  |  |}|pd}i }|dkr'ddd|d< d|v r#dttji|d< t|S | j|}|j|jd|d< h d	|s| 	|}z| j
| W n tyV   Y t|S w d|v rr jt|jrdtjntjtt j d
|d< d|v r fdd jD |d< d|v r jr jdkrdt jd? d@ d i|d< t|S )Nr5   r    T)r2   is_dirbasicdetailstype>   zipaccessr   )r@   r   modifiedr   c                    s"   i | ]}| d s|t |qS )_)
startswithgetattr).0kzip_infor5   r6   
<dictcomp>  s    
z%ReadZipFS.getinfo.<locals>.<dictcomp>r   r7   permissions   i  )mode)validatepathrM   r
   	directoryr   r)   r2   r   
isdisjointr   r(   KeyErrorr*   re   r   r   	date_time	__slots__external_attrcreate_systemr   dumpr   )r0   r{   
namespaces_pathraw_info
basic_infor   r5   r   r6   r)     sR   
)



zReadZipFS.getinfoc                 C      |    t|rE   r   r   ResourceReadOnly)r0   r{   infor5   r5   r6   setinfo     
zReadZipFS.setinfoc                 C   s   |    | j|S rE   )r   r   listdirrz   r5   r5   r6   r     s   zReadZipFS.listdirc                 C   r   rE   r   )r0   r{   r   r   r5   r5   r6   makedir  s   
zReadZipFS.makedirr'   r9   c                 K   sj   |    d|v sd|v sd|v rt|| j|s t|| j|r+t|| |}t	| |S )Nw+a)
r   r   r   r   existsResourceNotFoundr   FileExpectedr   r&   )r0   r{   r   	bufferingkwargsr   r5   r5   r6   openbin  s   




zReadZipFS.openbinc                 C   r   rE   r   rz   r5   r5   r6   remove  r   zReadZipFS.removec                 C   r   rE   r   rz   r5   r5   r6   	removedir  r   zReadZipFS.removedirc                    s*   t t|   t| dr| j  d S d S )Nr(   )r-   r$   r   hasattrr(   rF   r3   r5   r6   r     s   
zReadZipFS.closec                 C   s8   |    | j|st|| |}| j|}|S rE   )r   r   isfiler   r   r   r(   r=   )r0   r{   r   	zip_bytesr5   r5   r6   	readbytes  s   

zReadZipFS.readbytesdownloadc                 C   s@   |dkrt | jtjrt| j}t|}d||S t||)Nr1   zzip://{}!/{})
isinstancerm   r   string_typesr   rQ   r   NoURL)r0   r{   purposequoted_filequoted_pathr5   r5   r6   geturl  s
   
zReadZipFS.geturl)r^   rE   )NF)r'   r9   )r   )rW   rX   rY   rh   rr   r   CreateFailed	catch_allr.   rt   rw   r   propertyr   r)   r   r   r   r   r   r   r   r   r   r\   r5   r5   r3   r6   r$   M  s:    



4


	)<rh   
__future__r   r   rZ   rk   r   ri   r   r   r   
_url_toolsr   baser   compressr	   enumsr
   r   r   r   iotoolsr   memoryfsr   openerr   r{   r   r   r   r   r   r   timer   wrapfsr   rl   r   r   r   r   r   r   r   r   r   r    r!   subfsr"   TypeVarr#   r&   r]   python_2_unicode_compatiblerc   r$   r5   r5   r5   r6   <module>   s@    0 LL