o
    ;h(                     @  s   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 deeeZdS )    )annotationsN)Iterable)ceilfloor)
ModuleType)ConfigurationError)SlidingWindowCounterSupportStorageTimestampedSlidingWindow)AnyCallableMemcachedClientPPRcast)get_dependencyc                      s   e Zd ZdZdgZ	 dgZ	dMdN fddZedOddZdPddZ	dQd d!Z
edRd"d#ZdSd&d'ZdTd+d,ZdUd-d.Z	/	0dVdWd5d6ZdXd7d8ZdYd9d:ZdZd;d<Zd[d>d?Z	/d\d]dAdBZd^dDdEZd_dFdGZd`dKdLZ  ZS )aMemcachedStoragez[
    Rate limit storage with memcached as backend.

    Depends on :pypi:`pymemcache`.
    Z	memcached
pymemcacheFuristrwrap_exceptionsbooloptions$str | Callable[[], MemcachedClientP]returnNonec                   s  t j|}g | _|j dD ]}|sq|d\}}| j|t|f q|j	r6|js6|j
s6|j	g| _| jd j| _t|dd| _t|dd| _tttttttf  gtf |d| j| _|| _t| jsvtd	| j t | _d
| j_ t! j"||d d
S )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)r   )#urllibparseurlparsehostsnetlocstripsplitappendintpathportdependenciesmodule
dependencyr   popr   r   r   r   r   listtupler   
get_clientr    r   r   r   	threadinglocallocal_storagestoragesuper__init__)selfr   r   r   parsedlochostr+   	__class__ K/var/www/html/venv/lib/python3.10/site-packages/limits/storage/memcached.pyr8   '   s4   




zMemcachedStorage.__init__-type[Exception] | tuple[type[Exception], ...]c                 C  s   | j jS N)r.   ZMemcacheErrorr9   r?   r?   r@   base_exceptionsZ   s   z MemcachedStorage.base_exceptionsr-   r   r$   list[tuple[str, int]]kwargsr   c                 K  s6   t tt|dk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   lenZ
HashClientZPooledClient)r9   r-   r$   rF   r?   r?   r@   r2   `   s   
zMemcachedStorage.get_clientfuncCallable[P, R]argsP.argsP.kwargsr   c                 O  s:   d|v rt |}d|jv s|js|d ||i |S )Nnoreply)inspectgetfullargspecrK   varkwr/   )r9   rI   rK   rF   Zargspecr?   r?   r@   call_memcached_funcs   s
   

z$MemcachedStorage.call_memcached_funcc                 C  st   t | jdr
| jjs3tt| jdk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
        r6   rG   r   zUnable to import )hasattrr5   r6   r   rH   r$   r   r   r   r    r   r   r   )r9   r.   r?   r?   r@   r6   ~   s   
zMemcachedStorage.storagekeyr)   c                 C  s   t | j|dS )zB
        :param key: the key to get the counter value for
        0)r)   r6   getr9   rT   r?   r?   r@   rV      s   zMemcachedStorage.getkeysIterable[str]dict[str, Any]c                 C  s   | j |S )z
        Return multiple counters at once

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

        :meta private:
        )r6   get_many)r9   rX   r?   r?   r@   r[      s   zMemcachedStorage.get_manyc                 C  s   | j | dS )z>
        :param key: the key to clear rate limits for
        N)r6   deleterW   r?   r?   r@   clear   s   zMemcachedStorage.clearrG   Texpiryfloatamountset_expiration_keyc                 C  s   | j | jj||dd }dur|S | j | jj||t|dds(| j||p'|S |r?| j | jj| ||t  t|d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rN   N)ZexpirerN   )rR   r6   incraddr   set_expiration_keytime)r9   rT   r^   r`   ra   valuer?   r?   r@   rc      s&   
zMemcachedStorage.incrc                 C  s   t | j| |pt S )z;
        :param key: the key to get the expiry for
        )r_   r6   rV   rf   rg   rW   r?   r?   r@   
get_expiry   s   zMemcachedStorage.get_expiryc                 C  s   |d 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/expiresr?   rW   r?   r?   r@   rf      s   z MemcachedStorage._expiration_keyc                 C  s$   z|  | jjd W dS    Y dS )zq
        Check if storage is healthy by calling the ``get`` command
        on the key ``limiter-check``
        zlimiter-checkTF)rR   r6   rV   rC   r?   r?   r@   check   s
   zMemcachedStorage.check
int | Nonec                 C  s   t rB   )NotImplementedErrorrC   r?   r?   r@   reset   s   zMemcachedStorage.resetlimitc                 C  s   ||krdS t   }| |||\}}| j||||d\}}	}
}||	 | |
 }t|| |kr2dS | j|d| |dd}
td|	t   |  }|| | |
 }t||krc| j| jj||dd dS dS )NF)now   )r`   ra   r   Trb   )	rg   sliding_window_keys_get_sliding_window_infor   rc   minrR   r6   Zdecr)r9   rT   rn   r^   r`   ro   previous_keycurrent_keyprevious_countprevious_ttlcurrent_count_Zweighted_countZactualised_previous_ttlr?   r?   r@   acquire_sliding_window_entry   s2   z-MemcachedStorage.acquire_sliding_window_entrytuple[int, float, int, float]c                 C  s*   t   }| |||\}}| ||||S rB   )rg   rq   rr   r9   rT   r^   ro   rt   ru   r?   r?   r@   get_sliding_window  s   z#MemcachedStorage.get_sliding_windowc                 C  s2   t   }| |||\}}| | | | d S rB   )rg   rq   r]   r|   r?   r?   r@   clear_sliding_window  s   
z%MemcachedStorage.clear_sliding_windowrt   ru   ro   c           
      C  s~   |  ||g}t||dt||d}}|dkr!td}nd|| | d  | }d|| d  | | }	||||	fS )Nr   rG   )r[   r)   rV   r_   )
r9   rt   ru   r^   ro   resultrv   rx   rw   Zcurrent_ttlr?   r?   r@   rr   #  s   
z)MemcachedStorage._get_sliding_window_info)F)r   r   r   r   r   r   r   r   )r   rA   )r-   r   r$   rE   rF   r   r   r   )rI   rJ   rK   rL   rF   rM   r   r   )r   r   )rT   r   r   r)   )rX   rY   r   rZ   )rT   r   r   r   )rG   T)
rT   r   r^   r_   r`   r)   ra   r   r   r)   )rT   r   r   r_   )rT   r   r   r   )r   r   )r   rk   )rG   )
rT   r   rn   r)   r^   r)   r`   r)   r   r   )rT   r   r^   r)   r   r{   )rT   r   r^   r)   r   r   )
rt   r   ru   r   r^   r)   ro   r_   r   r{   )__name__
__module____qualname____doc__ZSTORAGE_SCHEMEZDEPENDENCIESr8   propertyrD   r2   rR   r6   rV   r[   r]   rc   ri   rf   rj   rm   rz   r}   r~   rr   __classcell__r?   r?   r=   r@   r      s8    3







'

	

)
r   )
__future__r   rO   r3   rg   urllib.parser!   collections.abcr   mathr   r   typesr   Zlimits.errorsr   Zlimits.storage.baser   r	   r
   Zlimits.typingr   r   r   r   r   r   Zlimits.utilr   r   r?   r?   r?   r@   <module>   s     