o
    .jG<                  	   @  sb  d Z ddlmZ 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mZmZmZ ejr=ddlmZmZ g d	Zd-ddZd.ddZd/ddZG dd dejeejejeef  f eje ZG dd dee ZG dd  d ee ZG d!d" d"ZG d#d$ d$Z G d%d& d&eeZ!G d'd( d(eeZ"G d)d* d*e eZ#G d+d, d,e eZ$dS )0a  
requests.hooks
~~~~~~~~~~~~~~

This module provides the capabilities for the Requests hooks system.

Available hooks:

``pre_request``:
    The prepared request just got built. You may alter it prior to be sent through HTTP.
``pre_send``:
    The prepared request got his ConnectionInfo injected.
    This event is triggered just after picking a live connection from the pool.
``on_upload``:
    Permit to monitor the upload progress of passed body.
    This event is triggered each time a block of data is transmitted to the remote peer.
    Use this hook carefully as it may impact the overall performance.
``response``:
    The response generated from a Request.
    )annotationsN)MutableMapping   )iscoroutinefunction)_HVAsyncHookCallableTypeAsyncHookTypeHookCallableTypeHookType)PreparedRequestResponsepre_requestpre_send	on_uploadearly_responseresponsereturnHookType[_HV]c                   C  s   dd t D S )Nc                 S  s   i | ]}|g qS  r   ).0eventr   r   C/home/thesage/.local/lib/python3.10/site-packages/niquests/hooks.py
<dictcomp>4   s    z!default_hooks.<locals>.<dictcomp>)HOOKSr   r   r   r   default_hooks3   s   r   keystrhooksHookType[_HV] | None	hook_datar   kwargs
typing.Anyc              	   K  sr   |du r|S | | }|r7t|r|g}|D ] }z
||fi |}W n ty/   ||}Y nw |dur6|}q|S )z6Dispatches a hook dictionary on a given piece of data.N)getcallable	TypeErrorr   r   r    r!   	callableshook
_hook_datar   r   r   dispatch_hook7   s    
r*   AsyncHookType[_HV] | Nonec              	     s   |du r|S | | }|rZt|r|g}|D ]B}t|r;z||fi |I dH }W n( ty:   ||I dH }Y nw z
||fi |}W n tyR   ||}Y nw |durY|}q|S )zEDispatches a hook dictionary on a given piece of data asynchronously.N)r#   r$   r   r%   r&   r   r   r   async_dispatch_hookL   s.   
r,   c                   @  s^   e Zd ZdddZdd	d
ZdddZdddZdddZdd Zdd Z	dd Z
dd ZdS )_BaseLifeCycleHookr   Nonec                 C  s   g g g g g d| _ d S Nr   _storeselfr   r   r   __init__k   s   z_BaseLifeCycleHook.__init__r   str | bytesvalue8list[HookCallableType[_HV] | AsyncHookCallableType[_HV]]c                 C     t dNzLifeCycleHook is Read OnlyNotImplementedError)r3   r   r6   r   r   r   __setitem__t      z_BaseLifeCycleHook.__setitem__r   c                 C  s
   | j | S Nr0   r3   r   r   r   r   __getitem__w      
z_BaseLifeCycleHook.__getitem__c                 C  s   | | S r>   r   r?   r   r   r   r#   z   r=   z_BaseLifeCycleHook.getc                 C  sT   t |tsti }t }| j D ]\}}|||< ||  |j| 7  < q||_|S r>   )
isinstancer-   r%   r1   items)r3   other	tmp_storecombined_hookshfnsr   r   r   __add__}   s   
z_BaseLifeCycleHook.__add__c                 c  s    | j E d H  d S r>   r0   r2   r   r   r   __iter__   s   z_BaseLifeCycleHook.__iter__c                 c  s    | D ]	}|| | fV  qd S r>   r   r?   r   r   r   rC      s   z_BaseLifeCycleHook.itemsc                 C  r8   r9   r:   r?   r   r   r   __delitem__   r=   z_BaseLifeCycleHook.__delitem__c                 C  s
   t | jS r>   )lenr1   r2   r   r   r   __len__   rA   z_BaseLifeCycleHook.__len__Nr   r.   )r   r5   r6   r7   r   r.   )r   r   r   r7   )r   r-   )__name__
__module____qualname__r4   r<   r@   r#   rI   rJ   rC   rK   rM   r   r   r   r   r-   h   s    

	


r-   c                      T   e Zd ZdZd fddZdddZdddZdddZdddZdddZ	  Z
S )LifeCycleHookzP
    A sync-only middleware to be used in your request/response lifecycles.
    r   r.   c                   :   t    | j| jg| jg| jg| jg| jgd d S r/   	superr4   r1   updater   r   r   r   r   r2   	__class__r   r   r4         
zLifeCycleHook.__init__prepared_requestr   r!   r"   PreparedRequest | Nonec                 K     dS zTThe prepared request just got built. You may alter it prior to be sent through HTTP.Nr   r3   r[   r!   r   r   r   r         zLifeCycleHook.pre_requestc                 K  r]   zThe prepared request got his ConnectionInfo injected. This event is triggered just
        after picking a live connection from the pool. You may not alter the prepared request.Nr   r_   r   r   r   r         zLifeCycleHook.pre_sendc                 K  r]   a  Permit to monitor the upload progress of passed body. This event is triggered each time
        a block of data is transmitted to the remote peer. Use this hook carefully as
        it may impact the overall performance. You may not alter the prepared request.Nr   r_   r   r   r   r      s   zLifeCycleHook.on_uploadr   r   c                 K  r]   zAn early response caught before receiving the final Response for a given Request.
        Like but not limited to 103 Early Hints.Nr   r3   r   r!   r   r   r   r      rb   zLifeCycleHook.early_responseResponse | Nonec                 K  r]   zJThe response generated from a Request. You may alter the response at will.Nr   re   r   r   r   r      r`   zLifeCycleHook.responserN   r[   r   r!   r"   r   r\   r[   r   r!   r"   r   r.   r   r   r!   r"   r   r.   r   r   r!   r"   r   rf   rO   rP   rQ   __doc__r4   r   r   r   r   r   __classcell__r   r   rX   r   rS          



rS   c                      rR   )AsyncLifeCycleHookzR
    An async-only middleware to be used in your request/response lifecycles.
    r   r.   c                   rT   r/   rU   r2   rX   r   r   r4      rZ   zAsyncLifeCycleHook.__init__r[   r   r!   r"   r\   c                      dS r^   r   r_   r   r   r   r         zAsyncLifeCycleHook.pre_requestc                   rq   ra   r   r_   r   r   r   r         zAsyncLifeCycleHook.pre_sendc                   rq   rc   r   r_   r   r   r   r      s   zAsyncLifeCycleHook.on_uploadr   r   c                   rq   rd   r   re   r   r   r   r      rs   z!AsyncLifeCycleHook.early_responserf   c                   rq   rg   r   re   r   r   r   r      rr   zAsyncLifeCycleHook.responserN   rh   ri   rj   rk   rl   r   r   rX   r   rp      ro   rp   c                   @  sH   e Zd ZU dZded< ded< ded< dd	d
ZdddZdddZdS )_LeakyBucketMixinz$Shared leaky bucket algorithm logic.floatrateintervalfloat | Nonelast_requestr   r.   c                 C  s   || _ d| | _d | _d S )N      ?)rv   rw   ry   r3   rv   r   r   r   _init_leaky_bucket   s   

z$_LeakyBucketMixin._init_leaky_bucketc                 C  s2   t  }| jdur|| j }| j| }|S d}|S )zDCompute wait time and update state. Returns wait time (may be <= 0).Ng        )time	monotonicry   rw   r3   nowelapsed	wait_timer   r   r   _compute_wait   s   


z_LeakyBucketMixin._compute_waitc                 C  s   t  | _dS )zRecord that a request was made.N)r}   r~   ry   r2   r   r   r   _record_request  s   z!_LeakyBucketMixin._record_requestNrv   ru   r   r.   )r   ru   rN   )rO   rP   rQ   rm   __annotations__r|   r   r   r   r   r   r   rt      s   
 


rt   c                   @  sP   e Zd ZU dZded< ded< ded< ded< dd
dZdddZdddZdS )_TokenBucketMixinz$Shared token bucket algorithm logic.ru   rv   capacitytokenslast_updaterx   r   r.   c                 C  s.   || _ |d ur	|n|| _| j| _t | _d S r>   )rv   r   r   r}   r~   r   r3   rv   r   r   r   r   _init_token_bucket  s   z$_TokenBucketMixin._init_token_bucketc                 C  sb   t  }|| j }t| j| j|| j  | _|| _| jdkr'|  jd8  _dS d| j | j }|S )zUReplenish tokens and try to acquire one. Returns wait time if needed, None otherwise.rz   Nr}   r~   r   minr   r   rv   r   r   r   r   _acquire_token  s   

z _TokenBucketMixin._acquire_tokenc                 C  sD   t  }|| j }t| j| j|| j  | _|| _|  jd8  _dS )z*Called after waiting to consume the token.rz   Nr   )r3   r   r   r   r   r   
_post_wait&  s
   
z_TokenBucketMixin._post_waitNrv   ru   r   rx   r   r.   )r   rx   rN   )rO   rP   rQ   rm   r   r   r   r   r   r   r   r   r   	  s   
 

r   c                      .   e Zd ZdZdd fddZdddZ  ZS )LeakyBucketLimiterap  Rate limiter using the leaky bucket algorithm.

    Requests "leak" out at a constant rate. When a request arrives, it waits
    until enough time has passed since the last request to maintain the rate.

    Usage::

        limiter = LeakyBucketLimiter(rate=10.0)  # 10 requests per second
        with niquests.Session(hooks=limiter) as session:
            ...
          $@rv   ru   r   r.   c                   "   t    | | t | _dS zjInitialize the leaky bucket limiter.

        Args:
            rate: Maximum requests per second
        N)rV   r4   r|   	threadingLock_lockr{   rX   r   r   r4   >     

zLeakyBucketLimiter.__init__r[   r   r!   r"   r\   c                 K  sN   | j  |  }|dkrt| |   W d   dS 1 s w   Y  dS )*Wait if needed to maintain the rate limit.r   N)r   r   r}   sleepr   r3   r[   r!   r   r   r   r   r   H  s   


zLeakyBucketLimiter.pre_requestr   r   rh   rO   rP   rQ   rm   r4   r   rn   r   r   rX   r   r   1      
r   c                      r   )AsyncLeakyBucketLimitera  Rate limiter using the leaky bucket algorithm.

    Requests "leak" out at a constant rate. When a request arrives, it waits
    until enough time has passed since the last request to maintain the rate.

    Usage::

        limiter = AsyncLeakyBucketLimiter(rate=10.0)  # 10 requests per second
        async with niquests.AsyncSession(hooks=limiter) as session:
            ...
    r   rv   ru   r   r.   c                   r   r   )rV   r4   r|   asyncior   r   r{   rX   r   r   r4   _  r   z AsyncLeakyBucketLimiter.__init__r[   r   r!   r"   r\   c              	     sj   | j 4 I dH   |  }|dkrt|I dH  |   W d  I dH  dS 1 I dH s.w   Y  dS )r   Nr   )r   r   r   r   r   r   r   r   r   r   i  s   
z#AsyncLeakyBucketLimiter.pre_requestr   r   rh   r   r   r   rX   r   r   R  r   r   c                      .   e Zd ZdZdd fd
dZdddZ  ZS )TokenBucketLimitera{  Rate limiter using the token bucket algorithm.

    Tokens are added to a bucket at a constant rate up to a maximum capacity.
    Each request consumes one token. Allows bursts up to the bucket capacity.

    Usage::

        limiter = TokenBucketLimiter(rate=10.0, capacity=50.0)  # 10/s, burst of 50
        with niquests.Session(hooks=limiter) as session:
            ...
    r   Nrv   ru   r   rx   r   r.   c                   $   t    | || t | _dS zInitialize the token bucket limiter.

        Args:
            rate: Token replenishment rate (tokens per second)
            capacity: Maximum bucket capacity (defaults to rate, allowing 1 second burst)
        N)rV   r4   r   r   r   r   r   rX   r   r   r4        
zTokenBucketLimiter.__init__r[   r   r!   r"   r\   c                 K  s^   | j " |  }|durt| |   W d   dS W d   dS 1 s(w   Y  dS z1Wait until a token is available, then consume it.N)r   r   r}   r   r   r   r   r   r   r     s   



zTokenBucketLimiter.pre_requestr   Nr   rh   r   r   r   rX   r   r   s      r   c                      r   )AsyncTokenBucketLimitera  Rate limiter using the token bucket algorithm.

    Tokens are added to a bucket at a constant rate up to a maximum capacity.
    Each request consumes one token. Allows bursts up to the bucket capacity.

    Usage::

        limiter = AsyncTokenBucketLimiter(rate=10.0, capacity=50.0)  # 10/s, burst of 50
        async with niquests.AsyncSession(hooks=limiter) as session:
            ...
    r   Nrv   ru   r   rx   r   r.   c                   r   r   )rV   r4   r   r   r   r   r   rX   r   r   r4     r   z AsyncTokenBucketLimiter.__init__r[   r   r!   r"   r\   c              	     s   | j 4 I dH + |  }|dur(t|I dH  |   W d  I dH  dS W d  I dH  dS 1 I dH s9w   Y  dS r   )r   r   r   r   r   r   r   r   r   r     s   
z#AsyncTokenBucketLimiter.pre_requestr   r   rh   r   r   r   rX   r   r     r   r   )r   r   )
r   r   r   r   r    r   r!   r"   r   r   )
r   r   r   r+   r    r   r!   r"   r   r   )%rm   
__future__r   r   r   r}   typingcollections.abcr   _compatr   r   r   r   r	   r
   TYPE_CHECKINGmodelsr   r   r   r   r*   r,   r   ListUnionGenericr-   rS   rp   rt   r   r   r   r   r   r   r   r   r   <module>   s4    
	


$2**(!!"