U
    QËáeÐG  ã                   @  sæ   d Z ddlm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
mZmZ ddlmZ ddlmZmZ ddlmZ e
r¬dd	l	mZ dd
lmZ ddlmZ ddlmZ e e¡Ze d¡ZdZdddœdd„Z G dd„ dƒZ!dS )z7
The httplib2 algorithms ported for use with requests.
é    )ÚannotationsN)Úparsedate_tz)ÚTYPE_CHECKINGÚ
CollectionÚMapping)ÚCaseInsensitiveDict)Ú	DictCacheÚSeparateBodyBaseCache)Ú
Serializer)ÚLiteral)ÚPreparedRequest)ÚHTTPResponse)Ú	BaseCachez9^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)é-  é4  Ústrztuple[str, str, str, str, str]©ÚuriÚreturnc                 C  s@   t  | ¡}|dk	st‚| ¡ }|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)
    Né   é   é   é   é   )ÚURIÚmatchÚAssertionErrorÚgroups)r   r   r   © r   úY/var/www/html/htmlvenv/lib/python3.8/site-packages/pip/_vendor/cachecontrol/controller.pyÚ	parse_uri%   s    
r    c                   @  sÒ   e Zd ZdZd.dddddœd	d
„Zedddœdd„ƒZedddœdd„ƒZdddœdd„Zdddœdd„Z	dddœdd„Z
dddœdd „Zd/ddd!d"d#d$d%œd&d'„Zd0dd!d"dd$d(œd)d*„Zdd!d!d+œd,d-„ZdS )1ÚCacheControllerz4An interface to see if request should cached or not.NTzBaseCache | NoneÚboolzSerializer | NonezCollection[int] | None)ÚcacheÚcache_etagsÚ
serializerÚstatus_codesc                 C  s4   |d krt ƒ n|| _|| _|p"tƒ | _|p,d| _d S )N)éÈ   éË   i,  r   r   )r   r#   r$   r
   r%   Úcacheable_status_codes)Úselfr#   r$   r%   r&   r   r   r   Ú__init__3   s    zCacheController.__init__r   r   c           	      C  sh   t |ƒ\}}}}}|r|s&td| ƒ‚| ¡ }| ¡ }|s>d}|rPd ||g¡pR|}|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_uriZ
defrag_urir   r   r   Ú_urlnorm?   s    zCacheController._urlnormc                 C  s
   |   |¡S )N)r8   )r1   r   r   r   r   Ú	cache_urlS   s    zCacheController.cache_urlzMapping[str, str]zdict[str, int | None])Úheadersr   c           
      C  s(  t dft dft dfddddddddt dfdœ}| d| dd¡¡}i }| d¡D ]Ò}| ¡ s^qP| d	d
¡}|d  ¡ }z|| \}}	W n$ tk
rª   t d|¡ Y qPY nX |r´|	s¼d ||< |rPz||d
  ¡ ƒ||< W qP tk
rü   |	røt d|¡ Y qP tk
r    t d||j	¡ Y qPX qP|S )NTF)NF)úmax-agez	max-staleú	min-freshúno-cacheúno-storezno-transformzonly-if-cachedzmust-revalidateÚpublicÚ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)
ÚintÚgetÚsplitÚstripÚKeyErrorÚloggerÚdebugÚ
IndexErrorÚ
ValueErrorÚ__name__)
r*   r:   Zknown_directivesZ
cc_headersÚretvalZcc_directiveÚpartsZ	directiveÚtypÚrequiredr   r   r   Úparse_cache_controlW   sV    ó
þýz#CacheController.parse_cache_controlr   zHTTPResponse | None)Úrequestr   c                 C  sx   |j }|dk	st‚| j |¡}|dkr4t d¡ dS t| jtƒrN| j |¡}nd}| j	 
|||¡}|dkrtt d¡ |S )zO
        Load a cached response, or return None if it's not available.
        NzNo cache entry availablez1Cache entry deserialization failed, entry ignored)Úurlr   r#   rE   rI   rJ   Ú
isinstancer	   Úget_bodyr%   ÚloadsÚwarning)r*   rS   r9   Z
cache_dataZ	body_fileÚresultr   r   r   Ú_load_from_cache   s    

z CacheController._load_from_cachezHTTPResponse | Literal[False]c                 C  s@  |j dk	st‚|  |j ¡}t d|¡ |  |j¡}d|krHt d¡ dS d|krj|d dkrjt d¡ dS |  |¡}|s|dS t|j	ƒt
krœd	}t |¡ |S t|jƒ}|r²d
|krÞd|krÐt d¡ | j |¡ t d¡ dS t ¡ }t|d
 ƒ}|dk	sþt‚t |dd… ¡}	td||	 ƒ}
t d|
¡ |  |¡}d}| d¡}|dk	r^|}t d|¡ nLd|krªt|d ƒ}|dk	rªt |dd… ¡|	 }td|ƒ}t d|¡ | d¡}|dk	rÎ|}t d|¡ | d¡}|dk	rö|
|7 }
t d|
¡ ||
krt d¡ t d||
¡ |S d|kr<t d¡ | j |¡ dS )ze
        Return a cached response if it exists in the cache, otherwise
        return False.
        NzLooking up "%s" in the cacher=   z-Request header has "no-cache", cache bypassedFr;   r   z1Request header has "max_age" as 0, cache bypassedzQReturning cached permanent redirect response (ignoring date and etag information)ÚdateÚetagz(Purging cached response: no date or etagz!Ignoring cached response: no dater   zCurrent age based on date: %iz#Freshness lifetime from max-age: %iÚexpiresz#Freshness lifetime from expires: %iz+Freshness lifetime from request max-age: %ir<   z'Adjusted current age from min-fresh: %iz2The response is "fresh", returning cached responsez%i > %iz4The cached response is "stale" with no etag, purging)rT   r   r9   rI   rJ   rR   r:   rZ   rD   ÚstatusÚPERMANENT_REDIRECT_STATUSESr   r#   ÚdeleteÚtimer   ÚcalendarÚtimegmÚmaxrE   )r*   rS   r9   ÚccÚrespÚmsgr:   ÚnowÚ
time_tupler[   Zcurrent_ageZresp_ccZfreshness_lifetimeÚmax_ager]   Zexpire_timeZ	min_freshr   r   r   Úcached_request¢   s|    


ÿ











 ÿ





zCacheController.cached_requestzdict[str, str]c                 C  sH   |   |¡}i }|rDt|jƒ}d|kr0|d |d< d|krD|d |d< |S )Nr\   ZETagzIf-None-Matchzlast-modifiedzLast-ModifiedzIf-Modified-Since)rZ   r   r:   )r*   rS   rf   Znew_headersr:   r   r   r   Úconditional_headers  s    

z#CacheController.conditional_headersr   zbytes | Nonez
int | NoneÚNone)r9   rS   ÚresponseÚbodyÚexpires_timer   c                 C  sd   t | jtƒrB| jj|| j ||d¡|d |dk	r`| j ||¡ n| jj|| j |||¡|d dS )z.
        Store the data in the cache.
        ó    )r]   N)rU   r#   r	   Úsetr%   ÚdumpsÚset_body)r*   r9   rS   rn   ro   rp   r   r   r   Ú
_cache_set  s    ýýzCacheController._cache_set)rS   rn   ro   r&   r   c                 C  sø  |p| j }|j|kr(t d|j|¡ dS t|jƒ}d|krft|d ƒ}|dk	sRt‚t 	|dd… ¡}nd}|dk	ržd|krž|d  
¡ ržt|d ƒt|ƒkrždS |  |j¡}	|  |¡}
|jdk	sÂt‚|  |j¡}t d|¡ d}d	|
krôd
}t d¡ d	|	krd
}t d¡ |r6| j |¡r6t d¡ | j |¡ |r@dS d| dd¡kr`t d¡ dS | jrêd|krêd}| d¡r®t|d ƒ}|dk	r®t 	|dd… ¡| }t|dƒ}t d|› d¡ t d¡ |  |||||¡ n
t|jƒtkrt d¡ |  |||d¡ nÞd|krôt|d ƒ}|dk	s:t‚t 	|dd… ¡}|
 d¡}|dk	rŒ|dkrŒt d¡ |}|  |||||¡ nhd|krô|d rôt|d ƒ}|dk	rÎt 	|dd… ¡| }nd}t d |¡¡ |  |||||¡ dS )zc
        Algorithm for caching requests.

        This assumes a requests Response object.
        zStatus code %s not in %sNr[   r   r   úcontent-lengthz&Updating cache with response from "%s"Fr>   TzResponse header has "no-store"zRequest header has "no-store"z0Purging existing cache entry to honor "no-store"Ú*ZvaryrA   zResponse header has "Vary: *"r\   r]   i u zetag object cached for z secondszCaching due to etagzCaching permanent redirectrq   r;   z'Caching b/c date exists and max-age > 0z4Caching b/c of expires header. expires in {} seconds)r)   r^   rI   rJ   r   r:   r   r   rb   rc   ÚisdigitrD   ÚlenrR   rT   r9   r#   rE   r`   r$   rd   ru   r_   Úformat)r*   rS   rn   ro   r&   r)   Zresponse_headersri   r[   Zcc_reqre   r9   Zno_storerp   r]   rj   r   r   r   Úcache_response=  s¶    

  ÿÿÿþ
ýü












û



ÿÿûzCacheController.cache_response)rS   rn   r   c                   sj   |j dk	st‚|  |j ¡}|  |¡}|s,|S dg‰ |j ‡ fdd„|j ¡ D ƒ¡ d|_|  |||¡ |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.
        Nrv   c                   s"   i | ]\}}|  ¡ ˆ kr||“qS r   )r/   )Ú.0ÚkÚv©Zexcluded_headersr   r   Ú
<dictcomp>á  s   þ z:CacheController.update_cached_response.<locals>.<dictcomp>r'   )	rT   r   r9   rZ   r:   ÚupdateÚitemsr^   ru   )r*   rS   rn   r9   Úcached_responser   r   r   Úupdate_cached_responseÆ  s    	
	
þÿ	z&CacheController.update_cached_response)NTNN)NN)NN)rM   Ú
__module__Ú__qualname__Ú__doc__r+   Úclassmethodr8   r9   rR   rZ   rk   rl   ru   r{   r„   r   r   r   r   r!   0   s,       û6n  ú"  û 
r!   )"r‡   Ú
__future__r   rb   ÚloggingÚrera   Úemail.utilsr   Útypingr   r   r   Úpip._vendor.requests.structuresr   Úpip._vendor.cachecontrol.cacher   r	   Ú"pip._vendor.cachecontrol.serializer
   r   Úpip._vendor.requestsr   Úpip._vendor.urllib3r   r   Ú	getLoggerrM   rI   Úcompiler   r_   r    r!   r   r   r   r   Ú<module>   s(   

