U
    Zfz-                     @   s   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	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 G d	d
 d
eZdS )    N)contextmanager)md5)Path)sleep)time)	BaseCache)FileSystemSerializerc                   @   s  e Zd ZdZdZdZe Zdddefe	e
e
eje
 ejddd	Ze
d
ddZee
d
ddZd<eje
 eje
 ddddZeje
 e
dddZe	edddZeje	ddf d
ddZed
ddZeddddZed
dd Zdd
d!d"Zed
d#d$Ze	e	d%d&d'Ze	ejd%d(d)Zd=e	ejeje
 ed*d+d,Z d>e	ejeje
 eed.d/d0Z!d?e	eed1d2d3Z"e	ed%d4d5Z#ej$ejejejd6d7d8Z%e&e	e	ejd9d:d;Z'dS )@FileSystemCachea  A cache that stores the items on the file system.  This cache depends
    on being the only user of the `cache_dir`.  Make absolutely sure that
    nobody but this cache stores files there or otherwise the cache will
    randomly delete files therein.

    :param cache_dir: the directory where cache files are stored.
    :param threshold: the maximum number of items the cache stores before
                      it starts deleting some. A threshold value of 0
                      indicates no threshold.
    :param default_timeout: the default timeout that is used if no timeout is
                            specified on :meth:`~BaseCache.set`. A timeout of
                            0 indicates that the cache never expires.
    :param mode: the file mode wanted for the cache files, default 0600
    :param hash_method: Default hashlib.md5. The hash method used to
                        generate the filename for cached results.
    z.__wz_cacheZ__wz_cache_counti  i,  N)	cache_dir	thresholddefault_timeoutmodehash_methodc              
   C   s   t | | || _|| _|| _|| _| jd kr8|  | _zt| j W n0 t	k
rx } z|j
t
jkrh W 5 d }~X Y nX | jdkr| jtt|  d d S )Nr   value)r   __init___path
_threshold_hash_method_mode_get_compatible_platform_modeosmakedirsOSErrorerrnoEEXIST_update_countlenlist	_list_dir)selfr
   r   r   r   r   ex r"   1/tmp/pip-unpacked-wheel-7m7iy3r0/cachelib/file.pyr   ,   s    


zFileSystemCache.__init__)returnc                 C   s   d}t  dkrtj}|S )Ni  Windows)platformsystemstatS_IWRITE)r    r   r"   r"   r#   r   K   s    z-FileSystemCache._get_compatible_platform_modec                 C   s   |  | jpdS Nr   )get_fs_count_filer    r"   r"   r#   _file_countQ   s    zFileSystemCache._file_count)deltar   r$   c                 C   s<   | j dkrd S |r| j| }n|p$d}| j| j|dd d S )Nr   T)mgmt_element)r   r.   setr,   )r    r/   r   Z	new_countr"   r"   r#   r   U   s    
zFileSystemCache._update_count)timeoutr$   c                 C   s*   t | |}|dkr"tt | }t|S r*   )r   _normalize_timeoutintr   )r    r2   r"   r"   r#   r3   a   s    z"FileSystemCache._normalize_timeout)namer$   c                 C   s,   |  | jtjd }||kp*|| jS )N)_get_filenamer,   splitr   sependswith_fs_transaction_suffix)r    r5   Zfshashr"   r"   r#   _is_mgmtg   s    zFileSystemCache._is_mgmtc                    s    fddt  jD S )z2return a list of (fully qualified) cache filenamesc                 3   s(   | ] }  |stj j|V  qd S N)r<   r   pathjoinr   ).0fnr-   r"   r#   	<genexpr>m   s   
z,FileSystemCache._list_dir.<locals>.<genexpr>)r   listdirr   r-   r"   r-   r#   r   k   s    

zFileSystemCache._list_dirc                 C   s   | j dko| j| j kS r*   )r   r.   r-   r"   r"   r#   _over_thresholds   s    zFileSystemCache._over_threshold)nowr$   c                 C   s   |   D ]}zX| |d}td|dd }W 5 Q R X |dkrb||k rbt| | jdd W q tk
rx   Y q t	t
tjfk
r   tjd|dd	 Y qX qd S )
NrbI   r   r6   r/   /Exception raised while handling cache file '%s'Texc_info)r   _safe_stream_openstructunpackreadr   remover   FileNotFoundErrorr   EOFErrorerrorloggingwarning)r    rE   fnamefexpiresr"   r"   r#   _remove_expiredv   s     
zFileSystemCache._remove_expiredc                 C   s   g }|   D ]}z@| |d*}td|dd }|||f W 5 Q R X W q tk
rd   Y q tttj	fk
r   t
jd|dd Y qX qdd	 t|d
d dD }|D ]j}zt| | jdd W n< tk
r   Y n* tk
r
   t
jd|dd Y  dS X |  s qqdS )NrF   rG   rH   r   rJ   TrK   c                 s   s   | ]\}}|V  qd S r=   r"   )r@   _rW   r"   r"   r#   rB      s   z0FileSystemCache._remove_older.<locals>.<genexpr>c                 S   s   | d S r*   r"   )itemr"   r"   r#   <lambda>       z/FileSystemCache._remove_older.<locals>.<lambda>)keyr6   rI   F)r   rM   rN   rO   rP   appendrR   r   rS   rT   rU   rV   sortedr   rQ   r   rD   )r    Zexp_fname_tuplesrW   rX   	timestampZfname_sortedr"   r"   r#   _remove_older   sH     

zFileSystemCache._remove_olderc                 C   s,   |   rt }| | |   r(|   d S r=   )rD   r   rZ   rc   )r    rE   r"   r"   r#   _prune   s
    
zFileSystemCache._prunec              	   C   s~   t |  D ]`\}}zt| W q tk
r6   Y q tk
rj   tjd|dd | j| d Y  dS X q| jdd dS )NrJ   TrK   rI   Fr   r   )		enumerater   r   rQ   rR   r   rU   rV   r   )r    irW   r"   r"   r#   clear   s    zFileSystemCache.clear)r_   r$   c                 C   s2   t |tr"|d}| | }tj| j|S )Nzutf-8)	
isinstancestrencoder   	hexdigestr   r>   r?   r   )r    r_   ZbkeyZ	bkey_hashr"   r"   r#   r7      s    

zFileSystemCache._get_filenamec              
   C   s   |  |}z^| |dH}td|dd }|dksB|t kr\| j|W  5 Q R  W S W 5 Q R X W n> tk
r|   Y n, t	t
tjfk
r   tjd|dd Y nX d S )NrF   rG   rH   r   rJ   TrK   )r7   rM   rN   rO   rP   r   
serializerloadrR   r   rS   rT   rU   rV   r    r_   filenamerX   Zpickle_timer"   r"   r#   r+      s    
(zFileSystemCache.get)r_   r   r2   r$   c                 C   s(   |  |}tj|s$| |||S dS )NF)r7   r   r>   existsr1   )r    r_   r   r2   ro   r"   r"   r#   add   s    
zFileSystemCache.addF)r_   r   r2   r0   r$   c              	   C   s   |r
d}n|    | |}| |}tj|}ztj| j| j	d\}}t
|d&}	|	td| | j||	 W 5 Q R X | tj|| | tj|| j t| j}
W n& tk
r   tjd|dd Y dS X |s|s| jd	d
 |
dkS d S )Nr   )suffixdirwbrG   rJ   TrK   F   rI   )rd   r3   r7   r   r>   isfiletempfilemkstempr;   r   fdopenwriterN   packrl   dump_run_safelyreplacechmodr   r   r(   st_sizer   rU   rV   r   )r    r_   r   r2   r0   ro   	overwritefdtmprX   fsizer"   r"   r#   r1      s6    

 
zFileSystemCache.set)r_   r0   r$   c                 C   sf   zt | | W n8 tk
r*   Y dS  tk
rL   tjddd Y dS X |s^| jdd dS d S )NTz*Exception raised while handling cache filerK   Fr6   rI   )r   rQ   r7   rR   r   rU   rV   r   )r    r_   r0   r"   r"   r#   delete  s    zFileSystemCache.deletec              
   C   s   |  |}zd| |dN}td|dd }|dksB|t krRW 5 Q R  W dS W 5 Q R  W dS W 5 Q R X W nB tk
r   Y dS  tttj	fk
r   t
jd|dd Y dS X d S )	NrF   rG   rH   r   TFrJ   rK   )r7   rM   rN   rO   rP   r   rR   r   rS   rT   rU   rV   rn   r"   r"   r#   has  s     
zFileSystemCache.has)rA   argskwargsr$   c                 O   st   t  dkrfd}d}d}d}||k rpz|||}W qd tk
r^   t| ||7 }|d9 }Y qX qpqn
|||}|S )ztOn Windows os.replace, os.chmod and open can yield
        permission errors if executed by two different processes.r%   NgMbP?g      $@g           )r&   r'   PermissionErrorr   )r    rA   r   r   outputZ	wait_stepZmax_sleep_timeZtotal_sleep_timer"   r"   r#   r}   /  s    
zFileSystemCache._run_safely)r>   r   r$   c                 c   s4   |  t||}|d krtz
|V  W 5 |  X d S r=   )r}   openr   close)r    r>   r   fsr"   r"   r#   rM   F  s    
z!FileSystemCache._safe_stream_open)NN)N)NF)F)(__name__
__module____qualname____doc__r;   r,   r   rl   r   ri   r4   _tOptionalAnyr   r   propertyr.   r   r3   boolr<   	Generatorr   rD   floatrZ   rc   rd   rg   r7   r+   rq   r1   r   r   Callabler}   r   rM   r"   r"   r"   r#   r	      sd       &
  +r	   )r   rU   r   r&   r(   rN   rw   typingr   
contextlibr   hashlibr   pathlibr   r   r   Zcachelib.baser   Zcachelib.serializersr   r	   r"   r"   r"   r#   <module>   s   