o
    Q `9f                     @   sV  d Z ddlmZ ddlmZ ddlZddl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 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 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' ddl%m(Z( ddl%m)Z) ddl%m*Z* ddlm+Z, e	j-rddlZddl	m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; ddlm<Z< ddlm=Z= ddl>m?Z? dd l@mAZA e	jBd!d"d#ZCd"gZDed3d$d%ZEed&d' ZFd(d) ZGerd*d+ ZHd,d- ZInd.d+ ZHd/d- ZIG d0d1 d1ejJZKG d2d" d"eZLdS )4z*Manage filesystems on remote FTP servers.
    )print_function)unicode_literalsN)OrderedDict)contextmanager)FTP)
error_perm)
error_temp)cast)PY2)	text_type   )errors)FS)DEFAULT_CHUNK_SIZE)ResourceType)SeekInfo)line_iterator)Mode)abspath)dirname)basename)normpath)split)
_ftp_parse)AnyBinaryIO
ByteStringContextManagerIterableIterator	ContainerDictListOptionalSupportsIntTextTupleUnion)_OpendirFactory)RawInfo)Permissions)SubFS_FFTPFS)Zboundc              
   c   s"   z| j  d V  W d    W d S 1 sw   Y  W d S  tjy.   tjd| jd ty>   tjd| jd tya } z|d urTtj	|d||dtj
d|dd }~w ty } z$t|\}}|dkrytj||d|dv rtjtt|d	tj|dd }~ww )
Nzunable to connect to {})msgzlost connection to {}zftp error on resource '{}' ({})zftp error ({})Z552)pathr0   )Z501550r1   )_locksocketerrorr   ZRemoteConnectionErrorformathostEOFErrorr   ZResourceErrorZOperationFailedr   _parse_ftp_errorZInsufficientStorageResourceNotFoundr	   strZPermissionDenied)fsr1   r6   codemessage r@   */usr/lib/python3/dist-packages/fs/ftpfs.py
ftp_errorsD   s6   &
rB   c                 c   sP    z| V  W z|    W d S  ty   Y d S w z|    W w  ty'   Y w w N)quit	Exception)ftpr@   r@   rA   
manage_ftp`   s   rG   c                 C   s   t | d\}}}||fS )z(Extract code and message from ftp error. )r   	partition)r6   r>   _r?   r@   r@   rA   r:   l   s   r:   c                 C   s   t | tr
| |S | S rC   )
isinstancer   encodestencodingr@   r@   rA   _encodeu   s   rP   c                 C   s   t | tr| |dS | S )NreplacerK   bytesdecoderM   r@   r@   rA   _decodey   s   rU   c                 C      | S rC   r@   rN   rJ   r@   r@   rA   rP         c                 C   rV   rC   r@   rW   r@   r@   rA   rU      rX   c                       s   e Zd Z fddZdd Zedd Zedd Zd	d
 Z fddZ	dd Z
dd Zd'ddZdd Zd'ddZd'ddZdd Zdd Zdd Zd(d!d"Zd#d$ Zejfd%d&Z  ZS ))FTPFilec                    sN   t t|   || _|| _t|| _d| _t	 | _
|  | _d | _d | _d S )Nr   )superrY   __init__r=   r1   r   modepos	threadingZLockr4   	_open_ftprF   
_read_conn_write_conn)selfZftpfsr1   r\   	__class__r@   rA   r[      s   



zFTPFile.__init__c                 C   s   | j  }|td |S )z Open an ftp object for the file.zTYPE I)r=   r_   Zvoidcmdr<   rb   rF   r@   r@   rA   r_      s   
zFTPFile._open_ftpc                 C   s6   | j d u r| jtdt| j| jj | j| _ | j S )NRETR )r`   rF   transfercmdr<   rP   r1   rO   r]   rb   r@   r@   rA   	read_conn   s
   
zFTPFile.read_connc                 C   sf   | j d u r0| jjr| jtdt| j| jj | _ | j S | jtdt| j| jj | j	| _ | j S )NzAPPE STOR )
ra   r\   Z	appendingrF   rg   r<   rP   r1   rO   r]   rh   r@   r@   rA   
write_conn   s   
zFTPFile.write_connc                 C   s   d}| | jj| j| jS )Nz<ftpfile {!r} {!r} {!r}>)r7   r=   ftp_urlr1   r\   )rb   Z_reprr@   r@   rA   __repr__   s   zFTPFile.__repr__c              
      s   | j s[| jK z9| jd ur| j  d | _| j  | jd ur'| j  d | _z| j  W n	 ty7   Y nw W t	t
|   nt	t
|   w W d    d S 1 sTw   Y  d S d S rC   )closedr4   ra   closerF   Zvoidrespr`   rD   r   rZ   rY   rh   rc   r@   rA   ro      s&   




""zFTPFile.closec                 C   s   | j S rC   )r]   rh   r@   r@   rA   tell   s   zFTPFile.tellc                 C      | j jS rC   )r\   readingrh   r@   r@   rA   readable      zFTPFile.readablec              	   C   s   | j jstdg }|}| j}| jA |rL|dk rt}ntt|}z||}W n
 tj	y2   Y nw |s6n|
| |  jt|7  _|t|8 }|sW d    n1 sVw   Y  d|S )NzFile not open for readingr       )r\   rr   IOErrorri   r4   r   minZrecvr5   r6   appendr]   lenjoin)rb   sizechunksZ	remainingconnZ	read_sizechunkr@   r@   rA   read   s0   


zFTPFile.readc                 C   s&   |  t|}t|}||d |< |S rC   )r   rz   )rb   bufferdataZ
bytes_readr@   r@   rA   readinto   s   zFTPFile.readintoc                 C   s   t t| |S rC   )nextr   )rb   r|   r@   r@   rA   readline   s   zFTPFile.readlinec                 C   sF   g }d}t | D ]}|| |t|7 }|dkr ||kr  |S q|S )Nr   ru   )r   ry   rz   )rb   Zhintlinesr|   liner@   r@   rA   	readlines   s   
 zFTPFile.readlinesc                 C   rq   rC   )r\   writingrh   r@   r@   rA   writable  rt   zFTPFile.writablec                 C   s   | j jstd| j= | j}d}t|}|r@t|t}|||||  }||7 }||8 }|  j	|7  _	|sW d    |S W d    |S 1 sKw   Y  |S )NzFile not open for writingr   )
r\   r   rw   r4   rk   rz   rx   r   sendr]   )rb   r   r~   Zdata_posZremaining_data
chunk_sizeZ	sent_sizer@   r@   rA   write  s(   


zFTPFile.writec                 C   s   |  d| d S )Nrv   )r   r{   )rb   r   r@   r@   rA   
writelines  s   zFTPFile.writelinesNc              	   C   s   | j c |d u r|  }| j| j}||}W d    n1 s#w   Y  | j| jd}|| t||k rG|d|t|   W d    n1 sQw   Y  W d    |S W d    |S 1 siw   Y  |S )Nw    )r4   rp   r=   openbinr1   r   r   rz   )rb   r|   fr   r@   r@   rA   truncate  s&   

	
		zFTPFile.truncatec                 C   s   dS )NTr@   rh   r@   r@   rA   seekable-  rX   zFTPFile.seekablec                 C   s   t |}|tjtjtjfvrtd| j^ |tjkr|}n|tjkr)| j| }n|tjkr9| j	| j
}|| }td|| _| j  |  | _| jrT| j  d | _| jri| j  d | _W d    |  S W d    |  S 1 svw   Y  |  S )Nzinvalid value for whencer   )intr   setZcurrentend
ValueErrorr4   r]   r=   getsizer1   maxrF   rD   r_   r`   ro   ra   rp   )rb   r]   whenceZ_whenceZnew_pos	file_sizer@   r@   rA   seek1  s6   








zFTPFile.seek)ru   rC   )__name__
__module____qualname__r[   r_   propertyri   rk   rm   ro   rp   rs   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r@   r@   rc   rA   rY      s*    





rY   c                       s  e Zd ZdZdddddddZ							
dS fdd	Zdd Zdd Zedd Z	edd Z
edd Zdd Zdd Zedd Zedd ZdTd d!Zd"d# Zed$d% Zd&d' Zed(d) ZdUd*d+Zed,d- Zed.d/ Zed0d1 ZejrdVd2d3ZdVd4d5ZdWd7d8Zd9d: Z	
	dXd;d<Z dYd?d@Z!dAdB Z"dCdD Z#dVdEdFZ$	
	
dZdGdHZ%dVdIdJZ&dKdL Z'dMdN Z(dOdP Z) fdQdRZ*  Z+S )[r/   a
  A FTP (File Transport Protocol) Filesystem.

    Arguments:
        host (str): A FTP host, e.g. ``'ftp.mirror.nl'``.
        user (str): A username (default is ``'anonymous'``).
        passwd (str): Password for the server, or `None` for anon.
        acct (str): FTP account.
        timeout (int): Timeout for contacting server (in seconds,
            defaults to 10).
        port (int): FTP port number (default 21).
        proxy (str, optional): An FTP proxy, or ``None`` (default)
            for no proxy.

     TF)Zinvalid_path_charsZnetworkZ	read_onlyZthread_safeunicode_pathsZvirtual	anonymous 
      Nc                    sT   t t|   || _|| _|| _|| _|| _|| _|| _	d| _
d | _d | _i | _d S )Nlatin-1)rZ   r/   r[   _host_userpasswdaccttimeoutportproxyrO   _ftp_welcome	_features)rb   r8   userr   r   r   r   r   rc   r@   rA   r[   e  s   
zFTPFS.__init__c                 C   s   d | j| jS )NzFTPFS({!r}, port={!r}))r7   r8   r   rh   r@   r@   rA   rm   ~  s   zFTPFS.__repr__c                 C   s$   | j dkrdnd}|j| j| j dS )Nr   z<ftpfs '{host}'>z<ftpfs '{host}:{port}'>)r8   r   )r   r7   r8   )rb   Z_fmtr@   r@   rA   __str__  s   zFTPFS.__str__c                 C   s    | j d u r| jS d| j| jS )Nz{}@{})r   r   r7   r   rh   r@   r@   rA   r     s   z
FTPFS.userc                 C   s   | j d u r| jS | j S rC   )r   r   rh   r@   r@   rA   r8     s   z
FTPFS.hostc                 C   sR   i }| dd dkr'| D ]}|dr&|dd d\}}}|||< q|S )z9Parse a dict of features from FTP feat response.
        -r   Z211rH   r   N)r   
splitlines
startswithrI   )clsfeat_responsefeaturesr   keyrJ   valuer@   r@   rA   _parse_features  s   
zFTPFS._parse_featuresc              	   C   s   t  }|d t| R || j| j| j || j| j	| j
 i | _z
t|dd}W n ty:   d| _Y nw | || _d| jv rHdnd| _tsW|jjd| jd|_W d   n1 saw   Y  | j|_|j| _|S )	zOpen a new ftp object.
        r   ZFEATr   UTF8utf-8r)rO   N)r   Zset_debuglevelrB   Zconnectr8   r   r   Zloginr   r   r   r   rU   sendcmdr   rO   r   r
   ZsockZmakefilefileZwelcomer   )rb   r   r   r@   r@   rA   r_     s,   


zFTPFS._open_ftpc                 C   s   |   }t|S rC   )r_   rG   re   r@   r@   rA   _manage_ftp  s   zFTPFS._manage_ftpc                 C   s\   | j dkr	| j}nd| j| j }| jdks| jdu rd}nd| j| j}d||}|S )z*Get the FTP url this filesystem will open.r   z{}:{}r   Nr   z{}:{}@z
ftp://{}{})r   r8   r7   r   r   )rb   Z
_host_partZ
_user_partZurlr@   r@   rA   rl     s   
zFTPFS.ftp_urlc                 C   s   |   S )z0~ftplib.FTP: the underlying FTP client.
        )_get_ftprh   r@   r@   rA   rF     s   z	FTPFS.ftpdownloadc                 C   s,   |  |}|dkrt||d| j|S )zGet FTP url for resource.r   z{}{})validatepathr   ZNoURLr7   rl   )rb   r1   Zpurpose_pathr@   r@   rA   geturl  s   
zFTPFS.geturlc                 C   s   | j d u r
|  | _ | j S rC   )r   r_   rh   r@   r@   rA   r     s   

zFTPFS._get_ftpc                 C   s   |    | jS )z1dict: features of the remote FTP server.
        )r   r   rh   r@   r@   rA   r     s   zFTPFS.featuresc                 C   s   t t|}g }t| |d | jtdt|| jj |j W d    n1 s*w   Y  dd |D }dd t	
|D }tdd |D }|S )Nr3   zLIST c                 S   s$   g | ]}t |tr|d n|qS )r   rR   ).0r   r@   r@   rA   
<listcomp>  s    z#FTPFS._read_dir.<locals>.<listcomp>c                 S   s   g | ]}t |qS r@   r   )r   raw_infor@   r@   rA   r         c                 S   s   i | ]}|j |qS r@   namer   infor@   r@   rA   
<dictcomp>  r   z#FTPFS._read_dir.<locals>.<dictcomp>)r   r   rB   rF   	retrlinesr<   rP   rO   ry   	ftp_parseparser   )rb   r1   r   r   Z_listZdir_listingr@   r@   rA   	_read_dir  s   zFTPFS._read_dirc                 C   s
   d| j v S )z8bool: whether the server supports MLST feature.
        ZMLST)r   rh   r@   r@   rA   supports_mlst  s   
zFTPFS.supports_mlstc                 C   s   |  |}t| |- |s| |s/t }| jtdt|| jj	 | 	 W d    dS W d    dS 1 s:w   Y  dS )Nrj   TF)
r   rB   isfileioBytesIOrF   
storbinaryr<   rP   rO   )rb   r1   Zwiper   Z
empty_filer@   r@   rA   create  s   

zFTPFS.createc           	      C   s   z2t |dd }t |dd }t |dd }t |dd }t |dd }t |dd }W n
 ty<   Y dS w t||||||f}|S )	z4Parse a time from an ftp directory listing.
        r            r         N)r   r   calendarZtimegm)	r   Z	time_texttm_yearZtm_monthZtm_daytm_hourtm_mintm_secZ
epoch_timer@   r@   rA   _parse_ftp_time  s   zFTPFS._parse_ftp_timec                 C   st   d }i }| dD ]$}|d\}}}|r$|  }| }|||< q	t|d }q	|dvr6||fS d |fS )N;=/).z..)r   rI   striplowerr   rstrip)r   r   r   factsZfactr   sepr   r@   r@   rA   _parse_facts   s   
zFTPFS._parse_factsc                 c   s    |D ]s}|  | \}}|d u rq|dd}|dvrq|dk}i }||d|d< ||d< dt|r6tjntji|d< |d }|d	|d
d}	d}
|	 rUt|	}
|
|d	< d|v rf| |d |d< d|v rs| |d |d< |V  qd S )Ntyper   >   dirr   r   r   is_dirbasicrF   detailsr|   Zsizd0r   ZmodifyZmodifiedr   Zcreated)	r   r   getr   r   	directoryr   isdigitr   )r   r   r   r   r   Z_typer   r   r   Zsize_strr|   r@   r@   rA   _parse_mlsx/  s4   zFTPFS._parse_mlsxc                 C   s   d S rC   r@   )rb   r1   factoryr@   r@   rA   opendirP  rX   zFTPFS.opendirc              	   C   sT  |  |}|pd}|dkrtddddttjidS | jrx| jN t| |d | j	t
d	t|| jj }W d    n1 sCw   Y  t|| jj d
d }| |D ]}t|  W  d    S W d    n1 ssw   Y  t| |d" t|\}}| |}	||	vrt||	| }
|
W  d    S 1 sw   Y  d S )Nr@   r   r   Tr   r   )r   r   r3   zMLST r   ru   )r   r   r   r   r   r   r4   rB   rF   r   r<   rP   rO   rU   r   r   r   r   r   r;   )rb   r1   
namespacesr   Zresponser   r   Zdir_name	file_namer   r   r@   r@   rA   getinfoT  s:   

	

$zFTPFS.getinfostandardc                 C   s0   i }|    |dkr| j }d| jv |d< |S )Nr  r   r   )r   _metacopyr   )rb   	namespacer  r@   r@   rA   getmetas  s   
zFTPFS.getmetac                 C   sJ   |  |}| j dd | |D }W d    |S 1 sw   Y  |S )Nc                 S   s   g | ]}|j qS r@   r   r   r@   r@   rA   r     s    z!FTPFS.listdir.<locals>.<listcomp>)r   r4   scandir)rb   r1   r   Zdir_listr@   r@   rA   listdir|  s   

zFTPFS.listdirc                 C   s   |  |}t| |dc |dkr#|r| |W  d    S t||r*| |sgz| jt|| jj	 W n/ t
yf } z#t|\}}|dkr]| |rSt|| |r]t|t|d }~ww W d    n1 sqw   Y  | |S )Nr3   r   r2   )r   rB   r   r   ZDirectoryExistsisdirrF   ZmkdrP   rO   r   r:   existsr;   )rb   r1   permissionsZrecreater   r6   r>   rJ   r@   r@   rA   makedir  s.   







zFTPFS.makedirr   ru   c           	   	   K   s   t |}|  | |}| jJ z| |}W n! tjy9   |jr(t||jr7| 	t
|s7t|Y nw |jrBt||jrJt|t| || }W d    |S 1 s]w   Y  |S rC   )r   Zvalidate_binr   r4   r  r   r;   rr   r   r	  r   r   FileExpectedZ	exclusiveZ
FileExistsrY   Zto_platform_bin)	rb   r1   r\   	bufferingoptions_moder   r   Zftp_filer@   r@   rA   r     s,   





zFTPFS.openbinc              	   C   s   |    | |}| j< | |rtj|dt| | | jt	|| jj
 W d    n1 s3w   Y  W d    d S W d    d S 1 sKw   Y  d S )Nr3   )checkr   r4   r	  r   r  rB   rF   deleterP   rO   )rb   r1   r   r@   r@   rA   remove  s   

"zFTPFS.removec                 C   s   |  |}|dkrt t| |B z| jt|| jj W n+ tyK } zt	|\}}|dkrF| 
|r<t|| |sFt| d }~ww W d    d S 1 sWw   Y  d S )Nr   r2   )r   r   ZRemoveRootErrorrB   rF   ZrmdrP   rO   r   r:   r   DirectoryExpectedZisemptyZDirectoryNotEmpty)rb   r1   r   r6   r>   rJ   r@   r@   rA   	removedir  s$   




"zFTPFS.removedirc              
   #   s    |}jt jrhg  t|d3 zjtdt|jj  fdd W n t	y@   
|js?t| w W d    n1 sKw   Y   rh D ]}t|V  qW	 W d    d S | D ]}|V  qoW d    d S 1 sw   Y  d S )Nr3   zMLSD c                    s     t| jjS rC   )ry   rU   rF   rO   )lr   rb   r@   rA   <lambda>  r   z FTPFS._scandir.<locals>.<lambda>)r   r4   r   rB   rF   r   r<   rP   rO   r   r  r   r   r  r   r   r   values)rb   r1   r   r   r   r   r@   r  rA   _scandir  s6   


"zFTPFS._scandirc                 C   sL   | j s| |jst|| j||d}|d ur$|\}}t|||}|S )N)r   )r   r  r   r   r  r  	itertoolsislice)rb   r1   r   ZpageZ	iter_infostartr   r@   r@   rA   r    s   
zFTPFS.scandirc              
   K   s   |  |}| jI |  ,}t| | |tdt|| jj | W d    n1 s-w   Y  W d    n1 s<w   Y  W d    d S W d    d S 1 sTw   Y  d S )Nrj   )	r   r4   r   rB   r   r<   rP   rF   rO   )rb   r1   r   r   r  r   rF   r@   r@   rA   upload  s   

"zFTPFS.uploadc                 C   s(   t |ts	td| |t| d S )Nzcontents must be bytes)rK   rS   	TypeErrorr  r   r   )rb   r1   contentsr@   r@   rA   
writebytes  s   
zFTPFS.writebytesc                 C   s   |  |s
t|d S rC   )r
  r   r;   )rb   r1   r   r@   r@   rA   setinfo	  s   

zFTPFS.setinfoc           	      C   s   |  |}t }t| |P |  <}z|tdt|| jj	 |j
 W n! tyG } zt|\}}|dkrB| |rBt| d }~ww W d    n1 sRw   Y  W d    n1 saw   Y  | }|S )Nrf   r2   )r   r   r   rB   r   Z
retrbinaryr<   rP   rF   rO   r   r   r:   r	  r   r  getvalue)	rb   r1   r   r   rF   r6   r>   rJ   Z
data_bytesr@   r@   rA   	readbytes  s,   



zFTPFS.readbytesc                    sB   |   sz| j  W n	 ty   Y nw d | _tt|   d S rC   )ZisclosedrF   rD   rE   r   rZ   r/   ro   rh   rc   r@   rA   ro   "  s   zFTPFS.close)r   r   r   r   r   N)r   )FrC   )r  )NF)r   ru   )NN),r   r   r   __doc__r  r[   rm   r   r   r   r8   classmethodr   r_   r   rl   rF   r   r   r   r   r   r   r   r   r   typingTYPE_CHECKINGr   r  r  r  r  r   r  r  r  r  r  r!  r"  r$  ro   r   r@   r@   rc   rA   r/   L  s    














	







rC   )Mr%  Z
__future__r   r   r   r   r  r5   r^   r'  collectionsr   
contextlibr   Zftplibr   r   r   r	   Zsixr
   r   r   r   baser   Z	constantsr   Zenumsr   r   r   r   Ziotoolsr   r\   r   r1   r   r   r   r   r   r   r   r(  r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r  r,   Zsubfsr-   TypeVarr.   __all__rB   rG   r:   rP   rU   	RawIOBaserY   r/   r@   r@   r@   rA   <module>   sj    @

 D