
    b\j                         % S SK Jr  S SKrS SKrS SKrS SKJrJr  S SKrSSK	J
r
Jr  SSKJr  SSKJrJr  SS	KJr  S
/r\R(                  " \5      rS\S'   Sr " S S
5      rg)    )annotationsN)CallableOptional   )AccessTokenAccessTokenProvider)WorkloadIdentityError)ADVISORY_REFRESH_SECONDSMANDATORY_REFRESH_SECONDS   )AnthropicError
TokenCachezlogging.Loggerlog   c                  |    \ rS rSrSr\\\R                  S.         SS jjrSS jr	SS jr
SS jrSS jrS	rg
)r      u  Thread-safe cache wrapping an :class:`AccessTokenProvider` with two-tier
proactive refresh and single-flight semantics.

Refresh policy on each :meth:`get_token` call:

* No cached token → call provider (blocking), cache, return.
* Cached with ``expires_at=None`` → return cached forever (never refresh).
* More than ``advisory_refresh_seconds`` remaining → return cached.
* Between ``mandatory_refresh_seconds`` and ``advisory_refresh_seconds``
  remaining (advisory window) → try provider; on success swap cache; on
  failure log a warning and return the stale cached token. If another
  caller is already refreshing, the advisory caller just returns the
  cached token — no second refresh, no waiting.
* Less than ``mandatory_refresh_seconds`` remaining or already expired
  (mandatory window) → call provider; on failure RAISE. Concurrent
  mandatory callers wait on a shared ``Event`` so exactly one provider
  call is in flight.

The lock is released before the provider call so a 30-second HTTP POST
doesn't serialize unrelated callers through a single thread. This matters
under async: ``asyncify(get_token)`` runs on the thread pool, and holding
the lock across the network call would pin an async worker for the whole
exchange.
)advisory_refresh_secondsmandatory_refresh_secondstime_sourcec                   Xl         X l        X0l        X@l        [        R
                  " 5       U l        S U l        S U l        SU l	        SU l
        g )NFg        )	_provider	_advisory
_mandatory_time_source	threadingLock_lock_cached_refresh_event_next_force_last_advisory_failure_time)selfproviderr   r   r   s        V/var/www/website/venv/lib/python3.13/site-packages/anthropic/lib/credentials/_cache.py__init__TokenCache.__init__3   sL     "13'^^%
.2 :> ! 36(    c                    U R                  US9$ ! [         a*  nS[        U5      ;  a  e U R                  5       s SnA$ SnAff = f)z@Invoke ``self._provider``, tolerating legacy zero-arg callables.)force_refreshr)   N)r   	TypeErrorstr)r"   forceerrs      r$   _invoke_providerTokenCache._invoke_providerL   sF    	$>>>66 	$ c#h.>>##	$s    
AA A Ac                ~   U R                      U R                  nSSS5         U R                  WS9nU R                      SU l        SSS5        U$ ! , (       d  f       N<= f! [         a?  nUR                  S:w  a  e [
        R                  S5        U R                  SS9n SnANsSnAff = f! , (       d  f       U$ = f)zBCall the provider, retrying once on a 401 from the token endpoint.N)r,   i  z*Token provider returned 401; retrying onceTF)r   r    r.   r	   status_coder   debug)r"   r,   resultr-   s       r$   _call_providerTokenCache._call_providerX   s     ZZ$$E 	7***7F ZZ$D  Z % 	7#%IIBC***6F		7
 Zs-   AA! B-
A!
B*+5B%%B*-
B<c                    SnSnU R                      U R                  nUb  UR                  c  UR                  sSSS5        $ UR                  U R	                  5       -
  nX@R
                  :  a  UR                  sSSS5        $ X@R                  :  ai  U R                  b  UR                  sSSS5        $ U R	                  5       U R                  -
  [        :  a  UR                  sSSS5        $ Un[        U5      nU R                  b  U R                  nO[        R                  " 5       U l        SnSSS5        Wb  UR                  5         GMP   U R                  5       nU R                      X`l        U R                  nSU l        SSS5        Wc   eUR!                  5         UR                  $ ! , (       d  f       N= f! [         a  nU R                      U R                  nSU l        SSS5        O! , (       d  f       O= fWc   eUR!                  5         Ub  [#        U[$        [&        R(                  45      (       ad  [*        R-                  SUU5        U R                      U R	                  5       U l        SSS5        O! , (       d  f       O= fUR                  s SnA$ e SnAff = f! , (       d  f       GN/= f)z5Return a valid bearer token, refreshing if necessary.Nr   zGAdvisory token refresh failed (%ds remaining); serving cached token: %s)r   r   
expires_attokenr   r   r   r   r!    ADVISORY_REFRESH_BACKOFF_SECONDSintr   Eventwaitr4   BaseExceptionset
isinstancer   httpx	HTTPErrorr   warning)	r"   advisory_fallbackremaining_secondscached	remainingwaiter_eventfreshr-   releaseds	            r$   	get_tokenTokenCache.get_tokeni   sD   7; !%((0%||	 
 !' 1 1D4E4E4G GI >>1%||  !??2  ..:#)<<    ,,.1Q1QQTtt#)<<# $ -3),/	N)&&2>B>Q>QL +4//*;D'#'L7 : '!!# ++-$ $..&*#  '''LLN;;C T ! ZZ#22H*.D'  ZZ  +++$0ZnV[VeVeEf5g5gKKa)
 ;?;L;L;N8 $,222" s   (F17F1'F160F10AF1G .J01
F?
J-J(G5,	J(5
H	?A'J(&J<	J(
J	J(!J-'J((J-0
J?c                l    U R                      SU l        SU l        SSS5        g! , (       d  f       g= f)zClear the cached token so the next :meth:`get_token` re-invokes the provider.

Also sets a one-shot ``force_refresh`` flag so on-disk providers skip
their freshness short-circuit instead of re-serving the revoked token.
NT)r   r   r    )r"   s    r$   
invalidateTokenCache.invalidate   s$     ZZDL#D ZZs   %
3)	r   r   r!   r   r   r    r   r   r   N)
r#   r   r   r:   r   r:   r   zCallable[[], float]returnNone)r,   boolrO   r   )rO   r   )rO   r+   )rO   rP   )__name__
__module____qualname____firstlineno____doc__r
   r   timer%   r.   r4   rJ   rM   __static_attributes__ r'   r$   r   r      sb    : )A)B+/996%6 #&	6
 $'6 )6 
62
$"FP$r'   )
__future__r   rW   loggingr   typingr   r   r@   _typesr   r   	_workloadr	   
_constantsr
   r   _exceptionsr   __all__	getLoggerrR   r   __annotations__r9   r   rY   r'   r$   <module>rd      sS    "    %  4 , K ).''1^ 1
 $%  `$ `$r'   