o
    riT(                     @  s   d dl m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 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)parse_storage_uri)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`.
    	memcached
pymemcacheFuristrwrap_exceptionsbooloptions$str | Callable[[], MemcachedClientP]returnNonec                   s   t |}|  |jr|jg| _n|j| _| jd j| _t|dd| _	t|dd| _
tttttttf  tt B gtf |d| j| _|| _t| j	sWt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   )r   pathhosts	locationsdependenciesmodule
dependencyr   popr   r   r   r   r   listtupleintr   
get_clientr    r   r   r   	threadinglocallocal_storagestoragesuper__init__)selfr   r   r   storage_uri_options	__class__ W/var/www/html/pca-backend/venv/lib/python3.10/site-packages/limits/storage/memcached.pyr1   '   s,   
"


zMemcachedStorage.__init__-type[Exception] | tuple[type[Exception], ...]c                 C  s   | j jS N)r&   MemcacheErrorr2   r6   r6   r7   base_exceptionsS   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   len
HashClientPooledClient)r2   r%   r"   r>   r6   r6   r7   r+   Y   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getfullargspecrE   varkwr'   )r2   rC   rE   r>   argspecr6   r6   r7   call_memcached_funcl   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
        r/   r?   r   zUnable to import )hasattrr.   r/   r   r@   r"   r   r   r   r    r   r   r   )r2   r&   r6   r6   r7   r/   w   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*   r/   getr2   rO   r6   r6   r7   rQ      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:
        )r/   get_many)r2   rS   r6   r6   r7   rV      s   zMemcachedStorage.get_manyc                 C  s   | j | dS )z>
        :param key: the key to clear rate limits for
        N)r/   deleterR   r6   r6   r7   clear   s   zMemcachedStorage.clearr?   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rH   N)expirerH   )rM   r/   incraddr   set_expiration_keytime)r2   rO   rY   r[   r\   valuer6   r6   r7   r_      s&   
zMemcachedStorage.incrc                 C  s   t | j| |pt S )z;
        :param key: the key to get the expiry for
        )rZ   r/   rQ   rb   rc   rR   r6   r6   r7   
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/expiresr6   rR   r6   r6   r7   rb      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)rM   r/   rQ   r;   r6   r6   r7   check   s
   zMemcachedStorage.check
int | Nonec                 C  s   t r9   )NotImplementedErrorr;   r6   r6   r7   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[   r\   r   Tr]   )	rc   sliding_window_keys_get_sliding_window_infor   r_   minrM   r/   decr)r2   rO   rj   rY   r[   rk   previous_keycurrent_keyprevious_countprevious_ttlcurrent_count_weighted_countactualised_previous_ttlr6   r6   r7   acquire_sliding_window_entry   s2   z-MemcachedStorage.acquire_sliding_window_entrytuple[int, float, int, float]c                 C  s*   t   }| |||\}}| ||||S r9   )rc   rm   rn   r2   rO   rY   rk   rq   rr   r6   r6   r7   get_sliding_window  s   z#MemcachedStorage.get_sliding_windowc                 C  s2   t   }| |||\}}| | | | d S r9   )rc   rm   rX   r{   r6   r6   r7   clear_sliding_window  s   
z%MemcachedStorage.clear_sliding_windowrq   rr   rk   c           
      C  s~   |  ||g}t||dt||d}}|dkr!td}nd|| | d  | }d|| d  | | }	||||	fS )Nr   r?   )rV   r*   rQ   rZ   )
r2   rq   rr   rY   rk   resultrs   ru   rt   current_ttlr6   r6   r7   rn     s   
z)MemcachedStorage._get_sliding_window_info)F)r   r   r   r   r   r   r   r   )r   r8   )r%   r   r"   r=   r>   r   r   r   )rC   rD   rE   rF   r>   rG   r   r   )r   r   )rO   r   r   r*   )rS   rT   r   rU   )rO   r   r   r   )r?   T)
rO   r   rY   rZ   r[   r*   r\   r   r   r*   )rO   r   r   rZ   )rO   r   r   r   )r   r   )r   rg   )r?   )
rO   r   rj   r*   rY   r*   r[   r*   r   r   )rO   r   rY   r*   r   rz   )rO   r   rY   r*   r   r   )
rq   r   rr   r   rY   r*   rk   rZ   r   rz   )__name__
__module____qualname____doc__STORAGE_SCHEMEDEPENDENCIESr1   propertyr<   r+   rM   r/   rQ   rV   rX   r_   re   rb   rf   ri   ry   r|   r}   rn   __classcell__r6   r6   r4   r7   r      s8    ,







'

	

)
r   )
__future__r   rI   r,   rc   collections.abcr   mathr   r   typesr   limits._storage_schemer   limits.errorsr   limits.storage.baser	   r
   r   limits.typingr   r   r   r   r   r   limits.utilr   r   r6   r6   r6   r7   <module>   s     