
    \Zi$                       S r SSKJr  SSKrSSKrSSKrSSKrSSKJr  SSK	J
r
  SSKrSSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJrJrJrJrJrJ r   \
(       a  SSK!r!SSK"J#r#  SSKJ$r$  \RJ                  " \&5      r'S r(\S 5       r)SS jr*  S       SS jjr+S S jr, " S S\-5      r.          S!S jr/ " S S\5      r0g)"zZstd interface for repodata.    )annotationsN)contextmanager)TYPE_CHECKING)	HTTPError   )REPODATA_FN)context)json)mask_anaconda_token   )disable_ssl_verify_warning)get_session   )URL_KEYRepodataOnDiskRepodataStateRepoInterfaceResponse304ContentUnchangedconda_http_errors)Session)RepodataCachec                0    [         R                  " SX5      $ )zChange file extension in URL.z(\.\w+)$)resub)urlexts     <lib/python3.13/site-packages/conda/gateways/repodata/zstd.pywithextr   )   s    66+s((    c              #     #    [         R                  " 5       nSv   [         R                  " 5       n[        R                  SXU-
  5        g7f)z&Context manager for timing operations.Nz%sTook %0.02fs)time	monotoniclogdebug)messagebeginends      r   timemer(   .   s5      NNE	
..
CIIu5s   A	Ac                l    0 nU R                  5       (       a  UR                  S5      nU(       a  X2S'   U$ )z+Build caching headers for a path and state._etagzif-none-match)existsget)	json_pathstateheadersetags       r   build_headersr1   7   s4    Gyy!'+O$Nr   c                0   Uc  UnU=(       d
    [        5       n[        X5      n[        R                  [        R                  4nUR                  U SXvS9n[        R                  SXR                  5        UR                  5         Sn	UR                  S:X  a  U(       a5  [        R                  " 5       n
U
R                  UR                  S5      SS9nOUR                  S5      nU nUR                  S	S
9 H  nUR!                  U5        M     SSS5        UR"                  (       aC   [%        UR                  S   5      n	[        R-                  SXR"                  R                  5        U$ ! , (       d  f       Nd= f! [&        [(        [*        4 a     NTf = f)zDownload url to dest_path, optionally decompressing zstd.

json_path: Path of old cached data (ignore etag if not exists).
dest_path: Path to write new data.
NT)streamtimeoutr/   z%s %sr      wb)closefdi @  )
chunk_sizezContent-LengthzDownload %d bytes %r)r   r1   r	   remote_connect_timeout_secsremote_read_timeout_secsr,   r#   r$   r/   raise_for_statusstatus_code	zstandardZstdDecompressorstream_writeropeniter_contentwriterequestintKeyError
ValueErrorAttributeErrorinfo)r   r-   sessionr.   is_zst	dest_pathr/   r4   responselengthdecompressorwriterrepodatablocks                 r   download_repodatarR   A   s`    	$]_EI-G1173S3SSG{{3tW{NHIIgs,,-Fs"$557L!//t$ 0 F
 ^^D)Fx!..'.Bu% C  	))*:;<F 	'1A1A1I1IJO V *n5 		s   &(E,(E= ,
E:=FFc                    U R                   c  gU R                   R                  nSUs=:*  =(       a    S:  Os  =(       a    US:g  $ )z4Determine if HTTP error is a 4xx error (except 416).Fi  i  i  )rL   r<   )er<   s     r   _is_http_error_most_400_codesrU   l   s;    zz**((K+###:s(::r   c                      \ rS rSrSrSrg)ZstSkipt   z#Exception to skip zst format check. N)__name__
__module____qualname____firstlineno____doc____static_attributes__rY   r   r   rW   rW   t   s    -r   rW   c                  UR                   nSn[        SU  S35          [        [        U S5      UUUUSS9nSSS5        WR                  R                  S5      US'   UR                  R                  S5      US'   UR                  R                  S5      US'   UR                  S:X  a
  [!        5       eUR                  S:X  aW  U(       a  gUR#                  S5       n	[$        R&                  " U	R)                  5       R+                  S5      5      n
SSS5        U
$ g! [        [
        R                  4 a  n[        U[
        R                  5      (       a*  [        R                  S[        [        U S5      5      U5        [        U[        5      (       a  [        U5      (       d  e UR                  SS5        Sn[        [        U S	5      UUUUS
9n SnAGNSnAff = f! , (       d  f       GN= f! , (       d  f       W
$ = f)a  
Download .json.zst file and return parsed JSON.

Args:
    url: URL to download from
    state: Repodata state
    session: Session object
    cache: Repodata cache
    temp_path: Temporary path to write json to
Returns:
    dict | None: Parsed JSON or None if error
FzDownload complete  z	.json.zstT)rI   r.   rK   rJ   z9Could not decompress %s as zstd. Fall back to .json. (%s)zstz.json)rI   r.   rK   Nzlast-modified_modr0   r*   zcache-control_cache_controli0  r5   rbzutf-8)cache_path_jsonr(   rR   r   r   r=   	ZstdError
isinstancer#   warningr   rU   set_has_formatr/   r,   r<   r   r@   r
   loadsreaddecode)r   r.   rI   cache	temp_pathr-   is_fallbackrL   rT   frepodata_jsons              r   request_url_zstd_staters   x   s   ( %%IK	$SE+	,	([)#H 
-B $$((9E&M%%))&1E'N&..22?CE
 s")++ s"  ^^D!Q JJqvvxw'?@M "  Y 9../ 	!Y0011O'[(AB
 !Y''0Ma0P0P   .K(W%#H	 
-	,b "! s;   GD4G0G6BGGGG
G-0
G?c                  L    \ rS rSr        SS jrS	S jrS
S jrSS jrSrg)ZstdRepoInterface   c                  [         R                  SU R                  R                  5        X0l        Xl        U=(       d    [        U l        [        R                  " [        5      U l
        [        R                  " S5      U l        g )NzUsing %szconda.stderrlog)r#   r$   	__class__rZ   _cache_urlr   _repodata_fnlogging	getLogger_log
_stderrlog)selfr   repodata_fnrn   kwargss        r   __init__ZstdRepoInterface.__init__   sX     			*dnn556	'6;%%h/	!++,=>r   c                8    U R                  U5        [        5       e)zL
Fetch newest repodata if necessary.

Always writes to ``cache_path_json``.
)repodata_parsedr   r   r.   s     r   rP   ZstdRepoInterface.repodata   s     	U#r   c           	        [        U R                  5      n[        R                  (       d
  [	        5         U R                   SU R
                   3nU R                  U5      nU R                  R                  U R                  R                   S[        R                  " S5      R                  5        S3-  n [        U R                  U R
                  5         [        UUUU R                  US9nUR                  U5        U R                  U[         '   U R                  R"                  R                  U5        SSS5        UR%                  5       (       a  U R                  R'                  U5         UR+                  5         Wc
  [/        5       eU$ ! , (       d  f       N^= f! [(         a    e f = f! [,         a     N;f = f!  UR+                  5         f ! [,         a     f f = f= f)z
Use this to avoid a redundant parse when repodata is updated.

When repodata is not updated, it doesn't matter whether this function or
the caller reads from a file.
/.r   z.tmp)rI   rn   ro   N)r   rz   r	   
ssl_verifyr   r{   _repodata_state_copyry   	cache_dirnameosurandomhexr   rs   updater   r.   r+   replacer   unlinkOSErrorr   )r   r.   rI   repodata_urlstate_ro   repodata_json_or_nones          r   r   !ZstdRepoInterface.repodata_parsed   s    dii(!!&())Ad&7&7%89 **51
 KK!!t{{'7'7&8"**Q-:K:K:M9Nd$SS 		"499d.?.?@(> #++')% V$!%g!!((/! A$ !!##I.  " !( ""((E A@( + 		    " sg   7 F! A!F88F! 1F0 
FF! !F--G  0
F=<F= G#GG#
G G#G  G#c                   [        U[        5      (       a3  [        UR                  UR                  UR                  [        U5      S9$ [        U R                  R                  U R                  R                  U R                  US9$ )z<Create a copy of state to avoid modifying the caller's dict.)rf   cache_path_stater   dict)rh   r   rf   r   r   r   ry   r{   r   s     r   r   &ZstdRepoInterface._repodata_state_copy   ss    e]++  % 5 5!&!7!7!--%[	  ! $ ; ;!%!=!= --	 r   )ry   r~   r{   r   rz   N)r   strr   
str | Nonern   r   returnNone)r.   dict | RepodataStater   r   )r.   r   r   dict | None)r.   r   r   r   )	rZ   r[   r\   r]   r   rP   r   r   r_   rY   r   r   ru   ru      s=    ??  ?
 ? 
?$9)vr   ru   )r-   pathlib.Pathr.   r   )FN)r-   r   rI   r   r.   zRepodataState | NonerK   zpathlib.Path | None)rT   r   r   bool)
r.   r   rI   r   rn   r   ro   r   r   r   )1r^   
__future__r   r|   r   r   r!   
contextlibr   typingr   r=   requestsr   base.constantsr   base.contextr	   common.serializer
   
common.urlr   connection.downloadr   connection.sessionr    r   r   r   r   r   r   pathlib
connectionr   r   r}   rZ   r#   r   r(   r1   rR   rU   	ExceptionrW   rs   ru   rY   r   r   <module>r      s   # "  	 	  %     ) # $ - < ,  $!)
 6 6 %)(( (  	( #(V;.i .NN 	N
 N N Nbf fr   