o
    i?#                     @   s   d dl mZ d dlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ dZd	d
 ZG dd deZdddZG dd de
ZG dd deZG dd deZdS )    )Lock)sha256   )_IndividualCache)_ExpiringMapping)Response)MsalServiceErrorz,urn:ietf:params:oauth:grant-type:device_codec                 C   s   t | di S )Nheaders)getattr)response r   Q/home/app/Keep/.python/lib/python3.10/site-packages/msal/throttled_http_client.py_get_headers   s   r   c                   @   s&   e Zd Zd ZdddZdd ZdS )RetryAfterParserzRetry-AfterNc                 C   s   |d u r	d| _ d S || _ d S )N   )_default_value)selfdefault_valuer   r   r   __init__   s   zRetryAfterParser.__init__c                K   s|   |}dd t | D }|jdks|jdks| j|v sdS || j| j}zt|}W n ty8   | j}Y nw td|S )zReturn seconds to throttlec                 S      i | ]	\}}|  |qS r   lower.0kvr   r   r   
<dictcomp>   s    z*RetryAfterParser.parse.<locals>.<dictcomp>i  i  r   i  )	r   itemsstatus_codeFIELD_NAME_LOWERgetr   int
ValueErrormin)r   resultignoredr   Zlowercase_headersretry_afterZdelay_secondsr   r   r   parse   s   


zRetryAfterParser.parseN)__name__
__module____qualname__r   r   r   r'   r   r   r   r   r      s    
r   Nc                 C   s$   |  di }t|tr| |S |S )Ndata)r    
isinstancedict)kwargskeydefaultr,   r   r   r   _extract_data+   s   r2   c                       s(   e Zd ZdZ fddZdd Z  ZS )NormalizedResponsezoA http response with the shape defined in Response,
    but contains only the data we will store in cache.
    c                    s6   t    |j| _|j| _dd t| D | _d S )Nc                 S   r   r   r   r   r   r   r   r   8   s    z/NormalizedResponse.__init__.<locals>.<dictcomp>)superr   r   textr   r   r	   )r   Zraw_response	__class__r   r   r   4   s   

zNormalizedResponse.__init__c                 C   s$   | j dkrtd| j d d dd S )N  zHTTP Error: {})errorZerror_description)r   r   formatr   r   r   r   raise_for_statusC   s   

z#NormalizedResponse.raise_for_status)r)   r*   r+   __doc__r   r<   __classcell__r   r   r6   r   r3   0   s    r3   c                   @   sB   e Zd ZdZddddZdd Zdd	 Zd
d Zedd Z	dS )ThrottledHttpClientBasea  Throttle the given http_client by storing and retrieving data from cache.

    This base exists so that:
    1. These base post() and get() will return a NormalizedResponse
    2. The base __init__() will NOT re-throttle even if caller accidentally nested ThrottledHttpClient.

    Subclasses shall only need to dynamically decorate their post() and get() methods
    in their __init__() method.
    N)
http_cachec                C   s8   t |tr|jn|| _t|d ur|ni dt d| _d S )Ni   )mappingcapacitylock)r-   r?   http_clientExpiringMappingr   _expiring_mapping)r   rD   r@   r   r   r   r   U   s   
z ThrottledHttpClientBase.__init__c                 O      t | jj|i |S r(   )r3   rD   postr   argsr/   r   r   r   rH   _      zThrottledHttpClientBase.postc                 O   rG   r(   )r3   rD   r    rI   r   r   r   r    b   rK   zThrottledHttpClientBase.getc                 C   s
   | j  S r(   )rD   closer;   r   r   r   rL   e   s   
zThrottledHttpClientBase.closec                 C   s   t t| d S )Nzutf-8)r   reprencode	hexdigest)rawr   r   r   _hashh   s   zThrottledHttpClientBase._hash)
r)   r*   r+   r=   r   rH   r    rL   staticmethodrQ   r   r   r   r   r?   K   s    	
r?   c                       s&   e Zd ZdZdd fdd
Z  ZS )ThrottledHttpClientzLA throttled http client that is used by MSAL's non-managed identity clients.N)default_throttle_timec                   s   t t j|i | t j fddt|pdjd j _t j fddd
ddd j _t j fdddd	dd j _dS )z/Decorate self.post() and self.get() dynamicallyc                    s<   d |d t|dt|d t|dt|dt|dS )Nz9POST {} client_id={} scope={} hash={} 429/5xx/Retry-Afterr   Z	client_idscopeZrefresh_tokencodeusername)r:   r2   rQ   funcrJ   r/   r;   r   r   <lambda>v   s   z.ThrottledHttpClient.__init__.<locals>.<lambda>r   )rA   Z	key_makerZ
expires_inc              
      s.   d |d  t|dt|d S )NzPOST {} hash={} 400r   paramsr,   )r:   rQ   strr    rX   r;   r   r   rZ      s    Nc                 [   sP   | j dkr&t|dtr|d dtks&tjtdd t| D vr&dS dS )Nr8   r,   Z
grant_typec                 s   s    | ]}|  V  qd S r(   r   )r   hr   r   r   	<genexpr>   s    
zAThrottledHttpClient.__init__.<locals>.<lambda>.<locals>.<genexpr><   r   )	r   r-   r    r.   DEVICE_AUTH_GRANTr   r   setr   )r$   r/   r%   r   r   r   rZ      s   

c              	      s   d |d  |ddS )NzGET {} hash={} 2xxr   r[    )r:   rQ   r    rX   r;   r   r   rZ      s    c                 [   s   d| j   krdk rdS  dS )N   i,  iQ r   )r   )r$   r%   r   r   r   rZ      s   )NNr(   )	r4   rS   r   IndividualCacherF   r   r'   rH   r    )r   rT   rJ   r/   r6   r;   r   r   o   s,   

#%

zThrottledHttpClient.__init__)r)   r*   r+   r=   r   r>   r   r   r6   r   rS   m   s    rS   r(   )	threadingr   hashlibr   Zindividual_cacher   rd   r   rE   Zoauth2cli.httpr   
exceptionsr   r`   r   objectr   r2   r3   r?   rS   r   r   r   r   <module>   s    
"