
    fJ                       d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 ddl
mZ ddlmZ ddlmZ ddlZdd	lmZ dd
lmZ ddlmZmZ ddlmZmZmZ ddlmZm Z  ddl!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6  ejn                  de8       Z9 ed       G d d             Z: G d de4      Z; ed        G d! d"e;             Z<y)#a  
This module provides a convenient interface between `libmamba.Solver`
and conda's `PrefixData`. In other words, it allows to expose channels
loaded in `conda` to the `libmamba` machinery without using the
`libmamba` networking stack.

Internally, the `libmamba`'s index is made of:

- A 'Pool' object, exposed to libsolv.
- The pool is made of `Repo` objects.
- Each repo corresponds to a repodata.json file.
- Each repodata comes from a channel+subdir combination.

Some notes about channels
-------------------------

In a way, conda channels are an abstraction over a collection of
channel subdirs. For example, when the user wants 'conda-forge', it
actually means 'repodata.json' files from the configured platform subdir
and 'noarch'. Some channels are actually 'MultiChannel', which provide
a collection of channels. The most common example is 'defaults', which
includes 'main', 'r' and 'msys2'.

So, for conda-forge on Linux amd64 we get:

- https://conda.anaconda.org/conda-forge/linux-64
- https://conda.anaconda.org/conda-forge/noarch

For defaults on macOS with Apple Silicon (M1 and friends):

- https://repo.anaconda.org/main/osx-arm64
- https://repo.anaconda.org/main/noarch
- https://repo.anaconda.org/r/osx-arm64
- https://repo.anaconda.org/r/noarch
- https://repo.anaconda.org/msys2/osx-arm64
- https://repo.anaconda.org/msys2/noarch

However, users will just say 'defaults' or 'conda-forge', for convenience.
This means that we need to deal with several formats of channel information,
which ultimately lead to a collection of subdir-specific URLs:

- Channel names from the CLI or configuration files / env-vars
- Channel URLs if names are not available (channel not served in anaconda.org)
- conda.models.channel.Channel objects

Their origins can be:

- Specified by the user on the command-line (-c arguments)
- Specified by the configuration files (.condarc) or environment vars (context object)
- Added from channel-specific MatchSpec (e.g. `conda-forge::python`)
- Added from installed packages in target environment (e.g. a package that was installed
  from a non-default channel remembers where it comes from)

Also note that a channel URL might have authentication in the form:

- https://user:password@server.com/channel
- https://server.com/t/your_token_goes_here/channel

Finally, a channel can be mounted in a local directory and referred to via
a regular path, or a file:// URL, with or without normalization on Windows.

The approach
------------
We pass the subdir-specific, authenticated URLs to conda's 'SubdirData.repo_patch',
which download the JSON files but do not process them to PackageRecords.
Once the cache has been populated, we can instantiate 'libmamba.Repo' objects directly.
We maintain a map of subdir-specific URLs to `conda.model.channel.Channel`
and `libmamba.Repo` objects.
    )annotationsN)	dataclass)	lru_cachepartial)Path)NamedTemporaryFile)Iterable)__version__)REPODATA_FN)contextreset_context)DummyExecutorThreadLimitedThreadPoolExecutorenv_var)	json_dump	json_load)percent_decoderemove_authsplit_anaconda_token)PackageCacheData)
SubdirData)Channel)	MatchSpec)PackageRecord)VersionOrder   )set_channel_priorities)IndexHelper)escape_channel_urlzconda.T)frozenc                  :    e Zd ZU dZded<   ded<   ded<   ded<   y	)
_ChannelRepoInfoz;A dataclass mapping conda Channels, libmamba Repos and URLsr   channelapi.Reporepostrfull_url
noauth_urlN)__name__
__module____qualname____doc____annotations__     n/home/gpsr/webserver/cgidocs/anshu/RAPID-engine/ls/lib/python3.12/site-packages/conda_libmamba_solver/index.pyr"   r"   h   s    A
NMOr/   r"   c                     e Zd Zdddeej
                  j                  df	 	 	 	 	 	 	 	 	 ddZddZd Z		 d	 	 	 	 	 	 	 ddZ
ddZ	 d	 	 	 	 	 	 	 dd	Zdd
ZdddZddZ	 d	 	 	 ddZ	 d	 	 	 ddZdddZddZd dZ	 d	 d!dZy)"LibMambaIndexHelperr.   NFc                x   |t         j                  n|| _        |t         j                  n|| _        || _        g | _        t        j                         | _	        | j                  |      }| j                  j                  |       |r)| j                  j                  | j                                | j                         | _        | xj                  | j                  j!                         D cg c]  }|j"                   c}z  c_        t        j$                  | j                        | _        || _        y c c}w N)r   channels	_channelssubdirs_subdirs_repodata_fn_reposapiPool_pool_load_installedappendextend_load_pkgs_cache_load_channels_indexvaluesr%   Query_query_format)	selfinstalled_recordsr5   r7   repodata_fnquery_formatload_pkgs_cacheinstalled_repoinfos	            r0   __init__zLibMambaIndexHelper.__init__r   s     .6-=))8+2?'XXZ
--.?@>*KKt4467))+dkk.@.@.BC.Bd		.BCCii

+# Ds   .D7c                B   |}|j                  d      st        t        |            d   }	 | j                  |   S # t        $ rZ}	 | j                  t        |         cY d }~S # t        $ r Y nw xY wt	        d| d| dt        | j                               |d }~ww xY w)Nfile://r   zChannel info for z (z) not found. Available keys: )
startswithr   r   rC   KeyErrorr   list)rH   keyorig_keyexcs       r0   get_infozLibMambaIndexHelper.get_info   s    ~~i( '{3'78;C	;;s## 		{{>##677 #H:Ru 5##'#4"57 		s3   ; 	BA"B"	A.+B-A..+BBc                   | j                   j                         D ]  \  }}|j                  d      s|j                  j                  dk(  s1| j                  |j                        \  }}| j                  j                  |j                        }|j                  j                  d       | j                  ||d      }|j                  | j                  |<   || j                   |<    t        | j                          y)zU
        Reload a channel that was previously loaded from a local directory.
        rQ   fileTF)try_solvN)rC   itemsrR   r#   scheme_fetch_channelr'   r:   indexr%   clear_json_path_to_repo_infor   )rH   r(   rN   url	json_pathrepo_positionnews          r0   reload_local_channelsz)LibMambaIndexHelper.reload_local_channels   s     !% 1 1 3J$$Y/4<<3F3F&3P!%!4!4T]]!CY $ 1 1$)) <		%223	E2R-0XXM**-J' !4 	t{{+r/   c                   i i d}i }|D ]  }t        |j                               }dD ]1  }||v rt        ||d      }	|	|dk(  r|	rt        |	dz        }	|	||<   3 |j                  j                  d      r||d   |j                  <   n||d   |j                  <   t        j                         }
|j                  r|j                  j                  |
_        |j                  r1|j                  j                  r|j                  j                  |
_        |
||j                  <    t        d	d
d      5 }|j                  t        |             ddd       	 t        j                   ||j"                  d      }|j%                  |       |t'        j(                  |j"                         S # 1 sw Y   ^xY w# t'        j(                  j"                         w xY w)z
        Build a libmamba 'Repo' object from conda 'PackageRecord' objects.

        This is done by rebuilding a repodata.json-like dictionary, which is
        then exported to a temporary file that will be loaded with 'libmambapy.Repo'.
        )packagespackages.conda)sha256track_featureslicensesizerb   noarchplatform	timestampNrp   i  z.condari   rh   z.jsonFw)suffixdeletemode )dictdumpgetattrintfnendswithr;   ExtraPkgInforn   valuer#   
subdir_urlrepo_urlr   writer   Reponameadd_extra_pkg_infoosunlink)rH   pool	repo_namerecordsexportedadditional_infosrecordrecord_datafieldr}   rN   fr%   s                r0   _repo_from_recordsz&LibMambaIndexHelper._repo_from_records   s    !#b9Fv{{}-K	 K't4$+ #EDL 1).K&!	" yy!!(+8C)*69952=$VYY/ ##%D}}$mm11~~&..";"; & 9 9*.VYY'C F  wu3G1GGIh'( H	88D)QVVR8D##$45IIaff HG IIaffs   5F-4F9 -F69!Gc                ~   t        j                  |      }|j                  st        d|       dt        j
                  v rt        t        j                  j                               D ]U  \  }}t        |t              s|d d || j                  fk(  s,|j                  t        d      k(  sEt        j                  |= W t        j!                  d|       t        || j                        }t"        j$                  st"        j&                  r|j(                  }||fS |j*                  j-                         \  }}||fS )Nz.Channel URLs must specify a subdir! Provided: PYTEST_CURRENT_TEST   infz&Fetching %s with SubdirData.repo_fetch)rJ   )r   from_urlsubdir
ValueErrorr   environrT   r   _cache_r\   
isinstancetupler9   _mtimefloatlogdebugr   offlineuse_index_cachecache_path_json
repo_fetchfetch_latest_path)rH   rb   r#   rU   cachedsubdir_datarc   _s           r0   r^   z"LibMambaIndexHelper._fetch_channel   s   ""3'~~McUSTT BJJ.  $J$6$6$<$<$>?V!#u-r7sD$5$5666==ERWL;X"**3/	  @ 			:GD d6G6GH??g55 $33I I~ '11CCELIqI~r/   c                   t        j                  |      }|j                  d|j                  f      d   }t	        |      }	 |j                         }|r.	 |j                  |j                   dz  }|j                         }	nd }d }	|	#|!t        j                  d|j                         y |	|}
n#||}
n|j                  |	j                  k  r|}
n|}
t        j                  | j                   |t#        |
      t%        |            }t'        ||||      S # t        $ r$}t        j                  d||       d }Y d }~d }~ww xY w# t        $ r$}t        j                  d|       d }	Y d }~d }~ww xY w)	NFwith_credentialsr7   r   zFailed to stat %s)exc_infoz.solvz2No repodata found for channel %s. Solve will fail.)r%   r#   r'   r(   )r   r   urlsr   r   statOSErrorr   r   parentstemwarningcanonical_namest_mtimer;   r   r=   r&   r   r"   )rH   rb   rc   r[   r#   r(   	json_statrW   	solv_path	solv_statpath_to_user%   s               r0   ra   z+LibMambaIndexHelper._json_path_to_repo_info  sv    ""3'\\57>>BS\TUVW
O		!(I !%,,)..1A/GG	%NN,	
 II!2KKDgF\F\ #K#K9#5#55#K#Kxx

JK0@BTU_B`a!	
 	
=  	II)9sICI	  !		-y3	G 	!s0   D ,E 	E D??E	E4E//E4c                   g }t               }| j                  D ]  }t        di t        |      j                         j	                         D ci c]  \  }}|dk7  s|| c}}}|j                  d| j                        }|j                  |      r||j                  d| j                        }||k7  r||z  }|j                  |       |D ])  }	|	|vs|j                  |	       |j                  |	       +  t        t        j                  |            }t        j                  st        j                   dk(  rt"        nt%        t&        t        j                         }
 |
       5 }|j)                  | j*                  |      D 	ci c]  \  }	}|	t-        |       }}	}d d d        i }|D ])  }	| j/                  |	|	         }||||j0                  <   + t3        |       |S c c}}w c c}}	w # 1 sw Y   RxY w)Nro   Fr   Tr   )max_workersr.   )setr6   r   rw   r\   r   r8   
issupersetupdater?   addr   rv   fromkeysr   r   repodata_threadsr   r   r   mapr^   r&   ra   r(   r   )rH   r   seen_noauth_ckvcnoauth_urls	auth_urlsrb   Executorexecutorpathjsonsr_   rN   s                   r0   rB   z"LibMambaIndexHelper._load_channels/  s   e..B[GBK,<,<,>,D,D,FZ,FDAq!z/1a4,FZ[A&&%&OK%%k2dmmLIi'	!"";/ #k)KK$OOC( # !& T]]4()
 }} 8 8A = 8gF^F^_ 	
 Z87?||DDWDWY]7^_7^dS#d)^7^E_  C//U3Z@D)-doo&  	u%M [4 ` Zs*   G)G)+ G5G/!G5/G55G>c                    |t         j                  }g }|D ]Y  }t        |      }|j                          | j	                  | j
                  ||j                               }|j                  |       [ |S r4   )r   	pkgs_dirsr   loadr   r=   rD   r?   )rH   r   reposr   package_cache_datar%   s         r0   rA   z$LibMambaIndexHelper._load_pkgs_cache]  sn    ))ID!1$!7##%**4::t=O=V=V=XYDLL	 
 r/   c                `    | j                  | j                  d|      }|j                          |S )N	installed)r   r=   set_installed)rH   r   r%   s      r0   r>   z#LibMambaIndexHelper._load_installedh  s+    &&tzz;Hr/   c                    | j                   j                  | j                  |      | j                        }| j                  t        j
                  j                  k(  r| j                  ||      S |S N)r   )rF   whoneeds_prepare_queryrG   r;   QueryFormatJSON_process_query_resultrH   queryr   
result_strs       r0   r   zLibMambaIndexHelper.whoneedsm  s[     [[))$*=*=e*DdllS
<<3??///--j'-JJr/   c                    | j                   j                  | j                  |      | j                        }| j                  t        j
                  j                  k(  r| j                  ||      S |S r   )rF   dependsr   rG   r;   r   r   r   r   s       r0   r   zLibMambaIndexHelper.dependsu  s[     [[(()<)<U)CT\\R
<<3??///--j'-JJr/   c                    | j                   j                  | j                  |      | j                        }| j                  t        j
                  j                  k(  r| j                  ||      S |S r   )rF   findr   rG   r;   r   r   r   r   s       r0   searchzLibMambaIndexHelper.search}  sY    [[%%d&9&9%&@$,,O
<<3??///--j'-JJr/   c                    t               }|D ]C  }| j                  |j                               }|D ]  }|j                  |j                          E t        |      S )zW
        Returns all the package names that (might) depend on the passed specs
        )r   r   dist_strr   r   r   )rH   specsexplicit_poolspecpkg_recordsr   s         r0   r   z!LibMambaIndexHelper.explicit_pool  sR     D,,t}}7K%!!&++. &  ]##r/   c                    t        |t              rd|vr|S t        |      }|j                  d      st        |d      }|j	                         S )N[version*)r   )r   r&   r   get_raw_valueconda_build_form)rH   r   s     r0   r   z"LibMambaIndexHelper._prepare_query  sN    eS!%e$E ""9-eS1E%%''r/   c                   t        |      }|j                  di       j                  d      dk7  r||j                  di       j                  dd      }|j                  di       j                  dd      }|j                  di       j                  dd|       }t        | d	| d
|       |r-g }|d   d   D ]  }t        di |}	|j	                  |	         |S |S )NresultstatusOKr   typez	<Unknown>msgzFaulty response: z query 'z
' failed: pkgsr.   )r   getr   r   r?   )
rH   r   r   r   
query_typer   	error_msgr   pkgr   s
             r0   r   z)LibMambaIndexHelper._process_query_result  s    
 :&::h#''1T9GR044V[IJJJw+//EE

8R044U>OPZ|<\]I
|8E7*YKPQQKh'/&--""6* 0 r/   )
rI   Iterable[PackageRecord]r5   zIterable[Channel | str] | Noner7   zIterable[str] | NonerJ   r&   rL   bool)rU   r&   returnr"   )r.   )r   zapi.Poolr   r&   r   r   r   r$   )rb   r&   r   ztuple[str, os.PathLike])T)rb   r&   rc   r&   r[   r   r   z_ChannelRepoInfo | None)r   zdict[str, _ChannelRepoInfo]r4   )r   zIterable[api.Repo])r   r   r   r$   )r   str | MatchSpecr   z$Iterable[PackageRecord] | dict | str)r   zIterable[MatchSpec]r   zIterable[str])r   r   r   r&   )r   zIterable[PackageRecord] | dict)r)   r*   r+   r   r;   r   r   rO   rX   rf   r   r^   ra   rB   rA   r>   r   r   r   r   r   r   r.   r/   r0   r2   r2   q   s#    6837(,&__)) %$2$ 1$ &	$
 $ $8(, RT66),67N6	6p6 :>+
+
#&+
26+
	 +
Z,\	 /3$	- /3$	-	$(4  
(	r/   r2   )maxsizec                  "     e Zd ZdZ fdZ xZS )_LibMambaIndexForCondaBuilda  
    See https://github.com/conda/conda-libmamba-solver/issues/386

    conda-build needs to operate offline so the index doesn't get updated
    accidentally during long build phases. However, this is only guaranteed
    to work if https://github.com/conda/conda/pull/13357 is applied. Otherwise
    the condarc configuration might be ignored, resulting in bad index configuration
    and missing packages anyway.
    c                    t        t              t        d      k  r%t        j                  d       t	        |   |i | y t        ddt              5  t	        |   |i | d d d        y # 1 sw Y   y xY w)Nz23.10.0a  conda-build requires conda >=23.11.0 for offline index support. Falling back to online index. This might result in KeyError messages, specially if the remote repodata is updated during the build phase. See https://github.com/conda/conda-libmamba-solver/issues/386.CONDA_OFFLINEtrue)callback)r   conda_versionr   r   superrO   r   r   )rH   argskwargs	__class__s      r0   rO   z$_LibMambaIndexForCondaBuild.__init__  sf    &,y*AAKKQ Gd-f-&=I $1&1 JIIs   A--A6)r)   r*   r+   r,   rO   __classcell__)r  s   @r0   r   r     s    2 2r/   r   )=r,   
__future__r   loggingr   dataclassesr   	functoolsr   r   pathlibr   tempfiler   typingr	   
libmambapyr;   condar
   r  conda.base.constantsr   conda.base.contextr   r   conda.common.ior   r   r   conda.common.serializer   r   conda.common.urlr   r   r   conda.core.package_cache_datar   conda.core.subdir_datar   conda.models.channelr   conda.models.match_specr   conda.models.recordsr   conda.models.versionr   mamba_utilsr   stater   utilsr   	getLoggerr)   r   r"   r2   r   r.   r/   r0   <module>r"     s   DJ #  	 ! (  '   . , 5 S S 7 N N : - ( - . - /  %g&
+, $  E+ EP
 42"5 2 2r/   