3
ûâdeE7  ã               @   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   úB/tmp/pip-build-red6nood/pip/pip/_vendor/cachecontrol/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   s4   |d krt ƒ n|| _|| _|p"tƒ | _|p,d| _d S )NéÈ   éË   é,  é-  )r   r   r   r   )r   ÚcacheÚcache_etagsr   Ú
serializerÚcacheable_status_codes)Úselfr   r   r   Ústatus_codesr   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   ÚschemeÚ	authorityÚpathÚqueryÚfragmentÚrequest_uriÚ
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   s2  t dft dft dfddddddddt dfdœ}|jd|jddƒƒ}i }xæ|jdƒD ]Ø}|jƒ s`qR|jdd	ƒ}|d
 jƒ }y|| \}}	W n" tk
rª   tjd|ƒ wRY nX | s¸|	 rÀd ||< |rRy||d	 jƒ ƒ||< W qR tk
�r   |	�r tjd|ƒ Y qR tk
�r(   tjd||j	ƒ Y qRX qRW |S )NTF)zmax-agez	max-stalez	min-freshzno-cachezno-storezno-transformzonly-if-cachedzmust-revalidateÚpublicZprivatezproxy-revalidatezs-maxagezcache-controlzCache-ControlÚ ú,ú=r   r   z,Ignoring unknown cache-control directive: %sz-Missing value for cache-control directive: %sz8Invalid value for cache-control directive %s, must be %s)NF)NF)NF)NF)NF)NF)NF)NF)
ÚintÚgetÚsplitÚstripÚKeyErrorÚloggerÚdebugÚ
IndexErrorÚ
ValueErrorÚ__name__)
r   ÚheadersZknown_directivesZ
cc_headersÚretvalZcc_directiveÚpartsZ	directiveÚtypÚrequiredr   r   r   Úparse_cache_controlB   sP    
z#CacheController.parse_cache_controlc             C   s4  | 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�rb|d }tjd|ƒ nDd|k�r¦t|d ƒ}|dk	�r¦tj|ƒ|	 }td|ƒ}tjd|ƒ d|k�rÄ|d }tjd|ƒ d|k�rê|d }|
|7 }
tjd|
ƒ ||
k�rtjdƒ tjd||
ƒ |S d|k�r0t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,   Úurlr6   r7   r@   r;   r   r2   r   ÚloadsÚwarningÚstatusr   ÚdeleteÚtimeÚcalendarÚtimegmr   Úmax)r   Úrequestr,   ÚccÚ
cache_dataÚrespÚmsgr;   ÚnowrA   Úcurrent_ageÚresp_ccÚfreshness_lifetimerC   Úexpire_timeÚ	min_freshr   r   r   Úcached_requestx   sv    




















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 )NrB   ÚETagzIf-None-Matchzlast-modifiedzLast-ModifiedzIf-Modified-Since)r,   rD   r   rE   r   r2   r   r;   )r   rM   r,   rP   Únew_headersr;   r   r   r   Úconditional_headersç   s    
z#CacheController.conditional_headersc             C   s  |p| j }|j|kr(tjd|j|ƒ dS t|jƒ}|dk	rfd|krf|d jƒ rft|d ƒt|ƒkrfdS | j	|jƒ}| j	|ƒ}| j
|jƒ}	tjd|	ƒ d}
d|kr®d}
tjdƒ d|krÄd}
tjd	ƒ |
rê| jj|	ƒrêtjd
ƒ | jj|	ƒ |
ròdS d|jddƒk�rtjdƒ dS | j�rLd|k�rLtjdƒ | jj|	| jj|||d�ƒ n´|jdk�r|tjdƒ | jj|	| jj||ƒƒ n„d|k�r d|k�rÆ|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.
        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"Ú*Úvaryr.   zResponse header has "Vary: *"rB   zCaching due to etag)Úbodyi-  zCaching permanant redirectrA   zmax-ager   z'Caching b/c date exists and max-age > 0rC   zCaching b/c of expires header)r   rG   r6   r7   r   r;   Úisdigitr1   Úlenr@   r,   rD   r   r2   rH   r   Úsetr   Údumps)r   rM   Úresponser^   r   r   Úresponse_headersÚcc_reqrN   r,   Úno_storer   r   r   Úcache_response÷   s^    














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!   )Ú.0ÚkÚv)Úexcluded_headersr   r   ú	<genexpr>l  s   z9CacheController.update_cached_response.<locals>.<genexpr>r   )r,   rD   r   rE   r   r2   r;   ÚupdateÚdictÚitemsrG   ra   rb   )r   rM   rc   r,   Úcached_responser   )rk   r   Úupdate_cached_responseR  s    	
z&CacheController.update_cached_response)NTNN)NN)r:   Ú
__module__Ú__qualname__Ú__doc__r   Úclassmethodr+   r,   r@   rX   r[   rg   rq   r   r   r   r   r      s   
6o
[r   )rt   ÚloggingÚrerJ   rI   Úemail.utilsr   Zpip._vendor.requests.structuresr   r   r   Ú	serializer   Ú	getLoggerr:   r6   Úcompiler   r   Úobjectr   r   r   r   r   Ú<module>   s   

	