ó
^†êWc           @   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	 „  Z d
 e f d „  ƒ  YZ d S(   s7   
The httplib2 algorithms ported for use with requests.
iÿÿÿÿN(   t   parsedate_tz(   t   CaseInsensitiveDicti   (   t	   DictCache(   t
   Serializers9   ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?c         C   s<   t  j |  ƒ j ƒ  } | d | d | d | d | d f S(   s‡   Parses a URI using the regex given in Appendix B of RFC 3986.

        (scheme, authority, path, query, fragment) = parse_uri(uri)
    i   i   i   i   i   (   t   URIt   matcht   groups(   t   uriR   (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt	   parse_uri   s    t   CacheControllerc           B   sn   e  Z d  Z d	 e d	 d „ Z e d „  ƒ Z e d „  ƒ Z d „  Z	 d „  Z
 d „  Z d	 d „ Z d „  Z RS(
   s9   An interface to see if request should cached or not.
    c         C   s1   | p t  ƒ  |  _ | |  _ | p' t ƒ  |  _ d  S(   N(   R   t   cachet   cache_etagsR   t
   serializer(   t   selfR
   R   R   (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   __init__!   s    	c   	      C   sš   t  | ƒ \ } } } } } | s) | r< t d | ƒ ‚ n  | j ƒ  } | j ƒ  } | sc d } n  | r~ d j | | g ƒ p | } | d | | } | S(   s4   Normalize the URL to create a safe key for the caches(   Only absolute URIs are allowed. uri = %st   /t   ?s   ://(   R   t	   Exceptiont   lowert   join(	   t   clsR   t   schemet	   authorityt   patht   queryt   fragmentt   request_urit
   defrag_uri(    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   _urlnorm&   s    	!c         C   s   |  j  | ƒ S(   N(   R   (   R   R   (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt	   cache_url:   s    c   
      C   sö   i  } d } d | k r! d } n  | | k rò | | j  d ƒ } g  | D]R } d | j d ƒ k rG t g  | j  d d ƒ D] } | j ƒ  j ƒ  ^ qx ƒ ^ qG } g  | D]3 } d | j d ƒ k r¦ | j ƒ  j ƒ  d f ^ q¦ }	 t | |	 ƒ } n  | S(   sz   
        Parse the cache control headers returning a dictionary with values
        for the different directives.
        s   cache-controls   Cache-Controlt   ,iÿÿÿÿt   =i   (   t   splitt   findt   tuplet   stripR   t   dict(
   R   t   headerst   retvalt	   cc_headert   partst   partt   xt   parts_with_argst   namet   parts_wo_args(    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   parse_cache_control>   s    	\=c         C   s^  |  j  | j ƒ } t j d | ƒ |  j | j ƒ } d | k rQ t j d ƒ t Sd | k r~ | d d k r~ t j d ƒ t S|  j j | ƒ } | d k r­ t j d ƒ t S|  j
 j | | ƒ } | sÙ t j d ƒ t 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 ƒ t 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 } q§Xn  d | k rþy t | d ƒ } Wn t k
 ràd } n X|
 | 7}
 t j d |
 ƒ n  | |
 k r.t j d ƒ t j d | |
 ƒ | Sd | k rZt j d ƒ |  j j | ƒ n  t S(   se   
        Return a cached response if it exists in the cache, otherwise
        return False.
        s   Looking up "%s" in the caches   no-caches-   Request header has "no-cache", cache bypasseds   max-agei    s1   Request header has "max_age" as 0, cache bypasseds   No cache entry availables1   Cache entry deserialization failed, entry ignoredi-  sV   Returning cached "301 Moved Permanently" response (ignoring date and etag information)t   datet   etags(   Purging cached response: no date or etags!   Ignoring cached response: no dates   Current age based on date: %is#   Freshness lifetime from max-age: %it   expiress#   Freshness lifetime from expires: %is+   Freshness lifetime from request max-age: %is	   min-freshs'   Adjusted current age from min-fresh: %is2   The response is "fresh", returning cached responses   %i > %is4   The cached response is "stale" with no etag, purgingN(   R   t   urlt   loggert   debugR.   R%   t   FalseR
   t   gett   NoneR   t   loadst   warningt   statusR   t   deletet   timet   calendart   timegmR    t   maxt   isdigitt   intt
   ValueError(   R   t   requestR   t   cct
   cache_datat   respt   msgR%   t   nowR/   t   current_aget   resp_cct   freshness_lifetimeR1   t   expire_timet	   min_fresh(    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   cached_requestV   sŒ    
	
		

	
c         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(   NR0   t   ETags   If-None-Matchs   last-modifieds   Last-Modifieds   If-Modified-Since(   R   R2   R   R8   R
   R6   R   R%   (   R   RC   R   RF   t   new_headersR%   (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   conditional_headersÏ   s    !c   
      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 | ƒ t }	 | j d	 ƒ r t }	 t j d
 ƒ n  | j d	 ƒ r%t }	 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(   sc   
        Algorithm for caching requests.

        This assumes a requests Response object.
        iÈ   iË   i,  i-  s   Status code %s not in %sNs   content-lengths&   Updating cache with response from "%s"s   no-stores   Response header has "no-store"s   Request header has "no-store"s0   Purging existing cache entry to honor "no-store"R0   s   Caching due to etagt   bodys   Caching permanant redirectR/   s   max-agei    s'   Caching b/c date exists and max-age > 0R1   s   Caching b/c of expires header(   R:   R3   R4   R   R%   R7   R@   RA   t   lenR.   R   R2   R5   R6   t   TrueR
   R;   R   t   setR   t   dumps(
   R   RC   t   responseRR   t   cacheable_status_codest   response_headerst   cc_reqRD   R   t   no_store(    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   cache_responseß   sd    			"
	c            s¤   |  j  | j ƒ } |  j j | |  j j | ƒ ƒ } | s= | Sd g ‰  | j j t ‡  f d †  | j j	 ƒ  Dƒ ƒ ƒ d | _
 |  j j | |  j j | | ƒ ƒ | S(   sé   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.
        s   content-lengthc         3   s3   |  ]) \ } } | j  ƒ  ˆ  k r | | f Vq d  S(   N(   R   (   t   .0t   kt   v(   t   excluded_headers(    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pys	   <genexpr>T  s    	iÈ   (   R   R2   R   R8   R
   R6   R%   t   updateR$   t   itemsR:   RU   RV   (   R   RC   RW   R   t   cached_response(    (   R`   st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   update_cached_response6  s    	
		&		N(   t   __name__t
   __module__t   __doc__R7   RT   R   t   classmethodR   R   R.   RN   RQ   R\   Rd   (    (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyR	      s   		y	W(   Rg   t   loggingt   reR=   R<   t   email.utilsR    t   pip._vendor.requests.structuresR   R
   R   t	   serializeR   t	   getLoggerRe   R3   t   compileR   R   t   objectR	   (    (    (    st   /private/var/folders/3n/6h2rwf155rn1m71wwyxn79n80000gn/T/pip-build-IcAT_k/pip/pip/_vendor/cachecontrol/controller.pyt   <module>   s   		