
^V2                 @   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 Gd d   d e  Z d S)z7
The httplib2 algorithms ported for use with requests.
    N)parsedate_tz)CaseInsensitiveDict   )	DictCache)
Serializerz9^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?c             C   s<   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   B/tmp/pip-build-9m6vxulb/pip/pip/_vendor/cachecontrol/controller.py	parse_uri   s    r   c               @   s   e  Z d  Z d Z d d 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   s1   | 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   s   t  |  \ } } } } } | s) | r< t d |   n  | j   } | j   } | sc d } n  | r~ d j | | g  p | } | 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   s}   i  } d } d | k r! d } n  | | k ry | | j  d  } d d   | D } d d   | D } t | |  } n  | S)zz
        Parse the cache control headers returning a dictionary with values
        for the different directives.
        zcache-controlzCache-Control,c             S   sJ   g  |  ]@ } d | j  d  k r t d d   | j d d   D   q S)r   =c             S   s"   g  |  ] } | j    j    q Sr   )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  |  ]3 } 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 rQ t j d  d Sd | 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 |  | St | j  } | s!d | k r^d | k rMt j d  |  j j |  n  t j d  d St j   } t j t | d   }	 t d | |	  }
 t j d |
  |  j |  } d } d | k r| d j   rt | d  } t j d |  n` d | k rZt | d  } | d k	 rZt j |  |	 } t d |  } t j d |  qZn  d | k ry$ t | d  } t j d |  Wqt k
 rd } YqXn  d | k r y t | d  } Wn t k
 rd } Yn X|
 | 7}
 t j d |
  n  | |
 k r0t j d  t j d | |
  | Sd | k r\t j d  |  j j |  n  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 rk | d | d <n  d | k r | d | d <q n  | 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 St | j  } | d k	 r d | k r | d j   r t | d  t |  k r d S|  j | j  } |  j |  } |  j	 | j
  } t j d |  d	 }	 | j d
  r d }	 t j d  n  | j d
  r%d }	 t j d  n  |	 r]|  j j |  r]t j d  |  j j |  n  |  j rd | k rt j d  |  j j | |  j j | | d |  n| j  d k rt j d  |  j j | |  j j | |   n d | k r| r]| j d  r]t | d  d k rt j d  |  j j | |  j j | | d |  qqd | k r| d rt j d  |  j j | |  j j | | d |  qqn  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                s   |  j  | j  } |  j j | |  j j |   } | s= | Sd 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   s3   |  ]) \ } } | 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)__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   	