U
    ~fh                     @  s  U d Z ddlm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mZmZmZmZmZmZmZ erddlmZ ed	dd
Zded	< eddd
Zded< ededd
Zded< ddddZddddZddddZdddddZ ddddZ!ddd d!d"Z"G d#d$ d$e	Z#ed%ed&ef d'Z$d%d%d(d)d*Z%d+d,dd-d.d/Z&d0Z'd1ed2< d3Z(d1ed4< G d5d6 d6Z)dS )7zInternal helpers for CSOT.    )annotationsN)deque)AbstractContextManager)
ContextVarToken)TYPE_CHECKINGAnyCallableDequeMutableMappingOptionalTypeVarcast)WriteConcernTIMEOUT)defaultzContextVar[Optional[float]]RTT        zContextVar[float]DEADLINEinfOptional[float]returnc                   C  s
   t d S N)r   get r   r   1/tmp/pip-unpacked-wheel-36gvocj8/pymongo/_csot.pyget_timeout#   s    r   floatc                   C  s   t  S r   )r   r   r   r   r   r   get_rtt'   s    r   c                   C  s   t  S r   )r   r   r   r   r   r   get_deadline+   s    r    None)rttr   c                 C  s   t |  d S r   )r   set)r"   r   r   r   set_rtt/   s    r$   c                   C  s   t  s
d S t t  S r   )r   r   r   time	monotonicr   r   r   r   	remaining3   s    r'   )max_timeoutr   c                 C  s   t  }|dkr| S t|| S )z4Return the remaining timeout clamped to a max value.N)r'   min)r(   timeoutr   r   r   clamp_remaining9   s    r+   c                   @  s@   e Zd ZdZddddZdddd	Zd
d
d
ddddZdS )_TimeoutContextzInternal timeout context manager.

    Use :func:`pymongo.timeout` instead::

      with pymongo.timeout(0.5):
          client.test.test.insert_one({})
    r   )r*   c                 C  s   || _ d | _d S r   )_timeout_tokens)selfr*   r   r   r   __init__J   s    z_TimeoutContext.__init__r!   r   c                 C  sZ   t | j}t }| jr(t | j ntd}tt||}t	d}|||f| _
d S )Nr   r   )r   r#   r-   r   r   r%   r&   r   r)   r   r.   )r/   timeout_tokenZprev_deadlineZnext_deadlinedeadline_token	rtt_tokenr   r   r   	__enter__N   s    
z_TimeoutContext.__enter__r   )exc_typeexc_valexc_tbr   c                 C  s4   | j r0| j \}}}t| t| t| d S r   )r.   r   resetr   r   )r/   r5   r6   r7   r1   r2   r3   r   r   r   __exit__V   s
    

z_TimeoutContext.__exit__N)__name__
__module____qualname____doc__r0   r4   r9   r   r   r   r   r,   A   s   r,   F.)bound)funcr   c                   sZ   t  r.t ddddd fdd}n"t ddddd fdd}tt|S )zbApply the client's timeoutMS to this operation. Can wrap both asynchronous and synchronous methodsr   )r/   argskwargsr   c              
     s`   t  d krJ| j}|d k	rJt|$  | f||I d H W  5 Q R  S Q R X  | f||I d H S r   r   r-   r,   r/   rA   rB   r*   r@   r   r   csot_wrapperf   s    

(zapply.<locals>.csot_wrapperc              
     sT   t  d krD| j}|d k	rDt|  | f||W  5 Q R  S Q R X  | f||S r   rC   rD   rE   r   r   rF   p   s    

")inspectiscoroutinefunction	functoolswrapsr   r>   )r@   rF   r   rE   r   applyb   s    
	rK   zMutableMapping[str, Any]zOptional[WriteConcern])cmdwrite_concernr   c                 C  s:   |r
|j rdS |j}t dk	r*|dd |r6|| d< dS )z+Apply the given write concern to a command.NZwtimeoutZwriteConcern)Zis_server_defaultdocumentr   pop)rL   rM   Zwcr   r   r   apply_write_concern|   s    

rP   
   int_MAX_RTT_SAMPLES   _MIN_RTT_SAMPLESc                   @  sT   e Zd ZU dZded< ddddZddd	d
dZddddZddddZdS )MovingMinimumz4Tracks a minimum RTT within the last 10 RTT samples.zDeque[float]samplesr!   r   c                 C  s   t td| _d S )N)maxlen)r   rS   rW   r/   r   r   r   r0      s    zMovingMinimum.__init__r   )sampler   c                 C  s&   |dk rt d| | j| d S )Nr   zduration cannot be negative )
ValueErrorrW   append)r/   rZ   r   r   r   
add_sample   s    zMovingMinimum.add_samplec                 C  s   t | jtkrt| jS dS )z7Get the min, or 0.0 if there aren't enough samples yet.r   )lenrW   rU   r)   rY   r   r   r   r      s    
zMovingMinimum.getc                 C  s   | j   d S r   )rW   clearrY   r   r   r   r8      s    zMovingMinimum.resetN)	r:   r;   r<   r=   __annotations__r0   r]   r   r8   r   r   r   r   rV      s   
rV   )*r=   
__future__r   rI   rG   r%   collectionsr   
contextlibr   Zcontextvarsr   r   typingr   r   r	   r
   r   r   r   r   Zpymongo.write_concernr   r   r`   r   r   r   r   r   r    r$   r'   r+   r,   r>   rK   rP   rS   rU   rV   r   r   r   r   <module>   s4   (