
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
ÝPfà2  ã               @   s„   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m
Z
 ddlmZ ejeƒZejdƒZd	d
„ ZG dd„ deƒZdS )z7
The httplib2 algorithms ported for use with requests.
é    N)Úparsedate_tz)ÚCaseInsensitiveDicté   )Ú	DictCache)Ú
Serializerz9^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?c             C   s0   t j| ƒjƒ }|d |d |d |d |d fS )z‡Parses a URI using the regex given in Appendix B of RFC 3986.

        (scheme, authority, path, query, fragment) = parse_uri(uri)
    r   é   é   é   é   )ÚURIÚmatchÚgroups)Úurir   © r   ú /usr/lib/python3.6/controller.pyÚ	parse_uri   s    r   c               @   s\   e Zd ZdZddd„Zedd„ ƒZedd	„ ƒZd
d„ Zdd„ Z	dd„ Z
ddd„Zdd„ ZdS )ÚCacheControllerz9An interface to see if request should cached or not.
    NTc             C   s"   |pt ƒ | _|| _|ptƒ | _d S )N)r   ÚcacheÚcache_etagsr   Ú
serializer)Úselfr   r   r   r   r   r   Ú__init__!   s    zCacheController.__init__c       	      C   sl   t |ƒ\}}}}}| s| r*td| ƒ‚|jƒ }|jƒ }|sBd}|rTdj||gƒpV|}|d | | }|S )z4Normalize the URL to create a safe key for the cachez(Only absolute URIs are allowed. uri = %sú/ú?z://)r   Ú	ExceptionÚlowerÚjoin)	Úclsr   ÚschemeZ	authorityÚpathZqueryZfragmentZrequest_uriZ
defrag_urir   r   r   Ú_urlnorm&   s    zCacheController._urlnormc             C   s
   | j |ƒS )N)r    )r   r   r   r   r   Ú	cache_url:   s    zCacheController.cache_urlc             C   sV   i }d}d|krd}||krR|| j dƒ}dd„ |D ƒ}dd„ |D ƒ}t|| ƒ}|S )zz
        Parse the cache control headers returning a dictionary with values
        for the different directives.
        zcache-controlzCache-Controlú,c             S   s4   g | ],}d|j dƒkrtdd„ |jdd ƒD ƒƒ‘qS )r   ú=c             S   s   g | ]}|j ƒ jƒ ‘qS r   )Ústripr   )Ú.0Úxr   r   r   ú
<listcomp>L   s    zBCacheController.parse_cache_control.<locals>.<listcomp>.<listcomp>éÿÿÿÿ)ÚfindÚtupleÚsplit)r%   Úpartr   r   r   r'   L   s   z7CacheController.parse_cache_control.<locals>.<listcomp>c             S   s*   g | ]"}d|j dƒkr|jƒ jƒ d f‘qS )r   r#   r(   )r)   r$   r   )r%   Únamer   r   r   r'   P   s   )r+   Údict)r   ÚheadersZretvalZ	cc_headerÚpartsZparts_with_argsZparts_wo_argsr   r   r   Úparse_cache_control>   s    z#CacheController.parse_cache_controlc             C   sŽ  | j |jƒ}tjd|ƒ | j|jƒ}d|kr:tjdƒ dS d|kr\|d dkr\tjdƒ dS | jj|ƒ}|dkr~tjd	ƒ dS | jj	||ƒ}|sžtj
d
ƒ dS |jdkrºd}tj|ƒ |S t|jƒ}| sÔd|k�r d|kròtjdƒ | jj|ƒ tjdƒ dS tjƒ }tjt|d ƒƒ}	td||	 ƒ}
tjd|
ƒ | j|ƒ}d}d|k�rt|d jƒ �rtt|d ƒ}tjd|ƒ nDd|k�r¸t|d ƒ}|dk	�r¸tj|ƒ|	 }td|ƒ}tjd|ƒ d|k�rúyt|d ƒ}tjd|ƒ W n tk
�rø   d}Y nX d|k�rDyt|d ƒ}W n tk
�r.   d}Y nX |
|7 }
tjd|
ƒ ||
k�rjtjdƒ tjd||
ƒ |S d|k�rŠtjdƒ | jj|ƒ dS )ze
        Return a cached response if it exists in the cache, otherwise
        return False.
        zLooking up "%s" in the cachezno-cachez-Request header has "no-cache", cache bypassedFzmax-ager   z1Request header has "max_age" as 0, cache bypassedNzNo cache entry availablez1Cache entry deserialization failed, entry ignoredi-  zVReturning cached "301 Moved Permanently" response (ignoring date and etag information)ÚdateÚetagz(Purging cached response: no date or etagz!Ignoring cached response: no datezCurrent age based on date: %iz#Freshness lifetime from max-age: %iÚexpiresz#Freshness lifetime from expires: %iz+Freshness lifetime from request max-age: %iz	min-freshz'Adjusted current age from min-fresh: %iz2The response is "fresh", returning cached responsez%i > %iz4The cached response is "stale" with no etag, purging)r!   ÚurlÚloggerÚdebugr1   r/   r   Úgetr   ÚloadsZwarningÚstatusr   ÚdeleteÚtimeÚcalendarZtimegmr   ÚmaxÚisdigitÚintÚ
ValueError)r   Úrequestr!   ÚccZ
cache_dataÚrespÚmsgr/   Znowr2   Zcurrent_ageZresp_ccZfreshness_lifetimer4   Zexpire_timeZ	min_freshr   r   r   Úcached_requestV   sŒ    





















zCacheController.cached_requestc             C   s`   | j |jƒ}| jj|| jj|ƒƒ}i }|r\t|jƒ}d|krH|d |d< d|kr\|d |d< |S )Nr3   ZETagzIf-None-Matchzlast-modifiedzLast-ModifiedzIf-Modified-Since)r!   r5   r   r9   r   r8   r   r/   )r   rB   r!   rD   Znew_headersr/   r   r   r   Úconditional_headersÏ   s    
z#CacheController.conditional_headersc       
      C   sú  ddddg}|j |kr*tjd|j |ƒ dS t|jƒ}|dk	rhd|krh|d jƒ rht|d ƒt|ƒkrhdS | j|jƒ}| j|ƒ}| j	|j
ƒ}tjd|ƒ d	}	|jd
ƒr²d}	tjdƒ |jd
ƒrÊd}	tjdƒ |	rð| jj|ƒrðtjdƒ | jj|ƒ | joüd|k�r(tjdƒ | jj|| jj|||d�ƒ nÎ|j dk�rXtjdƒ | jj|| jj||ƒƒ nžd|k�rö|�r¼|jdƒ�r¼|d jƒ �röt|d ƒdk�rötjdƒ | jj|| jj|||d�ƒ n:d|k�rö|d �rötjdƒ | jj|| jj|||d�ƒ dS )zc
        Algorithm for caching requests.

        This assumes a requests Response object.
        éÈ   éË   i,  i-  zStatus code %s not in %sNzcontent-lengthz&Updating cache with response from "%s"Fzno-storeTzResponse header has "no-store"zRequest header has "no-store"z0Purging existing cache entry to honor "no-store"r3   zCaching due to etag)ÚbodyzCaching permanant redirectr2   zmax-ager   z'Caching b/c date exists and max-age > 0r4   zCaching b/c of expires header)r:   r6   r7   r   r/   r?   r@   Úlenr1   r!   r5   r8   r   r;   r   Úsetr   Údumps)
r   rB   ÚresponserJ   Zcacheable_status_codesZresponse_headersZcc_reqrC   r!   Zno_storer   r   r   Úcache_responseß   sd    










 



zCacheController.cache_responsec                sv   | j |jƒ}| jj|| jj|ƒƒ}|s*|S dg‰ |jjt‡ fdd„|jj	ƒ D ƒƒƒ d|_
| jj|| jj||ƒƒ |S )zéOn a 304 we will get a new set of headers that we want to
        update our cached value with, assuming we have one.

        This should only ever be called when we've sent an ETag and
        gotten a 304 as the response.
        zcontent-lengthc             3   s&   | ]\}}|j ƒ ˆ kr||fV  qd S )N)r   )r%   ÚkÚv)Úexcluded_headersr   r   ú	<genexpr>T  s    z9CacheController.update_cached_response.<locals>.<genexpr>rH   )r!   r5   r   r9   r   r8   r/   Úupdater.   Úitemsr:   rL   rM   )r   rB   rN   r!   Zcached_responser   )rR   r   Úupdate_cached_response6  s    
z&CacheController.update_cached_response)NTN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úclassmethodr    r!   r1   rF   rG   rO   rV   r   r   r   r   r      s   
y
Wr   )rZ   ZloggingÚrer=   r<   Zemail.utilsr   Zpip._vendor.requests.structuresr   r   r   Z	serializer   Z	getLoggerrW   r6   Úcompiler   r   Úobjectr   r   r   r   r   Ú<module>   s   

	