3
LY2                 @   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 )zParses 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   v/private/var/folders/7d/20zwc49s3kn54d3vgq8bd4640000gn/T/pip-build-an2lx5zf/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   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   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   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   )r0   dict)r   headersretval	cc_headerpartsparts_with_args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	||}|stj
d
 dS |jdkrd}tj| |S t|j}| sd|kr d|krt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rt|d }|dk	rtj||	 }td|}tjd| d|kry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rt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debugr:   r4   r   getr   loadswarningstatusr   deletetimecalendartimegmr   maxisdigitint
ValueError)r   requestr&   cc
cache_datarespmsgr4   nowr;   current_ageresp_ccfreshness_lifetimer=   expire_time	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 )Nr<   ETagzIf-None-Matchzlast-modifiedzLast-ModifiedzIf-Modified-Since)r&   r>   r   rB   r   rA   r   r4   )r   rM   r&   rP   new_headersr4   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
rd}	tjd |jd
rd}	tjd |	r| jj|rtjd | jj| | jod|kr(tjd | jj|| jj|||d n|j dkrXtjd | jj|| jj|| nd|kr|r|jdr|d j rt|d dkrtjd | jj|| jj|||d n:d|kr|d rt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"r<   zCaching due to etag)bodyzCaching permanant redirectr;   zmax-ager   z'Caching b/c date exists and max-age > 0r=   zCaching b/c of expires header)rD   r?   r@   r   r4   rJ   rK   lenr:   r&   r>   rA   r   rE   r   setr   dumps)
r   rM   responser^   cacheable_status_codesresponse_headerscc_reqrN   r&   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 )zOn 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>r\   )r&   r>   r   rB   r   rA   r4   updater3   itemsrD   r`   ra   )r   rM   rb   r&   cached_responser   )rj   r   update_cached_response6  s    
z&CacheController.update_cached_response)NTN)N)__name__
__module____qualname____doc__r   classmethodr%   r&   r:   rX   r[   rg   ro   r   r   r   r   r      s   
y
Wr   )rs   loggingrerG   rF   email.utilsr   Zpip._vendor.requests.structuresr   r   r   	serializer   	getLoggerrp   r?   compiler   r   objectr   r   r   r   r   <module>   s   

	