+
    :1j%                       R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	 ^ RI
HtHtHtHt ^ RIHt ^ RIHt ^ RIHt ]	'       d%   ^ R	IHtHt ^ R
IHt ^ RIHt ^ RIHtHt ]! R4      t]P>                  ! ] 4      t!]"! ]4      t#^
t$R R lt%RR R llt&R R lt'R R lt(]PR                  R R l4       t*RR R llt+R R lt,R t-R# )z
Miscellaneous utility functions for sharded repodata processing.

This module contains utility functions that don't fit cleanly into other modules:
- URL handling
- Package name parsing
- Data transformation helpers
- Threading utilities
)annotationsN)suppress)TYPE_CHECKING)urljoinurlparse
urlunparseuses_relative)context)InvalidMatchSpec)	MatchSpec)IteratorSequence)SimpleQueue)TypeVar)PackageRecordDict	ShardDict_Tc                   V ^8  d   QhRR/# )   returnint )formats   ":lib/python3.14/site-packages/conda/_private/shards/misc.py__annotate__r   ,   s     & &S &    c                 R    \         P                  e   \         P                  # \        # )a  
If context.repodata_threads is not set, find the size of the connection pool
in a typical https:// session. This should significantly reduce dropped
connections. We match requests' default 10.

Is this shared between all sessions? Or do we get a different pool for a
different get_session(url)?

Other adapters (file://, s3://) used in conda would have different
concurrency behavior;  we are not prepared to have separate threadpools per
connection type.
)r	   repodata_threadsSHARDS_CONNECTIONS_DEFAULTr   r   r   _shards_connectionsr   ,   s"     +'''%%r   c               $    V ^8  d   QhRRRRRR/# )r   base_urlstrrelative_urlr   r   )r   s   "r   r   r   >   s!     / /s /# /s /r   c                L   \        V 4      p\        V4      pVP                  \        9   d,   VP                  '       d   TpM\        \        W4      R4      pMVP                  '       d   TpMVP                  '       gr   VP                  '       d`   \	        VP                  RR7      4      p\        \        WQ4      R4      p\	        \        V4      P                  VP                  R7      4      pM\        \        W4      R4      pVP                  R4      '       g
   VR,          pV# )a  
Join base_url with relative_url, ensuring proper handling of all URL schemes.

Python's urllib.parse.urljoin only handles schemes registered in
``urllib.parse.uses_relative``. For unregistered schemes like ``s3://``,
it returns just ``"."`` instead of the resolved URL. This function falls
back to a scheme-swap workaround for those cases.

The result always ends with "/" to enable proper string concatenation with filenames.

See: https://github.com/conda/conda-libmamba-solver/issues/866
.https)scheme/)r   r'   _URLJOIN_SAFE_SCHEMESr   r   _replaceendswith)r!   r#   parsedrelative_parsedresulthttps_base_urljoined_httpss   &&     r   _safe_urljoin_with_slashr1   >   s     hF|,O }}-- !!!!F WX<cBF
 !!!!F '''FMMM'w(GHN"7>#H#NL 6 ? ?v}} ? UVF WX<cBF ??3#Mr   c                    V ^8  d   QhRRRR/# )r   status_codez	str | intr   boolr   )r   s   "r   r   r   p   s      y T r   c                x    \        V \        4      ;'       d$    RT u;8*  ;'       d    R8  Mu ;'       d    V R8g  # )zO
Determine whether the `HTTPError` is an HTTP 400 error code (except for 416).
i  i  i  )
isinstancer   )r3   s   &r   _is_http_error_most_400_codesr7   p   s6    
 	;$XX)A)Ac)AXXkUXFXr   c                   V ^8  d   QhRR/# )r   recordr   r   )r   s   "r   r   r   y   s      - r   c                    R FQ  pV P                  V4      ;p'       g   K  \        V\        4      '       d   K6  \        V4      P	                  4       W&   KS  	  V # )zA
Convert bytes checksums to hex; leave unchanged if already str.
)sha256md5)getr6   r"   byteshex)r9   	hash_type
hash_values   &  r   ensure_hex_hashrB   y   sO     %	I..:..j#..$)*$5$9$9$;! % Mr   c                    V ^8  d   QhRRRR/# )r   specr"   r   z
str | Noner   )r   s   "r   r   r      s      s z r   c                ~     \        V 4      P                  #   \         d    \        P	                  RT 4        R# i ; i)a%  
Given a dependency spec, return the package name, or None if the spec is
not parseable.

Uses conda's MatchSpec rather than libmambapy to avoid a hard dependency
on a solver backend. With @functools.cache the performance is equivalent
(benchmarked at ~10ms for 5000 unique specs either way).
z,Could not parse dependency spec %r; skippingN)r   namer
   logwarning)rD   s   &r   spec_to_package_namerI      s8    ### BDIs    !<<c                    V ^8  d   QhRRRR/# )r   repodatar   r   r   )r   s   "r   r   r      s      	 i r   c           	         V'       d   V # RpRp\        V4      pV P                  R/ 4      pV P                  R/ 4      p/ V CRVP                  4        UUu/ uF  w  rxVRV)   V 2V9  g   K  WxbK  	  upp/C# u uppi )z
Given repodata or a single shard, remove any .tar.bz2 packages that have a
.conda counterpart.

Return a shallow copy if use_only_tar_bz2==False, else unmodified input.
z.tar.bz2z.condapackageszpackages.condaN)lenr=   items)	rK   use_only_tar_bz2_tar_bz2_conda_len_tar_bz2legacy_packagesconda_packageskvs	   &&       r   filter_redundant_packagesrX      s     HFx=Lll:r2O\\"2B7N
'--/
/Nl]#$VH-^C AD/
 
s   A9
-A9
c                    V ^8  d   QhRRRR/# )r   in_queuezQueue[Sequence[_T] | None]r   zIterator[Sequence[_T]]r   )r   s   "r   r   r      s      (r   c              #    "   RpV'       d    V P                  ^R7      pVf   R#  \        T4      p\	        \        P                  4      ;_uu_ 4         T P                  4       pTf   RpMTP                  T4       K+  RRR4       Tx  K  R#   \        P                   d     K  i ; i  + '       g   i     L4; i5i)zF
Combine lists from in_queue until we see None. Yield combined lists.
T)timeoutNF)r=   queueEmptylistr   
get_nowaitextend)rZ   runningbatchnode_idss   &   r   combine_batches_until_nonere      s      G
	LLL+E}  ;ekk"" ++-=#GOOE* # )  {{ 		
 #"s?   
B>B /B>,B+?B>B($B>'B((B>+B;	6B>c                F   a  \         P                  ! S 4      V 3R l4       pV# )zJ
Decorator to send unhandled exceptions to the second argument out_queue.
c                   <  S! W.VO5/ VB #   \          d.   pT P                  R 4       TP                  T4        R p?R # R p?ii ; i)N)BaseExceptionput)rZ   	out_queueargskwargsefuncs   &&*, r   wrapper#exception_to_queue.<locals>.wrapper   sH    	=d=f== 	LLMM!	s    A"AA)	functoolswraps)rn   ro   s   f r   exception_to_queuers      s'    
 __T  Nr   ) )F).__doc__
__future__r   rq   loggingr]   
contextlibr   typingr   urllib.parser   r   r   r   conda.base.contextr	   conda.exceptionsr
   conda.models.match_specr   collections.abcr   r   r   Queuer   conda._private.shards.typingr   r   r   	getLogger__name__rG   	frozensetr)   r   r   r1   r7   rB   cacherI   rX   re   rs   r   r   r   <module>r      s    #       E E & - -2*I	B ! "-0  &$/d   6<r   