o
    Q `b                     @   sV  d Z ddlm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ZddlZddlZddlZddlZddlZzddl	mZ W n eyi   zddlmZ W n eyf   dZY nw Y nw zddl	mZ W n ey   zddlmZ W n ey   dZY nw Y nw dd	lmZ dd
lmZ ddlmZ ddlmZmZ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(m)Z) ddlm*Z*m+Z+ ddl,m-Z- ej.rddlm/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 ddlm:Z: ddlm;Z; ddl<m=Z= ej>dddZ?e@dZAe
B dkZCejDG dd deZEdS )zManage the filesystem provided by your OS.

In essence, an `OSFS` is a thin layer over the `io` and `os` modules
of the Python standard library.
    )absolute_import)print_function)unicode_literalsN)scandir)sendfile   )errors)FS)ResourceType)fsencodefsdecodefspath)Info)basenamedirname)Permissions)convert_os_errors)Modevalidate_open_mode)FileExpectedNoURL)	url_quote)AnyBinaryIO
CollectionDictIteratorIOListOptionalSupportsIntTextTuple)_OpendirFactory)RawInfo)SubFS_OOSFS)Zboundzfs.osfsZWindowsc                       s  e Zd ZdZ			dE fdd	Zdd Zd	d
 Zdd Zedd Z	edd Z
ejejejejejejejejejejejejejejiZedd Zdd Zdd ZdFddZdd Z 		dGddZ!dHd d!Z"d"d# Z#d$d% Z$e%j&rydFd&d'Z'dId(d)Z(e)j*dd* d+k re+dure,j-e,j.e,j/e,j0e,j1e,j2hZ3e4e,d,re35e,j6 dId-d.Z7ndId/d.Z7e8rdFd0d1Z9ndFd2d1Z9		dJd3d4Z8d5d6 Z:dKd8d9Z;d:d; Z<d<d= Z=					>	dLd?d@Z>dAdB Z? fdCdDZ@  ZAS )Mr'   a  Create an OSFS.

    Arguments:
        root_path (str or ~os.PathLike): An OS path or path-like object to
            the location on your HD you wish to manage.
        create (bool): Set to `True` to create the root directory if it
            does not already exist, otherwise the directory should exist
            prior to creating the ``OSFS`` instance (defaults to `False`).
        create_mode (int): The permissions that will be used to create
            the directory if ``create`` is `True` and the path doesn't
            exist, defaults to ``0o777``.
        expand_vars(bool): If `True` (the default) environment variables of
            the form $name or ${name} will be expanded.

    Raises:
        `fs.errors.CreateFailed`: If ``root_path`` does not
            exist, or could not be created.

    Examples:
        >>> current_directory_fs = OSFS('.')
        >>> home_fs = OSFS('~/')
        >>> windows_system32_fs = OSFS('c://system32')

    F  Tc              
      s
  t t|   t|trt|}|| _tj	tt
|\}}|r'||p%d n|}tj|r4tj|n|}tjtj|}|| _|rnztj|sVtj|t|d W n& tym } z
td|||d}~ww tj|s~d|}t|ddddtjjdd }	| _z#tjd	d
}
tj|
j |	d< W d   n1 sw   Y  W n ty   t  dkrtj!ddk|	d< Y nw t"rd#dd t$dD d |	d< dS d|	d< dtj%v rzt&t'|tj%d |	d< W dS  ty   Y dS w dS )z!Create an OSFS instance.
        /modezunable to create {} ({})Nzroot path '{}' does not existFT)ZnetworkZ	read_onlyZsupports_renameZthread_safeZunicode_pathsZvirtualZTmP)prefixZcase_insensitiveZDarwinZAaZaa c                 s   s    | ]}t |V  qd S N)sixZunichr).0n r2   )/usr/lib/python3/dist-packages/fs/osfs.py	<genexpr>   s    z OSFS.__init__.<locals>.<genexpr>   z\:*?"<>|Zinvalid_path_chars PC_PATH_MAXZmax_sys_path_length)(superr'   __init__
isinstancebytesr   	root_pathospath
splitdriver   
expanduser
expandvarsnormpathabspath
_root_pathisdirmakedirsintOSErrorr   ZCreateFailedformatsupports_unicode_filenames_metatempfileZNamedTemporaryFileexistsnamelower	Exceptionplatformsystemnormcase_WINDOWS_PLATFORMjoinrangepathconf_namespathconfr   )selfr<   ZcreateZcreate_modeZexpand_varsZ_driverD   errormessagerK   Z	_tmp_file	__class__r2   r3   r9   k   sn   



	
zOSFS.__init__c                 C   s   d}| j j}||| jS )Nz{}({!r}))r]   __name__rI   r<   )rY   Z_fmt_class_namer2   r2   r3   __repr__   s   zOSFS.__repr__c                 C   s   d}| j j}|| | jS )Nz	<{} '{}'>)r]   r^   rI   rO   r<   )rY   Zfmtr_   r2   r2   r3   __str__   s   zOSFS.__str__c                 C   s(   t tj| j|ddtj}|S )z/Convert a FS path to a path on the OS.
        r)   )r   r=   r>   rU   rD   lstripreplaceseprY   r>   sys_pathr2   r2   r3   _to_sys_path   s   zOSFS._to_sys_pathc                 C   sN   ddg|j |j|jt| |d}t|dd|d< trdnd}|j||< |S )zDMake a *details* info dict from an `os.stat_result` object.
        accessedmodified)Z_writerh   ri   sizetypeZst_birthtimeNZcreatedZmetadata_changed)st_atimest_mtimest_sizerG   _get_type_from_statgetattrrT   st_ctime)clsstat_resultdetailsZ	ctime_keyr2   r2   r3   _make_details_from_stat   s   

zOSFS._make_details_from_statc                 C   s   i }t |jd |d< |j |d< }|j |d< }tsNddl}ddl}z
||j	|d< W n	 t
y7   Y nw z||j|d< W |S  t
yM   Y |S w |S )	zDMake an *access* info dict from an `os.stat_result` object.
        r*   permissionsgiduidr   Ngroupuser)r   st_modedumpst_gidst_uidrT   grppwdZgetgrgidZgr_nameKeyErrorgetpwuidZpw_name)rr   rs   accessrw   rx   r   r   r2   r2   r3   _make_access_from_stat   s(   zOSFS._make_access_from_statc                 C   s    |j }t|}| j|tjS )z?Get the resource type from an `os.stat_result` object.
        )r{   statS_IFMTSTAT_TO_RESOURCE_TYPEgetr
   unknown)rr   _statr{   Zst_typer2   r2   r3   ro      s   
zOSFS._get_type_from_statc                 C   sH   t tdr"ztrt|W S ttt|W S  ty!   Y d S w d S )Nreadlink)hasattrr=   rT   r   r   r   rH   )rY   rf   r2   r2   r3   
_gettarget	  s   
zOSFS._gettargetc                 C   s   |  |}d|iS )Ntarget)r   )rY   rf   Z_targetr2   r2   r3   _make_link_info  s   
zOSFS._make_link_infoNc                    s  |    |pd}| |}| |}d  td| tt|d|v r,tt| W d    n1 s6w   Y  dt|t	j
di}d|v rS| |d< d|v rdfdd	tD |d< d|v ru fd
d	t D |d< d|v r| ||d< d|v r| |d< t|S )Nr2   getinfolstatbasicrN   is_dirrt   r   c                    "   i | ]}| d r|t |qS Zst_
startswithrp   r0   k)r   r2   r3   
<dictcomp>,  
    

z OSFS.getinfo.<locals>.<dictcomp>c                    r   r   r   r   )_lstatr2   r3   r   0  r   linkr   )checkvalidatepath
getsyspathr   r=   r   r   r   r   S_ISDIRr{   ru   dirr   r   r   )rY   r>   
namespaces_pathrf   infor2   )r   r   r3   r     s8   





zOSFS.getinfoc                 C   sf   |    | |}| |}td|dd tt|}W d    n1 s'w   Y  dd |D S )NlistdirT	directoryc                 S   s   g | ]}t |qS r2   )r   )r0   rN   r2   r2   r3   
<listcomp>A  s    z OSFS.listdir.<locals>.<listcomp>)r   r   rg   r   r=   r   r   )rY   r>   r   rf   namesr2   r2   r3   r   :  s   

zOSFS.listdirc                 C   s   |    t|}| |}| |}td|dd= zt|| W n' tyJ } z|j	t	j
kr6t||j	t	jkr?|r?n W Y d }~nd }~ww | |W  d    S 1 sZw   Y  d S )NmakedirTr   )r   r   Zget_moder   rg   r   r=   mkdirrH   errnoENOENTr   ResourceNotFoundZEEXISTopendir)rY   r>   rv   Zrecreater+   r   rf   rZ   r2   r2   r3   r   D  s$   



$zOSFS.makedirrc           	      K   s   t |}|  |   | |}|dkrt|| |}td|* tj	r8|j
r8t|tjtjB tjB }tj|f| |d|}W d    |S 1 sQw   Y  |S )Nr)   openbin)r+   	buffering)r   Zvalidate_binr   r   r   r   rg   r   r/   PY2	exclusiver=   openO_RDWRO_CREATO_EXCLioZto_platform_bin)	rY   r>   r+   r   options_moder   rf   binary_filer2   r2   r3   r   [  s*   



zOSFS.openbinc                 C   s   |    | |}| |}td|J zt| W n9 tyT } z-|jtjkr9t	j
dkr9tj|r9t||jtjkrOt	j
dkrOtj|rOt| d }~ww W d    d S 1 s`w   Y  d S )Nremovewin32darwin)r   r   rg   r   r=   r   rH   r   ZEACCESsysrQ   r>   rE   r   r   EPERM)rY   r>   r   rf   rZ   r2   r2   r3   r   l  s$   



"zOSFS.removec                 C   sj   |    | |}|dkrt | |}td|dd t| W d    d S 1 s.w   Y  d S )Nr)   	removedirTr   )r   r   r   ZRemoveRootErrorrg   r   r=   rmdirrY   r>   r   rf   r2   r2   r3   r     s   

"zOSFS.removedirc                 C   s   d S r.   r2   )rY   r>   factoryr2   r2   r3   r     s   zOSFS.opendirc                 C   sp   |  |}|  |}| |tjurt||s#| |r#t|| t|tj	ur4t
t|||fS r.   )r   gettyper
   filer   r   rM   ZDestinationExistsr   r   ZDirectoryExpectedrY   src_pathdst_path	overwrite	_src_path	_dst_pathr2   r2   r3   _check_copy  s   



zOSFS._check_copy   )      ENOTSUPc                 C   sL  | j  | |||\}}| || |}}zTt|dD}t|d.}	| |	 }
}t|
j }}d}|dkrMt	||
||}||7 }|dks>W d    n1 sWw   Y  W d    n1 sfw   Y  W n t
y } z|j| jvr{ t|| W Y d }~nd }~ww W d    d S W d    d S 1 sw   Y  d S )Nr   wr   )_lockr   r   r   r   filenor=   fstatrn   r   rH   r   _sendfile_error_codesshutilcopy2)rY   r   r   r   r   r   Z_src_sysZ_dst_syssrcdstZfd_srcZfd_dstsentmaxsizeoffseter2   r2   r3   copy  s<   "z	OSFS.copyc                 C   sV   | j  | |||\}}t| || | W d    d S 1 s$w   Y  d S r.   )r   r   r   r   r   r   r2   r2   r3   r     s   "c                 #   sf   |    |pd}| |}tr!tj| j|ddtj	}n| 
|}td|dd| t|D ]n}dt|j| di}d|v rO| | |d< d	|v rd| fd
dtD |d	< d|v r{|jdd  fddt D |d< d|v r| tj||j|d< d|v r| | |d< t|V  q2W d    d S 1 sw   Y  d S )Nr2   r)   r   Tr   r   r   rt   r   c                    r   r   r   r   rs   r2   r3   r         
!OSFS._scandir.<locals>.<dictcomp>r   F)follow_symlinksc                    r   r   r   r   lstat_resultr2   r3   r     r   r   r   )r   r   rT   r=   r>   rU   rD   rb   rc   rd   rg   r   r   r   rN   r   r   ru   r   r   r   r   )rY   r>   r   r   rf   Z	dir_entryr   r2   r   rs   r3   _scandir  sN   





"zOSFS._scandirc           	      #   sH   |    |pd}| |}| |}td|dd t|D ]q}t|}tj||}t	t
|d|t	jdi}d|v rJ| |d< d|v r[fd	d
tD |d< d|v rqt|  fdd
t D |d< d|v r| tj|||d< d|v r| |d< t|V  q W d    d S 1 sw   Y  d S )Nr2   r   Tr   r   r   rt   r   c                    r   r   r   r   r   r2   r3   r   !  r   r   r   c                    r   r   r   r   r   r2   r3   r   (  r   r   r   )r   r   r   r   r=   r   r   r>   rU   r   r   r   r{   ru   r   r   r   r   r   )	rY   r>   r   r   rf   Z
entry_nameZ_entry_nameZ
entry_pathr   r2   r   r3   r     sF   







"c                 C   s0   | j ||d}|d ur|\}}t|||}|S )N)r   )r   	itertoolsislice)rY   r>   r   ZpageZ	iter_infostartendr2   r2   r3   r   6  s
   zOSFS.scandirc                 C   s$   t j| j|ddt j}|S )Nr)   )r=   r>   rU   rD   rb   rc   rd   re   r2   r2   r3   r   E  s    zOSFS.getsyspathdownloadc                 C   s<   |  |}|dkrd| S |dkrt|}d| S t||)Nr   zfile://Zfszosfs://)r   r   r   )rY   r>   Zpurposerf   Zurl_pathr2   r2   r3   geturlJ  s   

zOSFS.geturlc                 C   sT   |    | |}td| t|}W d    n1 sw   Y  | |}|S )Nr   )r   rg   r   r=   r   ro   )rY   r>   rf   r   Zresource_typer2   r2   r3   r   U  s   

zOSFS.gettypec                 C   sj   |    | |}| |}| |st|td| tj	|W  d    S 1 s.w   Y  d S )Nislink)
r   r   rg   rM   r   r   r   r=   r>   r   r   r2   r2   r3   r   ^  s   




$zOSFS.islinkr-   c              	   K   s   t |}	t| |   | |}
|
dkrt|| |
}td|: tjr7|	j	r7t
|t
jt
jB t
jB }|p:d}tj|f|	 ||	jrHd n|||	jrOd n|d|W  d    S 1 s`w   Y  d S )Nr)   r   zutf-8)r+   r   encodingr   newline)r   r   r   r   r   rg   r   r/   r   r   r=   r   r   r   r   r   Zto_platformbinary)rY   r>   r+   r   r   r   r   line_bufferingr   r   r   rf   	_encodingr2   r2   r3   r   h  s.   

$z	OSFS.openc           
      C   s   |    | |}| |}tj|st|d|v rr|d }d|v s)d|v rtt	t
|d}t	t
|d|}t
|d u rC|n|}t
|}	|d usR|	d urvtd| t|||	f W d    d S 1 skw   Y  d S d S d S d S )Nrt   rh   ri   setinfo)r   r   rg   r=   r>   rM   r   r   typingcastrG   r   r   utime)
rY   r>   r   r   rf   rt   Z	_accessedZ	_modifiedrh   ri   r2   r2   r3   r     s&   


"zOSFS.setinfoc              
      sN   zt | W n ty } ztj|dj||ddd}~ww tt| |S )z7Check path may be encoded, in addition to usual checks.zSpath '{path}' could not be encoded for the filesystem (check LANG env var); {error})r>   rZ   )msgN)r   UnicodeEncodeErrorr   ZInvalidCharsInPathrI   r8   r'   r   )rY   r>   rZ   r\   r2   r3   r     s   zOSFS.validatepath)Fr(   Tr.   )NF)r   r   )F)NN)r   )r   r   NNr-   F)Br^   
__module____qualname____doc__r9   r`   ra   rg   classmethodru   r   r   S_IFDIRr
   r   S_IFCHR	characterS_IFBLKZblock_special_fileS_IFREGr   S_IFIFOZfifoS_IFLNKsymlinkS_IFSOCKZsocketr   ro   r   r   r   r   r   r   r   r   r   TYPE_CHECKINGr   r   r   version_infor   r   ZEIOEINVALZENOSYSZEBADFENOTSOCK
EOPNOTSUPPr   r   addr   r   r   r   r   r   r   r   r   r   r   __classcell__r2   r2   r\   r3   r'   P   s    F	




 







0,

	
!)Fr   Z
__future__r   r   r   r   r   r   Zloggingr=   rQ   r   r   r   rL   r   r/   r   ImportErrorr   r-   r   baser	   Zenumsr
   Z	_fscompatr   r   r   r   r   r>   r   r   rv   r   Zerror_toolsr   r+   r   r   r   r   Z
_url_toolsr   r  r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   Zsubfsr%   TypeVarr&   Z	getLoggerlogrR   rT   Zpython_2_unicode_compatibler'   r2   r2   r2   r3   <module>   sr    4
