3
ãdej  ã               @   sd   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
dd
d„Zddd„ZG dd„ deƒZd	S )é    )ÚLock)Úsha256é   )Ú_IndividualCache)Ú_ExpiringMappingz,urn:ietf:params:oauth:grant-type:device_codec             C   s   t t| ƒjdƒƒjƒ S )Nzutf-8)r   ÚreprÚencodeÚ	hexdigest)Úraw© r   úQ/var/www/agendate/envp3/lib/python3.6/site-packages/msal/throttled_http_client.pyÚ_hash   s    r   Nc             K   s’   | dk	st dƒ‚| }dd„ t|di ƒjƒ D ƒ}|jdkpH|jdkpHd|ksNd	S d
}t|jd|ƒƒ}yt|ƒ}W n tk
r†   |}Y nX td|ƒS )zReturn seconds to throttleNzî
        The signature defines it with a default value None,
        only because the its shape is already decided by the
        IndividualCache's.__call__().
        In actual code path, the result parameter here won't be None.
        c             S   s   i | ]\}}||j ƒ “qS r   )Úlower)Ú.0ÚkÚvr   r   r   ú
<dictcomp>   s    z3_parse_http_429_5xx_retry_after.<locals>.<dictcomp>Úheadersi­  iô  zretry-afterr   é<   i  )ÚAssertionErrorÚgetattrÚitemsÚstatus_codeÚintÚgetÚ
ValueErrorÚmin)ÚresultÚignoredÚresponseZlowercase_headersÚdefaultÚretry_afterZdelay_secondsr   r   r   Ú_parse_http_429_5xx_retry_after   s    

r"   c             C   s$   | j di ƒ}t|tƒr |j |ƒS |S )NÚdata)r   Ú
isinstanceÚdict)ÚkwargsÚkeyr    r#   r   r   r   Ú_extract_data+   s    r(   c               @   s   e Zd Zdd„ Zdd„ ZdS )ÚThrottledHttpClientc             C   s„   t |dk	r|ni dtƒ d�}|j}t|dd„ td�|ƒ}t|dd„ ddd„d�|ƒ}|| _t|d	d„ dd
d„d�|jƒ| _|| _dS )zêThrottle the given http_client by storing and retrieving data from cache.

        This wrapper exists so that our patching post() and get() would prevent
        re-patching side effect when/if same http_client being reused.
        Ni   )ÚmappingÚcapacityÚlockc             S   s:   dj |d t|dƒt|dƒtt|dt|dt|dƒƒƒƒƒS )Nz9POST {} client_id={} scope={} hash={} 429/5xx/Retry-Afterr   Z	client_idZscopeZrefresh_tokenÚcodeÚusername)Úformatr(   r   )ÚfuncÚargsr&   r   r   r   Ú<lambda>C   s    z.ThrottledHttpClient.__init__.<locals>.<lambda>)r*   Z	key_makerZ
expires_inc             S   s,   dj |d tt|jdƒƒt|jdƒƒ ƒƒS )NzPOST {} hash={} 400r   Úparamsr#   )r/   r   Ústrr   )r0   r1   r&   r   r   r   r2   U   s   c             [   sX   | j dkrTt|jdƒtƒo*|d jdƒtk rTdtdd„ t| di ƒjƒ D ƒƒkrTdS d	S )
Ni�  r#   Z
grant_typezretry-afterc             s   s   | ]}|j ƒ V  qd S )N)r   )r   Úhr   r   r   ú	<genexpr>t   s    zAThrottledHttpClient.__init__.<locals>.<lambda>.<locals>.<genexpr>r   r   r   )r   r$   r   r%   ÚDEVICE_AUTH_GRANTÚsetr   Úkeys)r   r&   r   r   r   r   r2   g   s    
"c             S   s   dj |d t|jddƒƒƒS )NzGET {} hash={} 2xxr   r3   Ú )r/   r   r   )r0   r1   r&   r   r   r   r2   |   s   c             [   s"   d| j   kodk n  rdS dS )NéÈ   i,  i  é   r   i€Q )r   )r   r   r   r   r   r2   €   s    )NN)N)ÚExpiringMappingr   ÚpostÚIndividualCacher"   r   Ú_http_client)ÚselfÚhttp_clientZ
http_cacheZexpiring_mappingÚ_postr   r   r   Ú__init__1   s,    

zThrottledHttpClient.__init__c             C   s
   | j jƒ S )zGMSAL won't need this. But we allow throttled_http_client.close() anyway)r@   Úclose)rA   r   r   r   rE   Š   s    zThrottledHttpClient.closeN)Ú__name__Ú
__module__Ú__qualname__rD   rE   r   r   r   r   r)   0   s   Yr)   )N)N)Ú	threadingr   Úhashlibr   Zindividual_cacher   r?   r   r=   r7   r   r"   r(   Úobjectr)   r   r   r   r   Ú<module>   s   

