
    ^gy(                        d dl m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mZ d dlmZ d dlmZmZ  ed	
       G d deee             Zy)    )annotationsN)Iterable)ceilfloor)versionadded)SlidingWindowCounterSupportStorage)TimestampedSlidingWindow)EmcacheClientPItemPz2.1)versionc                      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
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Z	 d"	 	 	 	 	 	 	 	 	 d#dZ	 	 	 	 	 	 d$dZ	 	 	 	 	 	 	 	 	 	 d%dZ xZS )&MemcachedStoragezW
    Rate limit storage with memcached as backend.

    Depends on :pypi:`emcache`
    zasync+memcachedemcachec                   t         j                  j                  |      }g | _        d |j                  j                         j                  d      D        D ]+  \  }}| j                  j                  |t        |      f       - || _	        d| _
        t        | 0  |fd|i| | j                  d   j                  | _        y)a  
        :param uri: memcached location of the form
         ``async+memcached://host:port,host:port``
        :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:`emcache.Client`
        :raise ConfigurationError: when :pypi:`emcache` is not available
        c              3  `   K   | ]&  }|j                         s|j                  d        ( yw):N)stripsplit).0locs     c/var/www/html/suriana-translation/venv/lib/python3.12/site-packages/limits/aio/storage/memcached.py	<genexpr>z,MemcachedStorage.__init__.<locals>.<genexpr>.   s%      
"#))+CIIcN
s   ..,Nwrap_exceptionsr   )urllibparseurlparsehostsnetlocr   r   appendint_options_storagesuper__init__dependenciesmodule
dependency)selfurir   optionsparsedhostport	__class__s          r   r&   zMemcachedStorage.__init__   s     &&s+

&,mm&9&9&;&A&A#&F
 	1JD$ JJtSY/0	1
  IoII++I6==    c                Z    | j                   j                  | j                   j                  fS N)r)   ClusterNoAvailableNodesCommandErrorr*   s    r   base_exceptionsz MemcachedStorage.base_exceptions8   s(    
 OO33OO((
 	
r1   c           
     <  K   | j                   sk | j                  j                  | j                  D cg c]!  \  }}| j                  j	                  ||      # c}}fi | j
                   d {   | _         | j                   sJ | j                   S c c}}w 7 )wr3   )r$   r)   create_clientr   MemcachedHostAddressr#   )r*   hps      r   get_storagezMemcachedStorage.get_storageA   s     }}"?$//"?"?HL

S155a;S#--# DM }}}}}	 Ts   2B&B
B0B1*Bc                   K   | j                          d{   j                  |j                  d             d{   }|xr t        |j                        xs dS 7 G7 #w)zB
        :param key: the key to get the counter value for
        Nutf-8r   )r=   getencoder"   value)r*   keyitems      r   r@   zMemcachedStorage.getJ   sQ      !,,..33CJJw4GHH'DJJ,1, /Hs   A"A%A"A "A" A"c                   K   | j                          d{   j                  |D cg c]  }|j                  d       c}       d{   S 7 8c c}w 7 w)zo
        Return multiple counters at once

        :param keys: the keys to get the counter values for
        Nr?   )r=   get_manyrA   )r*   keysks      r   rF   zMemcachedStorage.get_manyR   sN      !,,..88(,-1QXXg-
 
 	
.-
s,   AAAA 
A
AAAc                   K   | j                          d{   j                  |j                  d             d{    y7 +7 w)z>
        :param key: the key to clear rate limits for
        Nr?   )r=   deleterA   r*   rC   s     r   clearzMemcachedStorage.clear\   s8      %%''//

70CDDD'Ds   AA%AAAAc                   K   | j                          d{   }|j                  d      }	 |j                  |||       d{   xs d}|S 7 87 # | j                  j                  $ r d}Y |S w xY ww)a-  
        decrements the counter for a given rate limit key

        retursn 0 if the key doesn't exist or if noreply is set to True

        :param key: the key to decrement
        :param amount: the number to decrement by
        :param noreply: set to True to ignore the memcached response
        Nr?   noreplyr   )r=   rA   	decrementr)   NotFoundCommandError)r*   rC   amountrO   storage	limit_keyrB   s          r   decrzMemcachedStorage.decrb   s      ((**JJw'		!++Ivw+OOTSTE  + P33 	E	sD   A5AA5A AA A5A A2.A51A22A5c           
     "  K   | j                          d{   }|j                  d      }| j                  |      j                         }d}		 |j                  ||       d{   xs |}	|ry|j	                  |t        |             d{    |rS|j                  |t        |t        j                         z         j                  d      t        |      d       d{    |	S 7 7 7 _7 # | j                  j                  $ r | j                          d{  7  }	 |j                  || j                         t        |             d{  7   |rT|j                  |t        |t        j                         z         j                  d      t        |      d       d{  7   |}	n# | j                  j                  $ r | j                          d{  7  }|j                  ||       d{  7  xs |}	|r{|j	                  |t        |             d{  7   |rT|j                  |t        |t        j                         z         j                  d      t        |      d       d{  7   Y nw xY w|	cY S w xY ww)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
        :param elastic_expiry: whether to keep extending the rate limit
         window every hit.
        :param amount: the number to increment by
        :param set_expiration_key: if set to False, the expiration time won't be stored but the key will still expire
        Nr?   )exptimeF)rW   rO   )r=   rA   _expiration_key	incrementtouchr   setstrtimer)   rQ   addNotStoredStorageCommandError)
r*   rC   expiryelastic_expiryrR   set_expiration_keyrS   rT   
expire_keyrB   s
             r   incrzMemcachedStorage.incrt   sI    $ ((**JJw'	))#.557
&	!++Iv>>H&EmmItF|mDDD%!++"FTYY[0188A $V %	 &    L +
 ?D 33 	 ,,...Gkk)x-?-?-A4PV<kXXX%!++"FTYY[0188A $V %	 &    ????  $ 0 0 222%//	6BBBLf!!--	4<-HHH)%kk& 45<<WE$(L$)	 *    L5	s   JC)6JC1 #C+$)C1 C-AC1 "C/#C1 (J+C1 -C1 /C1 1-JD!J%/F3EAF3*F-+F32J3,JG" J:G=;*J%H(&AJ;I><JJJJ	JJJc                  K   | j                          d{   }|j                  | j                  |      j                  d             d{   }|xr t	        |j
                        xs t        j                         S 7 j7 5w)z;
        :param key: the key to get the expiry for
        Nr?   )r=   r@   rX   rA   floatrB   r]   )r*   rC   rS   rD   s       r   
get_expiryzMemcachedStorage.get_expiry   sh      ((**[[!5!5c!:!A!A'!JKK)djj)8TYY[8 +Ks!   BB6BB4BB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 rK   s     r   rX   z MemcachedStorage._expiration_key   s     Zr1   c                   K   	 | j                          d{   }|j                  d       d{    y7 7 #  Y yxY ww)zq
        Check if storage is healthy by calling the ``get`` command
        on the key ``limiter-check``
        Ns   limiter-checkTF)r=   r@   )r*   rS   s     r   checkzMemcachedStorage.check   sD     
	 ,,..G++./// //	s/   A: 6: 8: A: : >Ac                   K   t         wr3   )NotImplementedErrorr6   s    r   resetzMemcachedStorage.reset   s     !!s   	c                  K   ||kD  ryt        j                          }| j                  |||      \  }}| j                  ||||       d {   \  }}	}
}t        j                          }||	z  |z  |
z   }t        |      |z   |kD  ry| j	                  |d|z  |d       d {   }
t        j                          }t        d|	||z
  z
        }||z  |z  |
z   }t        |      |kD  r| j                  ||d       d {    yy7 7 c7 
w)NF   )rR   rb   r   TrN   )r]   sliding_window_keys_get_sliding_window_infor   rd   maxrU   )r*   rC   limitr`   rR   nowprevious_keycurrent_keyprevious_countprevious_ttlcurrent_count_t0weighted_countt1actualised_previous_ttls                   r   acquire_sliding_window_entryz-MemcachedStorage.acquire_sliding_window_entry   s9     E>iik$($<$<S&#$N!k //k6SVWW	
YY[',6?-O 6)E1
 #'))QZ5 #, # M B&)!\R"W-E&F#!886AMQ  ^$u, iiVTiBBB/ X Cs8   AD
DAD D!AD;D<DDDc                   K   t        j                          }| j                  |||      \  }}| j                  ||||       d {   S 7 wr3   )r]   rq   rr   )r*   rC   r`   ru   rv   rw   s         r   get_sliding_windowz#MemcachedStorage.get_sliding_window   sR      iik$($<$<S&#$N!k22+vs
 
 	
 
s   AAA	Ac                  K   | j                  ||g       d {   }|j                  |j                  d            }|j                  |j                  d            }|xr t        |j                        xs d}|xr t        |j                        xs d}	|	dk(  rt        d      }
nd||z
  |z  dz  z
  |z  }
d||z  dz  z
  |z  |z   }|	|
||fS 7 w)Nr?   r      )rF   r@   rA   r"   rB   rf   )r*   rv   rw   r`   ru   resultraw_previous_countraw_current_countrz   rx   ry   current_ttls               r   rr   z)MemcachedStorage._get_sliding_window_info  s      }}lK%@AA#ZZ(;(;G(DE"JJ{'9'9''BC)Jc2C2I2I.JOa+M4F4L4L0MRQRQ 8L3<6"9Q!>?6ILS6\Q./69FB|]KGG Bs   CCB8C)F)r+   r\   r   boolr,   zfloat | str | boolreturnNone)r   z-type[Exception] | tuple[type[Exception], ...])r   r   )rC   r\   r   r"   )rG   zIterable[str]r   zdict[bytes, ItemP])rC   r\   r   r   )r   F)rC   r\   rR   r"   rO   r   r   r"   )Fr   T)rC   r\   r`   rf   ra   r   rR   r"   rb   r   r   r"   )rC   r\   r   rf   )rC   r\   r   r\   )r   r   )r   z
int | None)r   )
rC   r\   rt   r"   r`   r"   rR   r"   r   r   )rC   r\   r`   r"   r   tuple[int, float, int, float])
rv   r\   rw   r\   r`   r"   ru   rf   r   r   )__name__
__module____qualname____doc__STORAGE_SCHEMEDEPENDENCIESr&   propertyr7   r=   r@   rF   rL   rU   rd   rg   rX   rk   rn   r   r   rr   __classcell__)r0   s   @r   r   r      sl    ((NI;L
 !&>> > &	>
 
>8 
	6
 
-
E,  %#'<< < 	<
 < !< 
<|9 " '' ' 	'
 ' 
'R

 #
	&
HH.1H;>HEJH	&Hr1   r   )
__future__r   r]   urllib.parser   collections.abcr   mathr   r   deprecated.sphinxr   limits.aio.storage.baser   r	   limits.storage.baser
   limits.typingr   r   r   ri   r1   r   <module>r      sL    "   $  * H 8 / eFHw ;=U FH FHr1   