
    g                         d dl Zd dlZd dlZd dlZd dlZd dlZd dlZ G d d      Z	 G d d      Z
 G d de	      Z G d d	ej                  j                        Zy)
    Nc                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)	Stopwatcha  
    A simple stopwatch that starts automatically.

    >>> w = Stopwatch()
    >>> _1_sec = datetime.timedelta(seconds=1)
    >>> w.split() < _1_sec
    True
    >>> time.sleep(1.0)
    >>> w.split() >= _1_sec
    True
    >>> w.stop() >= _1_sec
    True
    >>> w.reset()
    >>> w.start()
    >>> w.split() < _1_sec
    True

    Launch the Stopwatch in a context:

    >>> with Stopwatch() as watch:
    ...     assert isinstance(watch.split(), datetime.timedelta)

    After exiting the context, the watch is stopped; read the
    elapsed time directly:

    >>> watch.elapsed
    datetime.timedelta(...)
    >>> watch.elapsed.seconds
    0
    c                 D    | j                          | j                          y N)resetstartselfs    #/opt/Tautulli/lib/tempora/timing.py__init__zStopwatch.__init__+   s    



    c                     t        j                  d      | _        t        j                  t
              5  | `d d d        y # 1 sw Y   y xY wNr   )datetime	timedeltaelapsed
contextlibsuppressAttributeError_startr	   s    r   r   zStopwatch.reset/   s<    ))!,  0 		 	 	s   A  A	c                 l    t        j                  t        j                         | j                  z
        S N)seconds)r   r   time	monotonicr   r	   s    r   _diffzStopwatch._diff4   s#    !!$..*:T[[*HIIr   c                 6    t        j                         | _        y r   )r   r   r   r	   s    r   r   zStopwatch.start7   s    nn&r   c                 d    | xj                   | j                         z  c_         | `| j                   S r   )r   r   r   r	   s    r   stopzStopwatch.stop:   s%    

$K||r   c                 <    | j                   | j                         z   S r   )r   r   r	   s    r   splitzStopwatch.split?   s    ||djjl**r   c                 &    | j                          | S r   )r   r	   s    r   	__enter__zStopwatch.__enter__C   s    

r   c                 $    | j                          y r   )r   )r
   exc_type	exc_value	tracebacks       r   __exit__zStopwatch.__exit__G   s    		r   N)__name__
__module____qualname____doc__r   r   r   r   r   r!   r#   r(    r   r   r   r      s0    >
J'
+r   r   c                        e Zd ZdZd Zd ZeZy)IntervalGovernorz
    Decorate a function to only allow it to be called once per
    min_interval. Otherwise, it returns None.

    >>> gov = IntervalGovernor(30)
    >>> gov.min_interval.total_seconds()
    30.0
    c                     t        |t        j                        rt        j                  |      }|| _        d | _        y r   )
isinstancenumbersNumberr   r   min_interval	last_call)r
   r4   s     r   r   zIntervalGovernor.__init__U   s/    lGNN3#--lCL(r   c                 F     t        j                         fd       }|S )Nc                      j                    xs' j                   j                         j                  kD  }|rt               _          | i |S y r   )r5   r!   r4   r   )argskwargsallowfuncr
   s      r   wrapperz*IntervalGovernor.decorate.<locals>.wrapper\   sM    &T$..*>*>*@4CTCT*TE!*T,V,, r   )	functoolswraps)r
   r;   r<   s   `` r   decoratezIntervalGovernor.decorate[   s%    			- 
	- r   N)r)   r*   r+   r,   r   r?   __call__r-   r   r   r/   r/   K   s     Hr   r/   c                   H     e Zd ZdZ ed      f fd	Zed        Zd Z xZ	S )Timerz
    Watch for a target elapsed time.

    >>> t = Timer(0.1)
    >>> t.expired()
    False
    >>> __import__('time').sleep(0.15)
    >>> t.expired()
    True
    Infc                 N    | j                  |      | _        t        |           y r   )_accepttargetsuperr   )r
   rF   	__class__s     r   r   zTimer.__init__t   s    ll6*r   c                 t    t        | t        j                        r| j                         } | t	        d      } | S )u   
        Accept None or ∞ or datetime or numeric for target

        >>> Timer._accept(datetime.timedelta(seconds=30))
        30.0
        >>> Timer._accept(None)
        inf
        rC   )r1   r   r   total_secondsfloat)rF   s    r   rE   zTimer._acceptx   s5     fh001))+F>5\Fr   c                 X    | j                         j                         | j                  kD  S r   )r!   rJ   rF   r	   s    r   expiredzTimer.expired   s     zz|))+dkk99r   )
r)   r*   r+   r,   rK   r   staticmethodrE   rM   __classcell__)rH   s   @r   rB   rB   h   s/    	 $El   $:r   rB   c                       e Zd ZdZdZdZ	 dZ	 ej                  j                  dd e
d      dfd       Zd Zd Zd Zd	 Zd
 Zy)BackoffDelaya  
    Exponential backoff delay.

    Useful for defining delays between retries. Consider for use
    with ``jaraco.functools.retry_call`` as the cleanup.

    Default behavior has no effect; a delay or jitter must
    be supplied for the call to be non-degenerate.

    >>> bd = BackoffDelay()
    >>> bd()
    >>> bd()

    The following instance will delay 10ms for the first call,
    20ms for the second, etc.

    >>> bd = BackoffDelay(delay=0.01, factor=2)
    >>> bd()
    >>> bd()

    Inspect and adjust the state of the delay anytime.

    >>> bd.delay
    0.04
    >>> bd.delay = 0.01

    Set limit to prevent the delay from exceeding bounds.

    >>> bd = BackoffDelay(delay=0.01, factor=2, limit=0.015)
    >>> bd()
    >>> bd.delay
    0.015

    To reset the backoff, simply call ``.reset()``:

    >>> bd.reset()
    >>> bd.delay
    0.01

    Iterate on the object to retrieve/advance the delay values.

    >>> next(bd)
    0.01
    >>> next(bd)
    0.015
    >>> import itertools
    >>> tuple(itertools.islice(bd, 3))
    (0.015, 0.015, 0.015)

    Limit may be a callable taking a number and returning
    the limited number.

    >>> at_least_one = lambda n: max(n, 1)
    >>> bd = BackoffDelay(delay=0.01, factor=2, limit=at_least_one)
    >>> next(bd)
    0.01
    >>> next(bd)
    1

    Pass a jitter to add or subtract seconds to the delay.

    >>> bd = BackoffDelay(jitter=0.01)
    >>> next(bd)
    0
    >>> next(bd)
    0.01

    Jitter may be a callable. To supply a non-deterministic jitter
    between -0.5 and 0.5, consider:

    >>> import random
    >>> jitter=functools.partial(random.uniform, -0.5, 0.5)
    >>> bd = BackoffDelay(jitter=jitter)
    >>> next(bd)
    0
    >>> 0 <= next(bd) <= 0.5
    True
    r      infc                     || _         || _        t        |t        j                        r|fd}|| _        t        |t        j                        r|fd}|| _        y )Nc                 0    t        dt        |             S r   )maxmin)nlimit_s    r   limitz$BackoffDelay.__init__.<locals>.limit   s    1c&!n--r   c                       S r   r-   )jitter_s   r   jitterz%BackoffDelay.__init__.<locals>.jitter   s    r   )delayfactorr1   r2   r3   rZ   r]   )r
   r^   r_   rZ   r]   r\   rY   s        @@r   r   zBackoffDelay.__init__   sS    
eW^^,F. 
fgnn-G r   c                 @    t        j                  t        |              y r   )r   sleepnextr	   s    r   r@   zBackoffDelay.__call__   s    

4:r   c                 >    | j                   }| j                          |S r   )r^   bump)r
   r^   s     r   __next__zBackoffDelay.__next__   s    

		r   c                     | S r   r-   r	   s    r   __iter__zBackoffDelay.__iter__  s    r   c                     | j                  | j                  | j                  z  | j                         z         | _        y r   )rZ   r^   r_   r]   r	   s    r   rd   zBackoffDelay.bump  s*    ZZ

T[[ 84;;= HI
r   c                 h    | j                   } | j                  |j                  i |j                   y r   )_saved___init__r   r8   r9   )r
   saveds     r   r   zBackoffDelay.reset  s(    $$uzz2U\\2r   N)r)   r*   r+   r,   r^   r_   r]   jaracor=   save_method_argsrK   r   r@   re   rg   rd   r   r-   r   r   rQ   rQ      se    M^ EF!F@&&qeQ  '$
J3r   rQ   )collections.abccollectionsr   r   r=   r2   r   jaraco.functoolsrl   r   r/   rB   abcIteratorrQ   r-   r   r   <module>rs      sT          = =@ :$:I $:N{3;??++ {3r   