
    #	h3                         S SK Jr  S SKr S SKJr  S SKrS SKJ	r	   " S S\5      r
 " S S\5      rg! \ a	    S SKJr   N/f = f)	    wrapsN)MutableMapping)Lockc                   l   ^  \ rS rSrSrSU 4S jjrS rS rS rS r	S r
S	 rS
 rS rS rS rSrU =r$ )_ExpiringMapping   _index_c                    > [         [        U ]
  " U0 UD6  Ub  UO0 U l        X l        X0l        Uc  [        5       U l        gUU l        g)am  Items in this mapping can have individual shelf life,
just like food items in your refrigerator have their different shelf life
determined by each food, not by the refrigerator.

Expired items will be automatically evicted.
The clean-up will be done at each time when adding a new item,
or when looping or counting the entire mapping.
(This is better than being done indecisively by a background thread,
which might not always happen before your accessing the mapping.)

This implementation uses no dependency other than Python standard library.

:param MutableMapping mapping:
    A dict-like key-value mapping, which needs to support __setitem__(),
    __getitem__(), __delitem__(), get(), pop().

    The default mapping is an in-memory dict.

    You could potentially supply a file-based dict-like object, too.
    This implementation deliberately avoid mapping.__iter__(),
    which could be slow on a file-based mapping.

:param int capacity:
    How many items this mapping will hold.
    When you attempt to add new item into a full mapping,
    it will automatically delete the item that is expiring soonest.

    The default value is None, which means there is no capacity limit.

:param int expires_in:
    How many seconds an item would expire and be purged from this mapping.
    Also known as time-to-live (TTL).
    You can also use :func:`~set()` to provide per-item expires_in value.

:param Lock lock:
    A locking mechanism with context manager interface.
    If no lock is provided, a threading.Lock will be used.
    But you may want to supply a different lock,
    if your customized mapping is being shared differently.
N)superr   __init___mapping	_capacity_expires_inr   _lock)selfmappingcapacity
expires_inlockargskwargs	__class__s          G/var/www/html/env/lib/python3.13/site-packages/msal/individual_cache.pyr   _ExpiringMapping.__init__   sG    T 	.??#*#6B!%#|TV

    c                 ~    XR                   :X  a.  [        SR                  XR                  R                  5      5      eg )Nz"key {} is a reserved keyword in {})_INDEX
ValueErrorformatr   __name__)r   keys     r   _validate_key_ExpiringMapping._validate_key>   s9    ++AHH^^,,. / / r   c                 t    U R                      U R                  XU5        SSS5        g! , (       d  f       g= f)a  It sets the key-value pair into this mapping, with its per-item expires_in.

It will take O(logN) time, because it will run some maintenance.
This worse-than-constant time is acceptable, because in a cache scenario,
__setitem__() would only be called during a cache miss,
which would already incur an expensive target function call anyway.

By the way, most other methods of this mapping still have O(1) constant time.
N)r   _set)r   r"   valuer   s       r   set_ExpiringMapping.setC   s#     ZZIIc*- ZZs   )
7c                 6   U R                  U5        U R                  R                  U R                  / 0 45      u  pEU R	                  XE5        [        [        R                  " 5       5      nXc-   nXvU/nX;  n	U R                  =(       a    [        U5      U R                  :  n
U	(       a.  U
(       a'  U R                  U[        R                  " XH5      5        O[        R                  " XH5        Xv/XQ'   X R                  U'   XE4U R                  U R                  '   g N)r#   r   getr   _maintenanceinttimer   len_drop_indexed_entryheapqheappushpopheappush)r   r"   r'   r   sequence
timestampsnow
expires_atentryis_new_itemis_beyond_capacitys              r   r&   _ExpiringMapping._setT   s     	3#}}00r2hG(/$))+%
#&+!^^QJ4>>0Q-$$Z1B1B81STNN8+%+
"c%-%9dkk"r   c                    [        [        R                  " 5       5      nU(       aK  US   u  pEnXSs=::  a  U:  a  O  OO3U R                  X!S   5        [        R                  " U5        U(       a  MK  U R
                  bn  [        U5      U R
                  :  aT  U R                  X!S   5        [        R                  " U5        U R
                  b  [        U5      U R
                  :  a  MR  gggg)z5It will modify input sequence and timestamps in-placer   N)r.   r/   r1   r2   heappopr   r0   )r   r5   r6   r7   r8   
created_atr"   s          r   r-   _ExpiringMapping._maintenanceg   s    $))+*21+'JC-:-$$Z!=MM(# h nn(S_t~~-M$$Z!=MM(# nn(S_t~~-M(-M(r   c                     Uu  p4nX4/UR                  U5      :X  a/  U R                  R                  US5        UR                  US5        gg)zGFor an entry came from index, drop it from timestamps and self._mappingN)r,   r   pop)r   r6   r9   r8   r?   r"   s         r   r1   $_ExpiringMapping._drop_indexed_entryt   sG    &+#
#z~~c'::MMc4(NN3% ;r   c                     U R                   c  [        S5      eU R                     U R                  XU R                   5        SSS5        g! , (       d  f       g= f)zImplements the __setitem__().

Same characteristic as :func:`~set()`,
but use class-wide expires_in which was specified by :func:`~__init__()`.
Nz5Need a numeric value for expires_in during __init__())r   r   r   r&   )r   r"   r'   s      r   __setitem___ExpiringMapping.__setitem__{   sA     #TUUZZIIc$"2"23 ZZs   A
Ac                 ,   U R                  U5        U R                     U R                  R                  U R                  / 0 45      u  p#X1   u  pE[        [        R                  " 5       5      nXVs=::  a  U:  dt  O  U R                  R                  US5        UR                  US5        X#4U R                  U R                  '   [        SR                  UXd:  a
  S5      5      eS5      5      eU R                  U   sSSS5        $ ! , (       d  f       g= f)CIf the item you requested already expires, KeyError will be raised.Nz{} {}expiredzcreated in the future?)
r#   r   r   r,   r   r.   r/   rB   KeyErrorr    )r   r"   r5   r6   r8   r?   r7   s          r   __getitem___ExpiringMapping.__getitem__   s    3ZZ#'==#4#4T[[2r(#K H%/_"Jdiik"C1z1!!#t,sD)-5-Adkk*w~~!$!2I   8P    ==% ZZs   CD
Dc                 6   U R                  U5        U R                     U R                  R                  US5        U R                  R	                  U R
                  / 0 45      u  p#X1	 X#4U R                  U R
                  '   SSS5        g! , (       d  f       g= f)rH   N)r#   r   r   rB   r,   r   )r   r"   r5   r6   s       r   __delitem___ExpiringMapping.__delitem__   sp    3ZZMMc4(#'==#4#4T[[2r(#K H)1)=DMM$++& ZZs   A#B


Bc                    U R                      U R                  R                  U R                  / 0 45      u  pU R	                  X5        X4U R                  U R                  '   [        U5      sSSS5        $ ! , (       d  f       g= f)z6Drop all expired items and return the remaining lengthN)r   r   r,   r   r-   r0   r   r5   r6   s      r   __len___ExpiringMapping.__len__   s^    ZZ#'==#4#4T[[2r(#K Hh3)1)=DMM$++&z?	 ZZs   A A77
Bc                    U R                      U R                  R                  U R                  / 0 45      u  pU R	                  X5        X4U R                  U R                  '   SSS5        [        W5      $ ! , (       d  f       N= f)zDDrop all expired items and return an iterator of the remaining itemsN)r   r   r,   r   r-   iterrQ   s      r   __iter___ExpiringMapping.__iter__   sg    ZZ#'==#4#4T[[2r(#K Hh3)1)=DMM$++&  J	 Zs   AA66
B)r   r   r   r   )NNNN)r!   
__module____qualname____firstlineno__r   r   r#   r(   r&   r-   r1   rE   rK   rN   rR   rV   __static_attributes____classcell__)r   s   @r   r   r      sE    F.6`/
.":&$&	4&$>#   r   r   c                   $    \ rS rSrSS jrS rSrg)_IndividualCache   Nc                 J    Ub  UO0 U l         U=(       d    S U l        X0l        g)a6  Constructs a cache decorator that allows item-by-item control on
how to cache the return value of the decorated function.

:param MutableMapping mapping:
    The cached items will be stored inside.
    You'd want to use a ExpiringMapping
    if you plan to utilize the ``expires_in`` behavior.

    If nothing is provided, an in-memory dict will be used,
    but it will provide no expiry functionality.

    .. note::

        When using this class as a decorator,
        your mapping needs to be available at "compile" time,
        so it would typically be a global-, module- or class-level mapping::

            module_mapping = {}

            @IndividualCache(mapping=module_mapping, ...)
            def foo():
                ...

        If you want to use a mapping available only at run-time,
        you have to manually decorate your function at run-time, too::

            def foo():
                ...

            def bar(runtime_mapping):
                foo = IndividualCache(mapping=runtime_mapping...)(foo)

:param callable key_maker:
    A callable which should have signature as
    ``lambda function, args, kwargs: "return a string as key"``.

    If key_maker happens to return ``None``, the cache will be bypassed,
    the underlying function will be invoked directly,
    and the invoke result will not be cached either.

:param callable expires_in:
    The default value is ``None``,
    which means the content being cached has no per-item expiry,
    and will subject to the underlying mapping's global expiry time.

    It can be an integer indicating
    how many seconds the result will be cached.
    In particular, if the value is 0,
    it means the result expires after zero second (i.e. immediately),
    therefore the result will *not* be cached.
    (Mind the difference between ``expires_in=0`` and ``expires_in=None``.)

    Or it can be a callable with the signature as
    ``lambda function=function, args=args, kwargs=kwargs, result=result: 123``
    to calculate the expiry on the fly.
    Its return value will be interpreted in the same way as above.
Nc                 :    U U[        UR                  5       5      4$ r+   )tupleitems)functionr   r   s      r   <lambda>+_IndividualCache.__init__.<locals>.<lambda>   s     &,,.!Hr   )r   
_key_makerr   )r   r   	key_makerr   s       r   r   _IndividualCache.__init__   s,    t $+#6B#  ) &r   c                 4   ^ ^ [        T5      UU 4S j5       nU$ )Nc                    > TR                  TX5      nUc  T" U 0 UD6$ [        [        R                  " 5       5      n TR                  U   $ ! [         a     Of = fT" U 0 UD6n[        TR                  5      (       a  TR                  TU UUS9OTR                  nUS:X  a  U$ Uc  UTR                  U'   U$ TR                  R                  X$U5        U$ )N)rd   r   r   resultr   )rg   r.   r/   r   rJ   callabler   r(   )r   r   r"   r7   r'   r   rd   r   s         r   wrapper*_IndividualCache.__call__.<locals>.wrapper   s    //(D9C{000diik"C}}S))  	
 d-f-E d..// ))!	 * 
 6:5E5E  Q!%*c" L !!#j9Ls   A 
AAr   )r   rd   rn   s   `` r   __call___IndividualCache.__call__   s     	x	 
	: r   )r   rg   r   )NNN)r!   rX   rY   rZ   r   rp   r[    r   r   r^   r^      s    
C&J r   r^   )	functoolsr   r/   collections.abcr   ImportErrorcollectionsr2   	threadingr   r   objectr^   rr   r   r   <module>ry      sM     +.  e ~ e Pjv j]  +*+s   3 AA