
    9i(                        d dl 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
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mZmZmZmZmZ d d	lmZ  G d
 deee      Zy)    )annotationsN)Iterable)ceilfloor)
ModuleType)ConfigurationError)SlidingWindowCounterSupportStorageTimestampedSlidingWindow)AnyCallableMemcachedClientPPRcast)get_dependencyc                  J    e Zd ZdZdgZ	 dgZ	 d	 	 	 	 	 	 	 d fdZe	 	 dd       Z	 	 	 	 	 	 	 	 ddZ		 	 	 	 	 	 	 	 ddZ
edd       Zdd	Zdd
ZddZ	 	 d	 	 	 	 	 	 	 	 	 ddZd dZd!dZd"dZd#dZ	 d$	 	 	 	 	 	 	 	 	 d%dZ	 	 	 	 	 	 d&dZd'dZ	 	 	 	 	 	 	 	 	 	 d(dZ xZS ))MemcachedStoragez[
    Rate limit storage with memcached as backend.

    Depends on :pypi:`pymemcache`.
    	memcached
pymemcachec                   t         j                  j                  |      }g | _        |j                  j                         j                  d      D ]?  }|s|j                  d      \  }}| j                  j                  |t        |      f       A |j                  r*|j                  s|j                  s|j                  g| _        | j                  d   j                  | _        t        |j                  dd            | _        t        |j                  dd            | _        t%        t&        t(        t*        t,        t        t        f      gt.        f   |j                  d| j0                              | _        || _        t7        | j                         st9        d	| j                          t;        j<                         | _        d
| j>                  _         tB        |   ||       y
)an  
        :param uri: memcached location of the form
         ``memcached://host:port,host:port``,
         ``memcached:///var/tmp/path/to/sock``
        :param wrap_exceptions: Whether to wrap storage exceptions in
         :exc:`limits.errors.StorageError` before raising it.
        :param options: all remaining keyword arguments are passed
         directly to the constructor of :class:`pymemcache.client.base.PooledClient`
         or :class:`pymemcache.client.hash.HashClient` (if there are more than
         one hosts specified)
        :raise ConfigurationError: when :pypi:`pymemcache` is not available
        ,:r   libraryzpymemcache.clientcluster_libraryzpymemcache.client.hashclient_getterz5memcached prerequisite not available. please install N)wrap_exceptions)#urllibparseurlparsehostsnetlocstripsplitappendintpathportdependenciesmodule
dependencystrpopr   r   r   r   r   listtupler   
get_clientr   optionsr   r   	threadinglocallocal_storagestoragesuper__init__)	selfurir   r1   parsedlochostr(   	__class__s	           K/var/www/html/venv/lib/python3.12/site-packages/limits/storage/memcached.pyr7   zMemcachedStorage.__init__'   s   $ &&s+
==&&(..s3 		+C3JD$JJtSY/0			+ {{6==$kk]
++L9@@7;;y2EFG"KK)+CD 
 "j$uS#X"78:JJKKK9
 dll+$G~V  '__.%)"o>    c                .    | j                   j                  S N)r+   MemcacheErrorr8   s    r>   base_exceptionsz MemcachedStorage.base_exceptionsZ   s     ,,,r?   c                    t        t        t        |      dkD  r |j                  |fi |      S  |j                  |i |      S )z
        returns a memcached client.

        :param module: the memcached module
        :param hosts: list of memcached hosts
           )r   r   len
HashClientPooledClient)r8   r*   r!   kwargss       r>   r0   zMemcachedStorage.get_client`   sY      u:> "!!%262
 	

 )V((%:6:
 	
r?   c                    d|v r@t        j                  |      }d|j                  v s|j                  s|j	                  d        ||i |S )Nnoreply)inspectgetfullargspecargsvarkwr-   )r8   funcrO   rJ   argspecs        r>   call_memcached_funcz$MemcachedStorage.call_memcached_funcs   sJ     ,,T2G-

9%T$V$$r?   c                   t        | j                  d      r| j                  j                  st        t	        | j
                        dkD  r| j                  n| j                        d   }|st        d| j                          | j                  || j
                  fi | j                  | j                  _        t        t        | j                  j                        S )zQ
        lazily creates a memcached client instance using a thread local
        r5   rF   r   zUnable to import )hasattrr4   r5   r   rG   r!   r   r   r   r   r1   r   r   )r8   r+   s     r>   r5   zMemcachedStorage.storage~   s     **I64;M;M;U;U'(+DJJ!(;$$J (+<T=Q=Q<R)STT);););DJJ**.,,*D& $d&8&8&@&@AAr?   c                L    t        | j                  j                  |d            S )zB
        :param key: the key to get the counter value for
        0)r&   r5   getr8   keys     r>   rX   zMemcachedStorage.get   s      4<<##C-..r?   c                8    | j                   j                  |      S )z
        Return multiple counters at once

        :param keys: the keys to get the counter values for

        :meta private:
        )r5   get_many)r8   keyss     r>   r\   zMemcachedStorage.get_many   s     ||$$T**r?   c                :    | j                   j                  |       y)z>
        :param key: the key to clear rate limits for
        N)r5   deleterY   s     r>   clearzMemcachedStorage.clear   s     	C r?   c                   | j                  | j                  j                  ||d      x}	 |S | j                  | j                  j                  ||t	        |      d      s | j                  j                  ||      xs |S |rW| j                  | j                  j
                  | j                  |      |t        j                         z   t	        |      d       |S )a  
        increments the counter for a given rate limit key

        :param key: the key to increment
        :param expiry: amount in seconds for the key to expire in
         window every hit.
        :param amount: the number to increment by
        :param set_expiration_key: set the expiration key with the expiration time if needed. If set to False, the key will still expire, but memcached cannot provide the expiration time.
        FrL   )expirerL   )rS   r5   incraddr   set_expiration_keytime)r8   rZ   expiryamountset_expiration_keyvalues         r>   rd   zMemcachedStorage.incr   s    " --!!3 .  E 	
 L++  #vtF|U ,  ||((f5??%,,((,,S1,#F| % -  Mr?   c                    t        | j                  j                  | j                  |            xs t	        j                               S )z;
        :param key: the key to get the expiry for
        )floatr5   rX   rg   rh   rY   s     r>   
get_expiryzMemcachedStorage.get_expiry   s4    
 T\\%%d&:&:3&?@ODIIKPPr?   c                    |dz   S )z
        Return the expiration key for the given counter key.

        Memcached doesn't natively return the expiration time or TTL for a given key,
        so we implement the expiration time on a separate key.
        z/expires rY   s     r>   rg   z MemcachedStorage._expiration_key   s     Zr?   c                `    	 | j                  | j                  j                  d       y#  Y yxY w)zq
        Check if storage is healthy by calling the ``get`` command
        on the key ``limiter-check``
        zlimiter-checkTF)rS   r5   rX   rC   s    r>   checkzMemcachedStorage.check   s.    
	$$T\\%5%5G	s   &) -c                    t         rA   )NotImplementedErrorrC   s    r>   resetzMemcachedStorage.reset   s    !!r?   c                   ||kD  ryt        j                          }| j                  |||      \  }}| j                  ||||      \  }}	}
}||	z  |z  |
z   }t        |      |z   |kD  ry| j	                  |d|z  |d      }
t        d|	t        j                          |z
  z
        }||z  |z  |
z   }t        |      |kD  r*| j                  | j                  j                  ||d       yy)NF)now   )rj   rk   r   Trb   )	rh   sliding_window_keys_get_sliding_window_infor   rd   minrS   r5   decr)r8   rZ   limitri   rj   rx   previous_keycurrent_keyprevious_countprevious_ttlcurrent_count_weighted_countactualised_previous_ttls                 r>   acquire_sliding_window_entryz-MemcachedStorage.acquire_sliding_window_entry   s     E>iik$($<$<S&#$N!k9=9V9V+v3 :W :
6mQ (,6?-O 6)E1
 !IIQZ5 & M '*!\TYY[3=N-O&P#!886AMQ  ^$u, ((LL%% 	 )  r?   c                ~    t        j                          }| j                  |||      \  }}| j                  ||||      S rA   )rh   rz   r{   r8   rZ   ri   rx   r   r   s         r>   get_sliding_windowz#MemcachedStorage.get_sliding_window  s@     iik$($<$<S&#$N!k,,\;PSTTr?   c                    t        j                          }| j                  |||      \  }}| j                  |       | j                  |       y rA   )rh   rz   r`   r   s         r>   clear_sliding_windowz%MemcachedStorage.clear_sliding_window  s>    iik$($<$<S&#$N!k

< 

;r?   c                   | j                  ||g      }t        |j                  |d            t        |j                  |d            }}|dk(  rt        d      }nd||z
  |z  dz  z
  |z  }d||z  dz  z
  |z  |z   }	||||	fS )Nr   rF   )r\   r&   rX   rn   )
r8   r   r   ri   rx   resultr   r   r   current_ttls
             r>   r{   z)MemcachedStorage._get_sliding_window_info#  s     k:;

<+,

;*+ &
 Q 8L3<6"9Q!>?6ILS6\Q./69FB|]KGGr?   )F)r9   r,   r   boolr1   z$str | Callable[[], MemcachedClientP]returnNone)r   z-type[Exception] | tuple[type[Exception], ...])r*   r   r!   zlist[tuple[str, int]]rJ   r,   r   r   )rQ   zCallable[P, R]rO   zP.argsrJ   zP.kwargsr   r   )r   r   )rZ   r,   r   r&   )r]   zIterable[str]r   zdict[str, Any])rZ   r,   r   r   )rF   T)
rZ   r,   ri   rn   rj   r&   rk   r   r   r&   )rZ   r,   r   rn   )rZ   r,   r   r,   )r   r   )r   z
int | None)rF   )
rZ   r,   r~   r&   ri   r&   rj   r&   r   r   )rZ   r,   ri   r&   r   tuple[int, float, int, float])rZ   r,   ri   r&   r   r   )
r   r,   r   r,   ri   r&   rx   rn   r   r   )__name__
__module____qualname____doc__STORAGE_SCHEMEDEPENDENCIESr7   propertyrD   r0   rS   r5   rX   r\   r`   rd   ro   rg   rs   rv   r   r   r   r{   __classcell__)r=   s   @r>   r   r      s    "]N* >L
 !&1?1? 1? 8	1?
 
1?f -	6- -

 
)>
JM
	
&	%"	%+1	%=E	%	
	% B B$/+! #'%% % 	%
 !% 
%NQ 
" '' ' 	'
 ' 
'RUU #U	&U HH.1H;>HEJH	&Hr?   r   )
__future__r   rM   r2   rh   urllib.parser   collections.abcr   mathr   r   typesr   limits.errorsr   limits.storage.baser	   r
   r   limits.typingr   r   r   r   r   r   limits.utilr   r   rq   r?   r>   <module>r      sO    "     $   , 
  'UHw ;=U UHr?   