o
    Ti                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlmZ zd dlZW n ey+   dZY nw dZ	dZ
dZdZejdkZG dd	 d	eZdS )
    N)dedentz)Frazer McLean <frazer@frazermclean.co.uk>z1.2.0.post0Apachez"Simple python rate limiting object)      c                   @   sd   e Zd ZdZdddZdd Zdd	 Zd
d Zdd Ze	r*e
dZee eeZedd ZdS )RateLimiterzjProvides rate limiting for an operation with a configurable number of
    requests for a time period.
          ?Nc                 C   sZ   |dkrt d|dkrt dt | _|| _|| _|| _t | _	d| _
t | _dS )zInitialize a RateLimiter object which enforces as much as max_calls
        operations on period (eventually floating) number of seconds.
        r   z"Rate limiting period should be > 0z+Rate limiting number of calls should be > 0N)
ValueErrorcollectionsdequecallsperiod	max_callscallback	threadingLock_lock_alock
_init_lock)selfr   r   r    r   ?/home/ubuntu/.local/lib/python3.10/site-packages/ratelimiter.py__init__)   s   

zRateLimiter.__init__c                 C   sP   | j  | jd u rt | _W d    d S W d    d S 1 s!w   Y  d S N)r   r   asyncior   r   r   r   r   _init_async_lock?   s   
"zRateLimiter._init_async_lockc                    s   t   fdd}|S )zpThe __call__ function allows the RateLimiter object to be used as a
        regular function decorator.
        c                     s6     | i |W  d    S 1 sw   Y  d S r   r   )argskwargsfr   r   r   wrappedH   s   $z%RateLimiter.__call__.<locals>.wrapped)	functoolswraps)r   r   r    r   r   r   __call__D   s   zRateLimiter.__call__c                 C   s   | j > t| j| jkr8t | j | j }| jr)tj	| j|fd}d|_
|  |t  }|dkr8t| | W  d    S 1 sDw   Y  d S )N)targetr   Tr   )r   lenr   r   timer   	_timespanr   r   Threaddaemonstartsleep)r   untilt	sleeptimer   r   r   	__enter__N   s   
$zRateLimiter.__enter__c                 C   sn   | j * | jt  | j| jkr%| j  | j| jksW d    d S W d    d S 1 s0w   Y  d S r   )r   r   appendr&   r'   r   popleft)r   exc_typeexc_valexc_tbr   r   r   __exit__^   s   
"zRateLimiter.__exit__aw  
            async def __aenter__(self):
                if self._alock is None:
                    self._init_async_lock()
                    
                with await self._alock:
                    # We want to ensure that no more than max_calls were run in the allowed
                    # period. For this, we store the last timestamps of each call and run
                    # the rate verification upon each __enter__ call.
                    if len(self.calls) >= self.max_calls:
                        until = time.time() + self.period - self._timespan
                        if self.callback:
                            asyncio.ensure_future(self.callback(until))
                        sleeptime = until - time.time()
                        if sleeptime > 0:
                            await asyncio.sleep(sleeptime)
                    return self

            c                 C   s   | j d | j d  S )Nr   )r   r   r   r   r   r'      s   zRateLimiter._timespan)r   N)__name__
__module____qualname____doc__r   r   r#   r/   r5   PY35r   aenter_codeexecr   	coroutine	__aexit__propertyr'   r   r   r   r   r   $   s    



r   )r	   r!   r   r&   systextwrapr   r   ImportError
__author____version____license____description__version_infor;   objectr   r   r   r   r   <module>   s"   
