o
    î6WjŒ   ã                   @  s¤   U d dl mZ d dlZd dlZd dlZd dlmZmZ d dlZddl	m
Z
mZ ddlmZ ddlmZmZ dd	lmZ d
gZe e¡Zded< dZG dd
„ d
ƒZdS )é    )ÚannotationsN)ÚCallableÚOptionalé   )ÚAccessTokenÚAccessTokenProvider)ÚWorkloadIdentityError)ÚADVISORY_REFRESH_SECONDSÚMANDATORY_REFRESH_SECONDSé   )ÚAnthropicErrorÚ
TokenCachezlogging.LoggerÚlogé   c                   @  sN   e Zd ZdZeeejdœddd„Zddd„Zddd„Z	ddd„Z
ddd„ZdS ) r   u2  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_sourceÚproviderr   r   Úintr   r   úCallable[[], float]ÚreturnÚNonec                C  s>   || _ || _|| _|| _t ¡ | _d | _d | _d| _	d| _
d S )NFg        )Ú	_providerÚ	_advisoryÚ
_mandatoryÚ_time_sourceÚ	threadingÚLockÚ_lockÚ_cachedÚ_refresh_eventÚ_next_forceÚ_last_advisory_failure_time)Úselfr   r   r   r   © r$   úo/home/esfera/Documents/content_generation/venv/lib/python3.10/site-packages/anthropic/lib/credentials/_cache.pyÚ__init__3   s   

zTokenCache.__init__ÚforceÚboolr   c             
   C  sJ   z| j |d�W S  ty$ } zdt|ƒvr‚ |   ¡ W  Y d}~S d}~ww )z@Invoke ``self._provider``, tolerating legacy zero-arg callables.)Úforce_refreshr)   N)r   Ú	TypeErrorÚstr)r#   r'   Úerrr$   r$   r%   Ú_invoke_providerL   s   €úzTokenCache._invoke_providerc              
   C  s¶   | j � | j}W d  ƒ n1 sw   Y  z| j|d�}W n# tyA } z|jdkr,‚ t d¡ | jdd�}W Y d}~nd}~ww | j � d| _W d  ƒ |S 1 sTw   Y  |S )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,   r$   r$   r%   Ú_call_providerX   s$   ÿ

€ü
ÿþzTokenCache._call_providerr+   c           	      C  s@  	 d}d}| j �q | j}|durb|jdu r|jW  d  ƒ S |j|  ¡  }|| jkr5|jW  d  ƒ S || jkrb| jdurI|jW  d  ƒ S |  ¡ | j t	k r\|jW  d  ƒ S |}t
|ƒ}| jdurk| j}nt ¡ | _d}W d  ƒ n1 s|w   Y  |durŠ| ¡  q z|  ¡ }W nd tyô } zX| j � | j}d| _W d  ƒ n1 s¬w   Y  |dus·J ‚| ¡  |durït|ttjfƒrït d||¡ | j � |  ¡ | _W d  ƒ n1 sáw   Y  |jW  Y d}~S ‚ d}~ww | j � || _| j}d| _W d  ƒ n	1 �sw   Y  |du�sJ ‚| ¡  |jS )z5Return a valid bearer token, refreshing if necessary.TNr   zGAdvisory token refresh failed (%ds remaining); serving cached token: %s)r   r   Ú
expires_atÚtokenr   r   r   r    r"   Ú ADVISORY_REFRESH_BACKOFF_SECONDSr   r   ÚEventÚwaitr1   ÚBaseExceptionÚsetÚ
isinstancer   ÚhttpxÚ	HTTPErrorr   Úwarning)	r#   Úadvisory_fallbackÚremaining_secondsÚcachedÚ	remainingÚwaiter_eventÚfreshr,   Úreleasedr$   r$   r%   Ú	get_tokeni   sz   
ü
ù

óï

€åþýÿ€ñýzTokenCache.get_tokenc                 C  s8   | j � d| _d| _W d  ƒ dS 1 sw   Y  dS )zôClear 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#   r$   r$   r%   Ú
invalidate±   s   "þzTokenCache.invalidateN)
r   r   r   r   r   r   r   r   r   r   )r'   r(   r   r   )r   r   )r   r+   )r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r	   r
   Útimer&   r-   r1   rD   rE   r$   r$   r$   r%   r      s    ú


H)Ú
__future__r   rJ   Úloggingr   Útypingr   r   r:   Ú_typesr   r   Ú	_workloadr   Ú
_constantsr	   r
   Ú_exceptionsr   Ú__all__Ú	getLoggerrF   r   Ú__annotations__r4   r   r$   r$   r$   r%   Ú<module>   s    