U
    /e0'                     @  s   d dl mZ d dlmZmZmZmZmZmZm	Z	 d dl
mZmZmZmZmZmZmZmZ d dlmZ G dd deeef ZdS )    )annotations)Callable
Collection	ItemsViewIteratorKeysViewMutableMapping
ValuesView)KTVT	NoDefaultZictBasecloseflushlocked	nodefault)InsertionSortedSetc                      s  e Zd ZU dZded< ded< ded< ded< ded	< d
ed< ded< ded< ded< ded< ded< ded< dddd dddddd
d fddZeddd d!d"Zed#d$d%d&d'Zddd(d)d*d+Z	eddd(d)d,d-Z
dRd.d(d/d0d1Zeefd2d3d d4d5Zedd(d d6d7Zd8d9d:d;Zd<d9d=d>Zd?d9d@dAZdBd9dCdDZdEd9dFdGZdHdd dIdJZdKd9dLdMZeZd(d9dNdOZd(d9dPdQZ  ZS )SLRUa  Evict Least Recently Used Elements.

    Parameters
    ----------
    n: int or float
        Number of elements to keep, or total weight if ``weight`` is used.
        Any individual key that is heavier than n will be automatically evicted as soon
        as it is inserted.

        It can be updated after initialization. See also: ``offset`` attribute.
    d: MutableMapping
        Dict-like in which to hold elements. There are no expectations on its internal
        ordering. Iteration on the LRU follows the order of the underlying mapping.
    on_evict: callable or list of callables
        Function:: k, v -> action to call on key/value pairs prior to eviction
        If an exception occurs during an on_evict callback (e.g a callback tried
        storing to disk and raised a disk full error) the key will remain in the LRU.
    on_cancel_evict: callable or list of callables
        Function:: k, v -> action to call on key/value pairs if they're deleted or
        updated from a thread while the on_evict callables are being executed in
        another.
        If you're not accessing the LRU from multiple threads, ignore this parameter.
    weight: callable
        Function:: k, v -> number to determine the size of keeping the item in
        the mapping.  Defaults to ``(k, v) -> 1``

    Notes
    -----
    If you call methods of this class from multiple threads, access will be fast as long
    as all methods of ``d`` are fast. Callbacks are not protected by locks and can be
    arbitrarily slow.

    Examples
    --------
    >>> lru = LRU(2, {}, on_evict=lambda k, v: print("Lost", k, v))
    >>> lru['x'] = 1
    >>> lru['y'] = 2
    >>> lru['z'] = 3
    Lost x 1
    zMutableMapping[KT, VT]dzInsertionSortedSet[KT]orderheavyzlist[Callable[[KT, VT], None]]on_evicton_cancel_evictzCallable[[KT, VT], float]weightfloatnoffsetzdict[KT, float]weightsboolclosedtotal_weightzdict[KT, bool]_cancel_evictNc                 C  s   dS )N    )kvr#   r#   ,/tmp/pip-unpacked-wheel-z3s6s24u/zict/lru.py<lambda>]       zLRU.<lambda>)r   r   r   z@Callable[[KT, VT], None] | list[Callable[[KT, VT], None]] | None)r   r   r   r   r   c                  s   t    || _ | _d| _t|r*|g}|p0g | _t|rB|g}|pHg | _| _fdd|	 D | _
t| j
 | _t|| _t fdd| j
	 D | _d| _i | _d S )Nr   c                   s   i | ]\}}| ||qS r#   r#   .0r$   r%   )r   r#   r&   
<dictcomp>l   s      z LRU.__init__.<locals>.<dictcomp>c                 3  s   | ]\}}| kr|V  qd S Nr#   r)   )r   r#   r&   	<genexpr>o   s      zLRU.__init__.<locals>.<genexpr>F)super__init__r   r   r   callabler   r   r   itemsr   sumvaluesr    r   r   r   r   r!   )selfr   r   r   r   r   	__class__)r   r   r&   r/   R   s"    



zLRU.__init__r
   r   )keyreturnc                 C  s&   | j | }| j| | j| |S r,   )r   r   removeadd)r4   r7   resultr#   r#   r&   __getitem__s   s    
zLRU.__getitem__zCollection[KT]zdict[KT, VT])keysr8   c                   s8    fdd|D }|D ]} j |  j | q|S )a8  If all keys exist in the LRU, update their FIFO priority and return their
        values; this would be the same as ``{k: lru[k] for k in keys}``.
        If any keys are missing, however, raise KeyError for the first one missing and
        do not bring any of the available keys to the top of the LRU.
        c                   s   i | ]}| j | qS r#   r   )r*   r7   r4   r#   r&   r+      s      z*LRU.get_all_or_nothing.<locals>.<dictcomp>)r   r9   r:   )r4   r=   r;   r7   r#   r?   r&   get_all_or_nothingz   s
    zLRU.get_all_or_nothingNone)r7   valuer8   c                 C  s   |  || z|   W nf tk
r~   | j|d| jkrx|| jkrxzt| jdkr`| 	  qHW n tk
rv   Y nX  Y nX d S )Nr   r"   )
set_noevictevict_until_below_target	Exceptionr   getr   r   lenr   evict)r4   r7   rB   r#   r#   r&   __setitem__   s    zLRU.__setitem__c                 C  sr   |  | | ||}|| jkr*d| j|< || j|< | j| || jkrV| j| || j|< |  j	|7  _	dS )a<  Variant of ``__setitem__`` that does not evict if the total weight exceeds n.
        Unlike ``__setitem__``, this method does not depend on the ``on_evict``
        functions to be thread-safe for its own thread-safety. It also is not prone to
        re-raising exceptions from the ``on_evict`` callbacks.
        TN)
discardr   r!   r   r   r:   r   r   r   r    )r4   r7   rB   r   r#   r#   r&   rC      s    





zLRU.set_noevictzfloat | None)r   r8   c                 C  sN   |dkr| j }| j| j |krJ| jsJz|   W q tk
rF   Y dS X qdS )zEvict key/value pairs until the total weight falls below n

        Parameters
        ----------
        n: float, optional
            Total weight threshold to achieve. Defaults to self.n.
        N)r   r    r   r   rH   KeyError)r4   r   r#   r#   r&   rD      s    zLRU.evict_until_below_targetzKT | NoDefaultz/tuple[KT, VT, float] | tuple[None, None, float]c              	   C  s  |t kr>ztt| jp| j}W n tk
r<   tdY nX || jkrLdS | j| }| j	| d| j|< z`| 
 N | jD ]}||| q~| j| r| jD ]}||| qW 5 Q R  W dS W 5 Q R X W 5 | j|= X | j|= | j| | j|}|  j|8  _|||fS )a$  Evict least recently used key, or least recently inserted key with individual
        weight > n, if any. You may also evict a specific key.

        This is typically called from internal use, but can be externally
        triggered as well.

        Returns
        -------
        Tuple of (key, value, weight)

        Or (None, None, 0) if the key that was being evicted was updated or deleted from
        another thread while the on_evict callbacks were being executed. This outcome is
        only possible in multithreaded access.
        zevict(): dictionary is empty)NNr   F)r   nextiterr   r   StopIterationrK   r!   r   rJ   Zunlockr   r   r9   r   popr    )r4   r7   rB   cbr   r#   r#   r&   rH      s0    






 
z	LRU.evictc                 C  sN   || j krd| j |< | j|= | j| | j| |  j| j|8  _d S NT)	r!   r   r   r9   r   rJ   r    r   rO   r4   r7   r#   r#   r&   __delitem__   s    

zLRU.__delitem__zKeysView[KT])r8   c                 C  s
   | j  S r,   )r   r=   r?   r#   r#   r&   r=      s    zLRU.keyszValuesView[VT]c                 C  s
   | j  S r,   )r   r3   r?   r#   r#   r&   r3      s    z
LRU.valueszItemsView[KT, VT]c                 C  s
   | j  S r,   )r   r1   r?   r#   r#   r&   r1     s    z	LRU.itemsintc                 C  s
   t | jS r,   )rG   r   r?   r#   r#   r&   __len__  s    zLRU.__len__zIterator[KT]c                 C  s
   t | jS r,   )rM   r   r?   r#   r#   r&   __iter__  s    zLRU.__iter__objectc                 C  s
   || j kS r,   r>   rR   r#   r#   r&   __contains__  s    zLRU.__contains__strc                 C  s<   t | jtst| jnd}d| j| j  d| j d| dS )Ndictz<LRU: /z on >)
isinstancer   rZ   rY   r    r   r   )r4   subr#   r#   r&   __str__  s    zLRU.__str__c                 C  s   t | j d S r,   )r   r   r?   r#   r#   r&   r     s    z	LRU.flushc                 C  s   d| _ t| j d S rQ   )r   r   r   r?   r#   r#   r&   r     s    z	LRU.close)N)__name__
__module____qualname____doc____annotations__r/   r   r<   r@   rI   rC   rD   r   rH   rS   r=   r3   r1   rU   rV   rX   r_   __repr__r   r   __classcell__r#   r#   r5   r&   r      sP   
)	!:r   N)
__future__r   collections.abcr   r   r   r   r   r   r	   Zzict.commonr
   r   r   r   r   r   r   r   Z
zict.utilsr   r   r#   r#   r#   r&   <module>   s   $
(