a
    xd\                     @   s
  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mZm	Z	m
Z
mZ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 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# eeeej$fZ%e&dZ'e(e(dddZ)G dd dZ*dS )    N)OrderedDict)datetime)AnyDictIteratorListOptionalUnion)settings)DEFAULT_TIMEOUT	BaseCacheget_key_func)ImproperlyConfigured)import_string)Redis)ConnectionErrorResponseErrorTimeoutError   )pool)CompressorErrorConnectionInterrupted)CacheKeyz([*?[]))sreturnc                 C   s   t d| S )Nz[\1])
special_resub)r    r   S/var/www/html/Ranjet/env/lib/python3.9/site-packages/django_redis/client/default.pyglob_escape   s    r   c                
   @   s  e Zd Zeeef eddddZeedddZ	dfee
ee  ed	d
dZdgee
ee  edddZdheedddZdiddZeddddfeee
e e
e e
e eeedddZdjeee
e e
e edddZeddfeeee
e e
e edddZdkee
e e
e ed d!d"Zdlee
e e
e dd d#d$Zdmee
e e
e dd d%d&Zdnd'd(Zdoeeeef e
e e
e dd)d*d+Zdpe
e e
e d-d.d/Zdqee
e e
e e
e ed0d1d2Zdree
e e
e e
e e
e ed3d4d5Z dse
e e
e d-d6d7Z!dte
e dd8d9d:Z"ee#ef ed;d<d=Z$eee#ef d;d>d?Z%due
e e
e e&d@dAdBZ'eddfeeef e
e e
e e
e ddCdDdEZ(dveee
e e
e eedFdGdHZ)dweee
e e
e eedFdIdJZ*dxeee
e e
e eddKdLZ+dyee
e e
e e
e d dMdNZ,dzdOdPZ-d{ee
e e
e ed dQdRZ.d|ee
e e
e e
e e/e dSdTdUZ0d}ee
e e
e ee dVdWdXZ1d~ee
e e
e e2dYdZd[Z3dee
e e
e e2d\d]d^Z4d_d` Z5dadb Z6eddfee
e e
e e
e edcdddeZ7dS )DefaultClientN)paramsbackendr   c                 C   s   || _ || _|| _t|dp d| _| js4tdt| jtt	t
fsT| jd| _d gt| j | _|di | _| jdd| _| jdd	}t|}| jd
d}t|}|| jd| _|| jd| _tj| jd| _d S )NZREVERSE_KEY_FUNCTIONz%django_redis.util.default_reverse_keyzMissing connections string,OPTIONSZREPLICA_READ_ONLYTZ
SERIALIZERz0django_redis.serializers.pickle.PickleSerializerZ
COMPRESSORz4django_redis.compressors.identity.IdentityCompressor)options)_backend_server_paramsr   getreverse_keyr   
isinstancelisttuplesetsplitlen_clients_options_replica_read_onlyr   _serializer_compressorr   Zget_connection_factoryconnection_factory)selfserverr!   r"   Zserializer_pathZserializer_clsZcompressor_pathZcompressor_clsr   r   r   __init__   s2    
zDefaultClient.__init__)keyr   c                 C   s
   |  |S N)has_key)r7   r:   r   r   r   __contains__@   s    zDefaultClient.__contains__T)writetriedr   c                    sx    du rt    rLt t| jk rL fddtdt| jD }t|S |s^t| jdkrbdS tdt| jd S )z
        Return a next index for read client. This function implements a default
        behavior for get a next read client for a replication setup.

        Overwrite this function if you want a specific
        behavior.
        Nc                    s   g | ]}| vr|qS r   r   ).0ir?   r   r   
<listcomp>Q       z7DefaultClient.get_next_client_index.<locals>.<listcomp>r      )r,   r0   r'   rangerandomchoicerandint)r7   r>   r?   Z	not_triedr   rB   r   get_next_client_indexC   s    

z#DefaultClient.get_next_client_indexFr>   r?   
show_indexc                 C   sL   | j ||d}| j| du r,| || j|< |r>| j| |fS | j| S dS )z
        Method used for obtain a raw redis client.

        This function is used by almost all cache backend
        operations for obtain a native redis client/connection
        instance.
        )r>   r?   N)rJ   r1   connect)r7   r>   r?   rL   indexr   r   r   
get_clientY   s    zDefaultClient.get_clientr   )rN   r   c                 C   s   | j | j| S )z
        Given a connection index, returns a new raw redis client/connection
        instance. Index is used for replication setups and indicates that
        connection string should be used. In normal setups, index is 0.
        )r6   rM   r'   )r7   rN   r   r   r   rM   p   s    zDefaultClient.connectc                 C   s"   |s| j | }|r| j|S dS )z9delegates the connection factory to disconnect the clientN)r1   r6   
disconnect)r7   rN   clientr   r   r   rP   x   s    
zDefaultClient.disconnect)r:   valuetimeoutversionrQ   nxxxr   c              
   C   s   | j ||d}| |}	|tu r(| jj}|}
g }z|du rN| jd|dd\}}|durt|d }|dkr|r| j|||d W S t| j	|||dW S t|j
||	|||d	W S  ty } zN|
s| jst|t| jk r|| d}W Y d}~q0t|d
|W Y d}~q0d}~0 0 q0dS )z
        Persist a value to the cache, and set an optional expiration time.

        Also supports optional nx parameter. If set to True - will use redis
        setnx instead of set.
        rT   NTrK     r   rT   rQ   )rQ   rT   )rU   ZpxrV   
connection)make_keyencoder   r&   default_timeoutrO   intr<   booldeleter.   _main_exceptionsr3   r0   r'   appendr   )r7   r:   rR   rS   rT   rQ   rU   rV   ZnkeyZnvalueZoriginal_clientr?   rN   er   r   r   r.   ~   s>    


zDefaultClient.setrE   )r:   deltarT   rQ   r   c           
   
   C   s   |du r| j dd}|du r$| jj}| ||}| j|||d}z| j|||d}W n0 ty } zt|d|W Y d}~n
d}~0 0 |du rtd| t	|t
r| j| || d}	n| j||| d}	| j|	|||d | j||d	 || S )
zh
        Adds delta to the cache version for the supplied key. Returns the
        new version.
        NTr>   rY   rZ   Key '%s' not foundrW   )rS   rQ   )rQ   )rO   r&   rT   r\   r)   ttlrb   r   
ValueErrorr+   r   Zoriginal_keyr.   ra   )
r7   r:   re   rT   rQ   Zold_keyrR   rh   rd   Znew_keyr   r   r   incr_version   s$    "
zDefaultClient.incr_version)r:   rR   rS   rT   rQ   r   c                 C   s   | j |||||ddS )z
        Add a value to the cache, failing if the key already exists.

        Returns ``True`` if the object was added, ``False`` if not.
        T)rT   rQ   rU   )r.   )r7   r:   rR   rS   rT   rQ   r   r   r   add   s    zDefaultClient.add)r:   rT   rQ   r   c              
   C   sx   |du r| j dd}| j||d}z||}W n0 ty` } zt|d|W Y d}~n
d}~0 0 |du rn|S | |S )zv
        Retrieve a value from the cache.

        Returns decoded value if key is found, the default if not.
        NFrf   rW   rZ   )rO   r\   r)   rb   r   decode)r7   r:   defaultrT   rQ   rR   rd   r   r   r   r)      s    "zDefaultClient.getc                 C   s:   |d u r| j dd}| j||d}||r6|| d S NTrf   rW   )rO   r\   existspersist)r7   r:   rT   rQ   r   r   r   rp     s
    
zDefaultClient.persistc                 C   s<   |d u r| j dd}| j||d}||r8||| d S rn   )rO   r\   ro   expirer7   r:   rS   rT   rQ   r   r   r   rq     s
    
zDefaultClient.expirec                 C   s<   |d u r| j dd}| j||d}||r8||| d S rn   )rO   r\   ro   pexpirerr   r   r   r   rs   %  s
    
zDefaultClient.pexpire)r:   whenrT   rQ   r   c                 C   s<   |du r| j dd}| j||d}||r8||| dS )z
        Set an expire flag on a ``key`` to ``when``, which can be represented
        as an integer indicating unix time or a Python datetime object.
        NTrf   rW   )rO   r\   ro   Zexpireat)r7   r:   rt   rT   rQ   r   r   r   	expire_at.  s
    
zDefaultClient.expire_at皙?rY   c                 C   s6   |d u r| j dd}| j||d}|j|||||dS )NTrf   rW   )rS   sleepblocking_timeoutthread_local)rO   r\   lock)r7   r:   rT   rS   rw   rx   rQ   ry   r   r   r   rz   A  s    
zDefaultClient.lock)r:   rT   prefixrQ   r   c              
   C   sb   |du r| j dd}z|| j|||dW S  ty\ } zt|d|W Y d}~n
d}~0 0 dS )z.
        Remove a key from the cache.
        NTrf   rT   r{   rZ   )rO   ra   r\   rb   r   )r7   r:   rT   r{   rQ   rd   r   r   r   ra   W  s    
zDefaultClient.delete)patternrT   r{   rQ   itersizer   c           	   
   C   s   |du r| j dd}| j|||d}z0d}|j||dD ]}|| |d7 }q8|W S  ty } zt|d|W Y d}~n
d}~0 0 dS )	z3
        Remove all keys matching pattern.
        NTrf   r|   r   matchcountrE   rZ   )rO   make_pattern	scan_iterra   rb   r   )	r7   r}   rT   r{   rQ   r~   r   r:   rd   r   r   r   delete_patterni  s    

zDefaultClient.delete_patternc              
      sr   |du r j dd} fdd|D }|s0dS z|j| W S  tyl } zt|d|W Y d}~n
d}~0 0 dS )z/
        Remove multiple keys at once.
        NTrf   c                    s   g | ]} j |d qS )rW   r\   r@   kr7   rT   r   r   rC     rD   z-DefaultClient.delete_many.<locals>.<listcomp>rZ   )rO   ra   rb   r   )r7   keysrT   rQ   rd   r   r   r   delete_many  s    zDefaultClient.delete_many)rQ   r   c              
   C   sV   |du r| j dd}z|  W n0 tyP } zt|d|W Y d}~n
d}~0 0 dS )z'
        Flush all cache keys.
        NTrf   rZ   )rO   Zflushdbrb   r   )r7   rQ   rd   r   r   r   clear  s    zDefaultClient.clear)rR   r   c                 C   sX   zt |}W nF ttfyR   z| j|}W n ty@   Y n0 | j|}Y n0 |S )z)
        Decode the given value.
        )r_   ri   	TypeErrorr5   
decompressr   r4   loadsr7   rR   r   r   r   rl     s    zDefaultClient.decodec                 C   s4   t |tst |ts0| j|}| j|}|S |S )z)
        Encode the given value.
        )r+   r`   r_   r4   dumpsr5   compressr   r   r   r   r]     s
    zDefaultClient.encode)rT   rQ   r   c           
   
      s   |du r j dd}|st S t }t fdd|D }z|j| }W n0 tyz } zt|d|W Y d}~n
d}~0 0 t||D ]$\}}	|	du rq |	||| < q|S )z%
        Retrieve many keys.
        NFrf   c                 3   s    | ]} j |d |fV  qdS )rW   Nr   r   r   r   r   	<genexpr>  rD   z)DefaultClient.get_many.<locals>.<genexpr>rZ   )rO   r   Zmgetrb   r   ziprl   )
r7   r   rT   rQ   Zrecovered_dataZmap_keysresultsrd   r:   rR   r   r   r   get_many  s    "zDefaultClient.get_many)datarS   rT   rQ   r   c           	   
   C   s   |du r| j dd}z:| }| D ]\}}| j|||||d q&|  W n0 ty~ } zt|d|W Y d}~n
d}~0 0 dS )a"  
        Set a bunch of values in the cache at once from a dict of key/value
        pairs. This is much more efficient than calling set() multiple times.

        If timeout is given, that timeout will be used for the key; otherwise
        the default cache timeout will be used.
        NTrf   rY   rZ   )rO   pipelineitemsr.   executerb   r   )	r7   r   rS   rT   rQ   r   r:   rR   rd   r   r   r   set_many  s    zDefaultClient.set_many)r:   re   rT   rQ   ignore_key_checkr   c           
   
   C   s   |d u r| j dd}| j||d}zz6|s0d}nd}||d||}|d u rXtd| W n^ ty   | j|||d}|d	krtd| | j|||d| }| j|||||d
 Y n0 W n0 ty }	 zt	|d|	W Y d }	~	n
d }	~	0 0 |S )NTrf   rW   z
                    local exists = redis.call('EXISTS', KEYS[1])
                    if (exists == 1) then
                        return redis.call('INCRBY', KEYS[1], ARGV[1])
                    else return false end
                    zW
                    return redis.call('INCRBY', KEYS[1], ARGV[1])
                    rE   rg   rY   )rT   rS   rQ   rZ   )
rO   r\   evalri   r   rh   r)   r.   rb   r   )
r7   r:   re   rT   rQ   r   ZluarR   rS   rd   r   r   r   _incr  s(    "zDefaultClient._incrc                 C   s   | j |||||dS )z
        Add delta to value in the cache. If the key does not exist, raise a
        ValueError exception. if ignore_key_check=True then the key will be
        created and set to the delta value by default.
        )r:   re   rT   rQ   r   r   )r7   r:   re   rT   rQ   r   r   r   r   incr(  s    zDefaultClient.incrc                 C   s   | j || ||dS )zx
        Decreace delta to value in the cache. If the key does not exist, raise a
        ValueError exception.
        )r:   re   rT   rQ   r   )r7   r:   re   rT   rQ   r   r   r   decr=  s    zDefaultClient.decrc                 C   sf   |du r| j dd}| j||d}||s0dS ||}|dkrF|S |dkrRdS |dkr^dS dS dS )z
        Executes TTL redis command and return the "time-to-live" of specified key.
        If key is a non volatile key, it returns None.
        NFrf   rW   r   r   )rO   r\   ro   rh   r7   r:   rT   rQ   tr   r   r   rh   J  s    

zDefaultClient.ttlc                 C   sf   |du r| j dd}| j||d}||s0dS ||}|dkrF|S |dkrRdS |dkr^dS dS dS )z
        Executes PTTL redis command and return the "time-to-live" of specified key.
        If key is a non volatile key, it returns None.
        NFrf   rW   r   r   r   )rO   r\   ro   pttlr   r   r   r   r   d  s    

zDefaultClient.pttlc              
   C   sh   |du r| j dd}| j||d}z||dkW S  tyb } zt|d|W Y d}~n
d}~0 0 dS )z%
        Test if key exists.
        NFrf   rW   rE   rZ   )rO   r\   ro   rb   r   )r7   r:   rT   rQ   rd   r   r   r   r<   |  s    zDefaultClient.has_key)searchr~   rQ   rT   r   c                 c   sJ   |du r| j dd}| j||d}|j||dD ]}| | V  q0dS )zo
        Same as keys, but uses redis >= 2.8 cursors
        for make memory efficient keys iteration.
        NFrf   rW   r   )rO   r   r   r*   rl   )r7   r   r~   rQ   rT   r}   itemr   r   r   	iter_keys  s
    zDefaultClient.iter_keys)r   rT   rQ   r   c              
      sr   |du r j dd} j||d}z fdd||D W S  tyl } zt|d|W Y d}~n
d}~0 0 dS )z
        Execute KEYS command and return matched results.
        Warning: this can return huge number of results, in
        this case, it strongly recommended use iter_keys
        for it.
        NFrf   rW   c                    s   g | ]}  | qS r   )r*   rl   r   r7   r   r   rC     rD   z&DefaultClient.keys.<locals>.<listcomp>rZ   )rO   r   r   rb   r   )r7   r   rT   rQ   r}   rd   r   r   r   r     s    
zDefaultClient.keys)r:   rT   r{   r   c                 C   sB   t |tr|S |d u r| jj}|d u r.| jj}t| j|||S r;   )r+   r   r&   
key_prefixrT   key_func)r7   r:   rT   r{   r   r   r   r\     s    
zDefaultClient.make_key)r}   rT   r{   r   c                 C   sV   t |tr|S |d u r| jj}t|}|d u r6| jj}tt|}t| j|||S r;   )r+   r   r&   r   r   rT   strr   )r7   r}   rT   r{   version_strr   r   r   r     s    
zDefaultClient.make_patternc                 K   s&   | j dttdd}|r"|   d S )NZCLOSE_CONNECTIONZDJANGO_REDIS_CLOSE_CONNECTIONF)r2   r)   getattrr
   do_close_clients)r7   kwargsZ
close_flagr   r   r   close  s    
zDefaultClient.closec                 C   s4   t | j}t|D ]}| j|d qdg| | _dS )z1default implementation: Override in custom client)rN   N)r0   r1   rF   rP   )r7   Znum_clientsidxr   r   r   r     s    
zDefaultClient.do_close_clients)r:   rS   rT   rQ   r   c                 C   sh   |t u r| jj}|du r$| jdd}| j||d}|du rHt||S t|d }t|||S dS )z2
        Sets a new expiration for a key.
        NTrf   rW   rX   )	r   r&   r^   rO   r\   r`   rp   r_   rs   rr   r   r   r   touch  s    zDefaultClient.touch)TN)TNF)r   )r   N)rE   NN)NNN)NN)NN)NN)NN)NNrv   NNT)NNN)NNNN)NN)N)NN)rE   NNF)rE   NNF)rE   NN)NN)NN)NN)NNN)NN)NN)NN)8__name__
__module____qualname__r   r   r   r   r9   r`   r=   r   r   r_   rJ   rO   r   rM   rP   r   floatr.   rj   rk   r)   rp   rq   rs   r	   r   ru   rz   ra   r   r   r   bytesrl   r]   r   r   r   r   r   r   rh   r   r<   r   r   r   r   r\   r   r   r   r   r   r   r   r   r       s  #    


@   *      
  
               
    7        
       
r    )+rG   resocketcollectionsr   r   typingr   r   r   r   r   r	   Zdjango.confr
   Zdjango.core.cache.backends.baser   r   r   Zdjango.core.exceptionsr   Zdjango.utils.module_loadingr   Zredisr   Zredis.exceptionsr   r   r    r   
exceptionsr   r   utilr   rS   rb   compiler   r   r   r    r   r   r   r   <module>   s$    
