3 �Pf�2�@s�dZddlZddlZddlZddlZddlmZddlmZddl m Z ddl m Z ej e�Zejd�Zd d �ZGd d �d e�ZdS) z7 The httplib2 algorithms ported for use with requests. �N)� parsedate_tz)�CaseInsensitiveDict�)� DictCache)� Serializerz9^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?cCs0tj|�j�}|d|d|d|d|dfS)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_urisrc@s\eZdZdZddd�Zedd��Zedd ��Zd d �Zd d �Z dd�Z ddd�Z dd�Z dS)�CacheControllerz9An interface to see if request should cached or not. NTcCs"|pt�|_||_|pt�|_dS)N)r�cache� cache_etagsr� serializer)�selfrrrrrr�__init__!s zCacheController.__init__c Cslt|�\}}}}}| s| r*td|��|j�}|j�}|sBd}|rTdj||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�pathZqueryZfragmentZ request_uriZ defrag_urirrr�_urlnorm&s  zCacheController._urlnormcCs |j|�S)N)r )rrrrr� cache_url:szCacheController.cache_urlcCsVi}d}d|krd}||krR||jd�}dd�|D�}dd�|D�}t||�}|S)zz Parse the cache control headers returning a dictionary with values for the different directives. z cache-controlz Cache-Control�,cSs4g|],}d|jd�krtdd�|jdd�D���qS)r�=cSsg|]}|j�j��qSr)�stripr)�.0�xrrr� LszBCacheController.parse_cache_control...�����)�find�tuple�split)r%�partrrrr'Lsz7CacheController.parse_cache_control..cSs*g|]"}d|jd�kr|j�j�df�qS)rr#r()r)r$r)r%�namerrrr'Ps)r+�dict)r�headersZretvalZ cc_header�partsZparts_with_argsZ parts_wo_argsrrr�parse_cache_control>s z#CacheController.parse_cache_controlcCs�|j|j�}tjd|�|j|j�}d|kr:tjd�dSd|kr\|ddkr\tjd�dS|jj|�}|dkr~tjd �dS|jj ||�}|s�tj d �dS|j d kr�d }tj|�|St |j�}| s�d |k�rd|kr�tjd�|jj |�tjd�dStj�}tjt|d ��} td|| �} tjd| �|j|�} d} d| k�rt| dj��rtt| d�} tjd| �nDd|k�r�t|d�} | dk �r�tj| �| }td|�} tjd| �d|k�r�yt|d�} tjd| �Wntk �r�d} YnXd|k�rDyt|d�}Wntk �r.d}YnX| |7} tjd| �| | k�rjtjd�tjd| | �|Sd|k�r�tjd�|jj |�dS)ze Return a cached response if it exists in the cache, otherwise return False. zLooking up "%s" in the cachezno-cachez-Request header has "no-cache", cache bypassedFzmax-agerz1Request header has "max_age" as 0, cache bypassedNzNo 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 datezCurrent 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�debugr1r/r�getr�loadsZwarning�statusr�delete�time�calendarZtimegmr�max�isdigit�int� ValueError)r�requestr!�ccZ cache_data�resp�msgr/Znowr2Z current_ageZresp_ccZfreshness_lifetimer4Z expire_timeZ min_freshrrr�cached_requestVs�                               zCacheController.cached_requestcCs`|j|j�}|jj||jj|��}i}|r\t|j�}d|krH|d|d<d|kr\|d|d<|S)Nr3ZETagz If-None-Matchz last-modifiedz Last-ModifiedzIf-Modified-Since)r!r5rr9rr8rr/)rrBr!rDZ new_headersr/rrr�conditional_headers�s    z#CacheController.conditional_headersc Cs�ddddg}|j|kr*tjd|j|�dSt|j�}|dk rhd|krh|dj�rht|d�t|�krhdS|j|j�}|j|�}|j |j �}tjd|�d } |j d �r�d } tjd �|j d �r�d } tjd �| r�|j j |�r�tjd�|j j |�|jo�d|k�r(tjd�|j j||jj|||d��n�|jdk�rXtjd�|j j||jj||��n�d|k�r�|�r�|j d��r�|dj��r�t|d�dk�r�tjd�|j j||jj|||d��n:d|k�r�|d�r�tjd�|j j||jj|||d��dS)zc Algorithm for caching requests. This assumes a requests Response object. ����i,i-zStatus code %s not in %sNzcontent-lengthz&Updating cache with response from "%s"Fzno-storeTzResponse header has "no-store"zRequest header has "no-store"z0Purging existing cache entry to honor "no-store"r3zCaching due to etag)�bodyzCaching permanant redirectr2zmax-agerz'Caching b/c date exists and max-age > 0r4zCaching b/c of expires header)r:r6r7rr/r?r@�lenr1r!r5r8rr;r�setr�dumps) rrB�responserJZcacheable_status_codesZresponse_headersZcc_reqrCr!Zno_storerrr�cache_response�sd                       zCacheController.cache_responsecsv|j|j�}|jj||jj|��}|s*|Sdg�|jjt�fdd�|jj �D���d|_ |jj ||jj ||��|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. zcontent-lengthc3s&|]\}}|j��kr||fVqdS)N)r)r%�k�v)�excluded_headersrr� Tsz9CacheController.update_cached_response..rH) r!r5rr9rr8r/�updater.�itemsr:rLrM)rrBrNr!Zcached_responser)rRr�update_cached_response6s  z&CacheController.update_cached_response)NTN)N) �__name__� __module__� __qualname__�__doc__r� classmethodr r!r1rFrGrOrVrrrrrs   y Wr)rZZlogging�rer=r<Z email.utilsrZpip._vendor.requests.structuresrrrZ serializerZ getLoggerrWr6�compiler r�objectrrrrr�s