o
    KDi4K                     @  s   d dl mZ d dlZd dlZd dlZd dlmZmZ d dlm	Z	m
Z
mZ d dlmZmZmZ d dlmZ edZedZed	d
edddG dd dee	e
ZdS )    )annotationsN)versionaddedversionchanged)MovingWindowSupportSlidingWindowCounterSupportStorage)	ParamSpecTypeVarcast)get_dependencyPRz2.1)versionz3.14.0zEAdded option to select custom collection names for windows & counters)r   reasonc                      s   e Zd ZdZddgZ	 ddgZ					d@dA fddZedBddZedd Z	dCddZ
dDdd ZdEd"d#ZdFd%d&ZdGd(d)ZdHdId-d.ZdJd/d0ZdKd3d4Z	*dHdLd5d6Z	*dHdLd7d8ZdMd:d;ZdNd<d=ZdCd>d?Z  ZS )OMongoDBStoragezS
    Rate limit storage with MongoDB as backend.

    Depends on :pypi:`motor`
    async+mongodbzasync+mongodb+srvmotor.motor_asynciopymongolimitscounterswindowsFuristrdatabase_namecounter_collection_namewindow_collection_namewrap_exceptionsbooloptionsfloat | str | boolreturnNonec                   s   | ddd}t j|fd|i| | jd | _| jd | _td\| _}| jjj	|fi || _
tj| j
_|| _||d| _d	| _d
S )a  
        :param uri: uri of the form ``async+mongodb://[user:password]@host:port?...``,
         This uri is passed directly to :class:`~motor.motor_asyncio.AsyncIOMotorClient`
        :param database_name: The database to use for storing the rate limit
         collections.
        :param counter_collection_name: The collection name to use for individual counters
         used in fixed window strategies
        :param window_collection_name: The collection name to use for sliding & moving window
         storage
        :param wrap_exceptions: Whether to wrap storage exceptions in
         :exc:`limits.errors.StorageError` before raising it.
        :param options: all remaining keyword arguments are passed
         to the constructor of :class:`~motor.motor_asyncio.AsyncIOMotorClient`
        :raise ConfigurationError: when the :pypi:`motor` or :pypi:`pymongo` are
         not available
        r   mongodb   r   r   r   zpymongo.errors)r   r   FN)replacesuper__init__dependencies
dependencyproxy_dependencyr   
lib_errorsmoduleAsyncIOMotorClientstorageasyncioget_running_loopget_io_loop_MongoDBStorage__database_name#_MongoDBStorage__collection_mapping _MongoDBStorage__indices_created)selfr   r   r   r   r   r   _	__class__ S/var/www/Datamplify/venv/lib/python3.10/site-packages/limits/aio/storage/mongodb.pyr&   ,   s   

zMongoDBStorage.__init__-type[Exception] | tuple[type[Exception], ...]c                 C  s   | j jS N)r*   PyMongoErrorr4   r8   r8   r9   base_exceptions[   s   zMongoDBStorage.base_exceptionsc                 C  s   | j | jS r;   )r-   get_databaser1   r=   r8   r8   r9   databasea   s   zMongoDBStorage.databasec                   sP   | j s#t| j| jd  jddd| j| jd  jdddI d H  d| _ d S )Nr   expireAtr   )expireAfterSecondsr   T)r3   r.   gatherr@   r2   create_indexr=   r8   r8   r9   create_indicese   s   

zMongoDBStorage.create_indices
int | Nonec                   sx   t t| j| jd  i | j| jd  i I dH }t| j| jd   | j| jd   I dH  tt|S )z^
        Delete all rate limit keys in the rate limit collections (counters, windows)
        r   r   N)	sumr.   rC   r@   r2   count_documentsdropr
   int)r4   num_keysr8   r8   r9   resetq   s   

zMongoDBStorage.resetkeyc                   sD   t | j| jd  d|i| j| jd  d|iI dH  dS )z>
        :param key: the key to clear rate limits for
        r   _idr   N)r.   rC   r@   r2   find_one_and_delete)r4   rM   r8   r8   r9   clear   s   zMongoDBStorage.clearfloatc                   sH   | j | jd  d|iI dH }|r|d ntj jtjjd S )z;
        :param key: the key to get the expiry for
        r   rN   NrA   tzinfo)	r@   r2   find_onedatetimenowr$   timezoneutc	timestampr4   rM   counterr8   r8   r9   
get_expiry   s   
zMongoDBStorage.get_expiryrJ   c                   sJ   | j | jd  j|dtjtjjiddgdI dH }|r#|d p$dS )zB
        :param key: the key to get the counter value for
        r   $gte)rN   rA   count)
projectionNr   )r@   r2   rT   rU   rV   rW   rX   rZ   r8   r8   r9   get   s   zMongoDBStorage.getr#   expiryamountc              	     s   |   I dH  tjtjjtj|d }| j| jd  jd|iddddd	gi|d
d|gididddd	gi|ddidigddg| j	j
jjdI dH }t|d S )z
        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 amount: the number to increment by
        Nsecondsr   rN   $set$condz$lt	$expireAt$$NOW$addz$countifthenelse)r^   rA   Tr^   )upsertr_   return_document)rE   rU   rV   rW   rX   	timedeltar@   r2   find_one_and_updater)   r+   ReturnDocumentAFTERrJ   )r4   rM   ra   rb   
expirationresponser8   r8   r9   incr   s>   



zMongoDBStorage.incrc                   s&   z| j  I dH  W dS    Y dS )z{
        Check if storage is healthy by calling
        :meth:`motor.motor_asyncio.AsyncIOMotorClient.server_info`
        NTF)r-   server_infor=   r8   r8   r9   check   s   zMongoDBStorage.checklimittuple[float, int]c                   s   t   }| j| jd  dd|iidddddd	d
|| gidiiidddiddidigjddI dH  }rE|d d |d d fS |dfS )z
        returns the starting point and the number of entries in the moving
        window

        :param str key: rate limit key
        :param int expiry: expiry of entry
        :return: (start of window, number of acquired entries)
        r   z$matchrN   z$projectfilteredEntriesz$filterz$entriesentryr]   z$$entry)inputascondz$minz$filteredEntriesz$size)minr^   r#   )lengthNr   r   r^   )timer@   r2   	aggregateto_list)r4   rM   ry   ra   rY   resultr8   r8   r9   get_moving_window   s6   
z MongoDBStorage.get_moving_windowc                   s   |   I dH  ||krdS t }z?d|g| d|didtjtjjtj|d id}| j| jd	  j	d
|d||  dd|| iii|ddI dH  W dS  | j
jjjy_   Y dS w )z
        :param key: rate limit key to acquire an entry in
        :param limit: amount of entries allowed
        :param expiry: expiry of the entry
        :param amount: the number of entries to acquire
        NFentriesr   )z$eachz	$positionz$slicerA   rc   )z$pushre   r   rN   zentries.z$notr]   T)rn   )rE   r   rU   rV   rW   rX   rp   r@   r2   
update_oner)   r+   errorsDuplicateKeyError)r4   rM   ry   ra   rb   rY   updatesr8   r8   r9   acquire_entry  s<   	
	zMongoDBStorage.acquire_entryc                   s  |   I d H  |d }| j| jd  jd|idddddd	d
gi|gidddgidddgidiiiddddd	d
gi|giddddgididddd	d
gi|giddd	dgidd	|gidd
d| gidid	dididdddddddddd	dd
|gigigi|gigidgiiiidddddd|gi|gidd|giddiiiddddd|gi|giiiddgig| jjjjddI d H }tt	|d S )N  r   rN   re   previousCountrf   $lte	$subtractrg   rh   $ifNull$currentCountr   $previousCountrj   z$gtri      )currentCountrA   curWeightedCountz$floorz	$multiplyz$dividez$maxr   z$curWeightedCount	_acquiredz$unsetT)ro   rn   )
rE   r@   r2   rq   r)   r+   rr   rs   r
   r   )r4   rM   ry   ra   rb   	expiry_msr   r8   r8   r9   acquire_sliding_window_entry?  s   







#&


qyz+MongoDBStorage.acquire_sliding_window_entrytuple[int, float, int, float]c              
     s2  |d }| j | jd  jd|idddddd	gi|gid
ddgid
ddgididdddd	gi|gidd
ddgididdddd	gi|gidd|giddidig| jjjjg ddI d H  }r|drs|d jt	j
jd nt }td|t  }td|d r|| nd}|d ||d |fS dS )Nr   r   rN   re   rf   r   r   rg   rh   r   r   r   r   rj   ri   )r   r   rA   )r   r   rA   )ro   r_   rA   rR   r   r   )r           r   r   )r@   r2   rq   r)   r+   rr   rs   r`   r$   rU   rW   rX   rY   r   max)r4   rM   ra   r   r   
expires_atcurrent_ttlprev_ttlr8   r8   r9   get_sliding_window  sp   







*3z!MongoDBStorage.get_sliding_windowc                   s   |  |I d H S r;   )rP   )r4   rM   ra   r8   r8   r9   clear_sliding_window  s   z#MongoDBStorage.clear_sliding_windowc                 C  s   | j o
| j   d S  d S r;   )r-   closer=   r8   r8   r9   __del__  s   zMongoDBStorage.__del__)r   r   r   F)r   r   r   r   r   r   r   r   r   r   r   r   r    r!   )r    r:   )r    r!   )r    rF   )rM   r   r    r!   )rM   r   r    rQ   )rM   r   r    rJ   )r#   )rM   r   ra   rJ   rb   rJ   r    rJ   )r    r   )rM   r   ry   rJ   ra   rJ   r    rz   )
rM   r   ry   rJ   ra   rJ   rb   rJ   r    r   )rM   r   ra   rJ   r    r   )rM   r   ra   rJ   r    r!   )__name__
__module____qualname____doc__STORAGE_SCHEMEDEPENDENCIESr&   propertyr>   r@   rE   rL   rP   r\   r`   rv   rx   r   r   r   r   r   r   __classcell__r8   r8   r6   r9   r      s<    /






-
+1 

Er   )
__future__r   r.   rU   r   deprecated.sphinxr   r   limits.aio.storage.baser   r   r   limits.typingr   r	   r
   limits.utilr   r   r   r   r8   r8   r8   r9   <module>   s     