
    7g&                     B   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 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mZ dZej*                  d	k\  r1 eej,                  eeej0                  j3                  e      f
      Zn eej,                  eed       Z G d de      Zy)    N)AbstractAsyncContextManager)partial)heappopheappush)count)TracebackType)ListOptionalTupleTypezThis AsyncLimiter instance is being re-used across loops. Please create a new limiter per event loop as re-use can lead to undefined behaviour.)      )messagecategoryskip_file_prefixes)r   r   
stacklevelc                       e Zd ZU dZdZeed<   eed<   ddededdfdZede	j                  fd       Zdd	Zdd
edefdZdd
eddfdZdeddfdZdefdZddZdeee      dee   dee   ddfdZy)AsyncLimitera  A leaky bucket rate limiter.

    This is an :ref:`asynchronous context manager <async-context-managers>`;
    when used with :keyword:`async with`, entering the context acquires
    capacity::

        limiter = AsyncLimiter(10)
        for foo in bar:
            async with limiter:
                # process foo elements at 10 items per minute

    :param max_rate: Allow up to `max_rate` / `time_period` acquisitions before
       blocking.
    :param time_period: duration, in seconds, of the time period in which to
       limit the rate. Note that up to `max_rate` acquisitions are allowed
       within this time period in a burst.

    )	max_ratetime_period_rate_per_sec_level_last_check_event_loop_waiters_next_count_waker_handler   r   returnNc                     || _         || _        ||z  | _        d| _        d| _        d | _        g | _        t        t        t                     | _
        y )Ng        )r   r   r   r   r   r   r   r   nextr   r   )selfr   r   s      W/var/www/api-billing-001-11/venv/lib/python3.12/site-packages/aiolimiter/leakybucket.py__init__zAsyncLimiter.__init__I   sO     &%3 :>IK"41    c                 l   |  	 | j                   }|j                         rbt        j                         x}| _         | j                  D cg c]  \  }}}|j                         |k(  r|||f  c}}}| _        t                |S c c}}}w # t        $ r t        j                         x}| _         Y |S w xY wN)r   	is_closedasyncioget_running_loopr   get_loop_warn_reuseAttributeError)r!   loopamtcntfuts        r"   _loopzAsyncLimiter._loopW   s    	A##D~~ +2*B*B*DDt' *.!)6S#||~- #sO)6!
  !  	A&-&>&>&@@D4#	As$   AB #B.B B $B32B3c                     | j                   j                         }| j                  r<|| j                  z
  }|| j                  z  }t        | j                  |z
  d      | _        || _        y)z"Drip out capacity from the bucket.r   N)r1   timer   r   r   max)r!   nowelapsed	decrements       r"   _leakzAsyncLimiter._leakl   sZ    jjoo;; D,,,G$"4"44IdkkI5q9DKr$   amountc                 Z    | j                          | j                  |z   | j                  k  S )zCheck if there is enough capacity remaining in the limiter

        :param amount: How much capacity you need to be available.

        )r8   r   r   )r!   r9   s     r"   has_capacityzAsyncLimiter.has_capacityw   s%     	

{{V#t}}44r$   c                   K   || j                   kD  rt        d      | j                  }| j                  |      s|j	                         }|j                  t        |j                  | j                               t        | j                  || j                         |f       | j                          | d{    | j                  |      s| xj                  |z  c_        | j                          y7 <w)aB  Acquire capacity in the limiter.

        If the limit has been reached, blocks until enough capacity has been
        freed before returning.

        :param amount: How much capacity you need to be available.
        :exception: Raises :exc:`ValueError` if `amount` is greater than
           :attr:`max_rate`.

        z,Can't acquire more than the maximum capacityN)r   
ValueErrorr1   r;   create_futureadd_done_callbackr   	call_soon
_wake_nextr   r   r   r   )r!   r9   r-   r0   s       r"   acquirezAsyncLimiter.acquire   s      DMM!KLLzz##F+ $$&C!!'$..$//"JKT]]VT-=-=-?$EFOOII ##F+ 	v s   B3C45C26C4'C4_argsc                 (   | j                   | j                  dc}}| _        ||j                          |r:|d   d   j                         r$t	        |       |r|d   d   j                         r$|sy|d   \  }}}| j                          || j                  z
  | j                  z   }|dk  rt	        |       |j                  d       y| j                  d| j                  z  |z  z   }| j                  j                  || j                        | _        y)z+Wake the next waiting future or set a timerNr      )r   r   canceldoner   r8   r   r   
set_resultr   r   r1   call_atrA   )	r!   rC   heaphandler9   _r0   neededwake_next_ats	            r"   rA   zAsyncLimiter._wake_next   s     ,0==$:L:Ld(fd(MMOtAwr{'')DM tAwr{'') a3

$--'$++5Q;DMNN4 ''1t/A/A+AF+JK!ZZ//dooNr$   c                 x   d| j                   d| j                  }d| j                  ddt        | j                         }| j
                  x}rU|j                         sEt        |j                         | j                  j                         z
  dz        }|dkD  r	|d| d	z  }d
| dt        |       dd| dS )Nz	max_rate=z, time_period=zlevel: fz, waiters: i@B r   z, waking in u    µsz<AsyncLimiter(z) at z#xz [z]>)r   r   r   lenr   r   	cancelledintwhenr1   r3   id)r!   argsstaterL   microsecondss        r"   __repr__zAsyncLimiter.__repr__   s    4==+>$:J:J9MN$++aC4F3GH(((F(&2B2B2D

0A AUJKLa<~5EFFvU2d8B-r%CCr$   c                 @   K   | j                          d {    y 7 wr&   )rB   )r!   s    r"   
__aenter__zAsyncLimiter.__aenter__   s     lln 	s   exc_typeexctbc                    K   y wr&    )r!   r]   r^   r_   s       r"   	__aexit__zAsyncLimiter.__aexit__   s      s   )<   )r   N)rF   )__name__
__module____qualname____doc__	__slots__float__annotations__r#   propertyr(   AbstractEventLoopr1   r8   boolr;   rB   objectrA   strrZ   r\   r
   r   BaseExceptionr   rb   ra   r$   r"   r   r   &   s    &
I O2 2U 2D 2 w00  (	55 5 5E $ >O OD O2D# D4./ m$ ]#	
 
r$   r   )r(   ossyswarnings
contextlibr   	functoolsr   heapqr   r   	itertoolsr   typesr   typingr	   r
   r   r   #LIMITER_REUSED_ACROSS_LOOPS_WARNINGversion_infowarnRuntimeWarningpathdirname__file__r+   r   ra   r$   r"   <module>r      s   
  	 
  2  #   . .N $
 w3GGOOH57	K 3	Ke. er$   