o
    ;h4K                     @  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   Zmongodb   r   r   r   zpymongo.errors)r   r   FN)replacesuper__init__dependencies
dependencyproxy_dependencyr   
lib_errorsmoduleZAsyncIOMotorClientstorageasyncioZget_running_loopZget_io_loop_MongoDBStorage__database_name#_MongoDBStorage__collection_mapping _MongoDBStorage__indices_created)selfr   r   r   r   r   r   _	__class__ M/var/www/html/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)   ZPyMongoErrorr0   r4   r4   r5   base_exceptions[   s   zMongoDBStorage.base_exceptionsc                 C  s   | j | jS r7   )r+   Zget_databaser-   r8   r4   r4   r5   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   )ZexpireAfterSecondsr   T)r/   r,   gatherr:   r.   Zcreate_indexr8   r4   r4   r5   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,   r<   r:   r.   Zcount_documentsZdropr
   int)r0   Znum_keysr4   r4   r5   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,   r<   r:   r.   Zfind_one_and_delete)r0   rB   r4   r4   r5   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   rC   Nr;   tzinfo)	r:   r.   find_onedatetimenowr#   timezoneutc	timestampr0   rB   Zcounterr4   r4   r5   
get_expiry   s   
zMongoDBStorage.get_expiryr@   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)rC   r;   count)
projectionNr   )r:   r.   rH   rI   rJ   rK   rL   rN   r4   r4   r5   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   rC   $set$condz$lt	$expireAt$$NOW$addz$countifZthenelse)rQ   r;   TrQ   )upsertrR   return_document)r=   rI   rJ   rK   rL   	timedeltar:   r.   find_one_and_updater(   r*   ReturnDocumentAFTERr@   )r0   rB   rT   rU   Z
expirationresponser4   r4   r5   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+   Zserver_infor8   r4   r4   r5   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$matchrC   z$projectZfilteredEntriesz$filterz$entriesentryrP   z$$entry)inputasZcondz$minz$filteredEntriesz$size)minrQ   r"   )lengthNr   rn   rQ   )timer:   r.   Z	aggregateZto_list)r0   rB   ri   rT   rM   resultr4   r4   r5   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$slicer;   rV   )z$pushrX   r   rC   zentries.z$notrP   T)r`   )r=   rp   rI   rJ   rK   rL   rb   r:   r.   Z
update_oner(   r*   errorsZDuplicateKeyError)r0   rB   ri   rT   rU   rM   Zupdatesr4   r4   r5   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   rC   rX   previousCountrY   $lte	$subtractrZ   r[   $ifNull$currentCountr   $previousCountr]   z$gtr\      )currentCountr;   ZcurWeightedCountz$floorz	$multiplyz$dividez$maxr~   z$curWeightedCountZ	_acquiredz$unsetT)ra   r`   )
r=   r:   r.   rc   r(   r*   rd   re   r
   r   )r0   rB   ri   rT   rU   	expiry_msrq   r4   r4   r5   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 )Nrv   r   rC   rX   rY   rx   ry   rZ   r[   rz   r{   r   r|   r]   r\   )rw   r~   r;   )r~   rw   r;   )ra   rR   r;   rF   rw   r~   )r           r   r   )r:   r.   rc   r(   r*   rd   re   rS   r#   rI   rK   rL   rM   rp   max)r0   rB   rT   r   rq   Z
expires_atZcurrent_ttlZprev_ttlr4   r4   r5   get_sliding_window  sp   







*3z!MongoDBStorage.get_sliding_windowc                   s   |  |I d H S r7   )rD   )r0   rB   rT   r4   r4   r5   clear_sliding_window  s   z#MongoDBStorage.clear_sliding_windowc                 C  s   | j o
| j   d S  d S r7   )r+   closer8   r4   r4   r5   __del__  s   zMongoDBStorage.__del__)r   r   r   F)r   r   r   r   r   r   r   r   r   r   r   r   r    r!   )r    r6   )r    r!   )r    r>   )rB   r   r    r!   )rB   r   r    rE   )rB   r   r    r@   )r"   )rB   r   rT   r@   rU   r@   r    r@   )r    r   )rB   r   ri   r@   rT   r@   r    rj   )
rB   r   ri   r@   rT   r@   rU   r@   r    r   )rB   r   rT   r@   r    r   )rB   r   rT   r@   r    r!   )__name__
__module____qualname____doc__ZSTORAGE_SCHEMEZDEPENDENCIESr%   propertyr9   r:   r=   rA   rD   rO   rS   rg   rh   rr   ru   r   r   r   r   __classcell__r4   r4   r2   r5   r      s<    /






-
+1 

Er   )
__future__r   r,   rI   rp   Zdeprecated.sphinxr   r   Zlimits.aio.storage.baser   r   r   Zlimits.typingr   r	   r
   Zlimits.utilr   r   r   r   r4   r4   r4   r5   <module>   s     