
    \ZieB                        S 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  S
SKJr  \(       a  SSKJr  S
SKJr  \" \5      r " S S5      r " S S\5      rg)zImplements directed graphs to sort and manipulate packages within a prefix.

Object inheritance:

.. autoapi-inheritance-diagram:: PrefixGraph GeneralGraph
   :top-classes: conda.models.prefix_graph.PrefixGraph
   :parts: 1
    )annotations)defaultdict)	getLogger)TYPE_CHECKING   )context)on_win)CyclicalDependencyError   )
NoarchType	MatchSpec)Iterable)PrefixRecordc                      \ rS rSrSr S   SS jjrS rS r\S 5       r	S r
S rS	 rS
 rS rS r\S 5       r\S 5       r\S 5       r\S 5       rSrg)PrefixGraph    a.  
A directed graph structure used for sorting packages (prefix_records) in prefixes and
manipulating packages within prefixes (e.g. removing and pruning).

The terminology used for edge direction is "parents" and "children" rather than "successors"
and "predecessors". The parent nodes of a record are those records in the graph that
match the record's "depends" field.  E.g. NodeA depends on NodeB, then NodeA is a child
of NodeB, and NodeB is a parent of NodeA.  Nodes can have zero parents, or more than two
parents.

Most public methods mutate the graph.
c                  ^^	 [        U5      n[        U5      nU   0 =U l        nU   0 =U l        nU H  m	[        S T	R                   5       5      nU V^s0 s H"  m[        U4S jU 5       5      (       d  M  TS _M$     nnXsT	'   [        R                  U	4S jU 5       5      nU(       d  M{  XT	'   M     U R                  5         g s  snf )Nc              3  8   #    U  H  n[        U5      v   M     g 7fNr   .0ds     9lib/python3.13/site-packages/conda/models/prefix_graph.py	<genexpr>'PrefixGraph.__init__.<locals>.<genexpr>8   s     &J\y||\   c              3  D   >#    U  H  oR                  T5      v   M     g 7fr   match)r   mrecs     r   r   r   <   s     @-?wws||-?s    c              3  V   >#    U  H  oR                  T5      (       d  M  Uv   M      g 7fr   r   )r   snodes     r   r   r   ?   s     *Mewwt}11es   )	))	tuplesetgraphspec_matchesdependsanydictfromkeys	_toposort)
selfrecordsspecsr(   r)   parent_match_specsr"   parent_nodesmatching_specsr%   s
         `  @r   __init__PrefixGraph.__init__.   s     .E

U+--LD!&&JT\\&J!J #"C@-?@@ T	"  
 '$K!]]*Me*MMN~%3T"  	s   C7Cc                L  ^^ U R                    Vs1 s H  o!R                  U5      (       d  M  UiM     nnUR                  S5      =(       d    S H1  n[        US9mUR	                  U4S jU R                    5       5        M3     [        5       mU H4  nTR                  U5        TR	                  U R                  U5      5        M6     [        [        U4S jU R                   5      5      mT H  nU R                  U5        M     U R                  5         [        T5      $ s  snf )z
Remove all matching nodes, and any associated child nodes.

Args:
    spec (MatchSpec):

Returns:
    tuple[PrefixRecord]: The removed nodes.

track_features )featuresc              3  X   >#    U  H  nTR                  U5      (       d  M  Uv   M!     g 7fr   r   )r   r%   feature_specs     r   r   *PrefixGraph.remove_spec.<locals>.<genexpr>V   s!     X|?Q?QRV?Ws   *	*c                   > U T;   $ r   r9   )r%   remove_theses    r   <lambda>)PrefixGraph.remove_spec.<locals>.<lambda>\   s
    1E    )r(   r    get_raw_valuer   updater'   addall_descendantsr&   filter_remove_noder.   )r/   specr%   node_matchesfeature_namer<   r?   s        @@r   remove_specPrefixGraph.remove_specE   s     *.Hzz$7GH !../?@FBFL$l;LXXX G u DT" 4 4T :; ! V$EtzzRS Dd# !\""! Is
   D!D!c                  ^^ U R                   nU R                  mU VVs0 s H  o"U Vs1 s H  o2X   ;   d  M  UiM     sn_M!     nnn[        U4S jUR                  5        5       5      m[        [	        U4S jU R                   5      5      nU H  nU R                  U5        M     U R                  5         U$ s  snf s  snnf )z
A specialized method used to determine only dependencies of requested specs.

Returns:
    tuple[PrefixRecord]: The removed nodes.

c              3  N   >#    U  H  u  pU(       a  M  UT;   d  M  Uv   M     g 7fr   r9   r   r%   childrenr)   s      r   r   JPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<genexpr>o   s,      *
"8  $ 4 D"8   %%	%c                   > U T;   $ r   r9   )r%   youngest_nodes_with_specss    r   r@   IPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<lambda>u   s    (A ArB   )r(   r)   r&   itemsrG   rH   r.   )r/   r(   r%   keyinverted_graphremoved_nodesr)   rU   s         @@r   +remove_youngest_descendant_nodes_with_specs7PrefixGraph.remove_youngest_descendant_nodes_with_specsb   s     

((KP
KP4%>%35:+=3%>>5 	 
 %* *
"0"6"6"8*
 %
!
 A4::N
 "Dd# " ?
s   
C B;B;C ;C c                ,    [        U R                  5      $ r   )iterr(   )r/   s    r   r0   PrefixGraph.records|   s    DJJrB   c                  ^^ U R                   nU R                  m[        U R                   5      n[        5       m U VVs0 s H  o3U Vs1 s H  oCX   ;   d  M  UiM     sn_M!     nnn[        U4S jUR	                  5        5       5      nU(       d  O-U H%  nTR                  U5        U R                  U5        M'     M  [        [        U4S jU5      5      mU R                  5         T$ s  snf s  snnf )z|Prune back all packages until all child nodes are anchored by a spec.

Returns:
    tuple[PrefixRecord]: The pruned nodes.

c              3  N   >#    U  H  u  pU(       a  M  UT;  d  M  Uv   M     g 7fr   r9   rP   s      r   r   $PrefixGraph.prune.<locals>.<genexpr>   s,      #&<ND $($< &<rS   c                   > U T;   $ r   r9   )r%   rZ   s    r   r@   #PrefixGraph.prune.<locals>.<lambda>   s
     5rB   )	r(   r)   r&   r'   rW   rE   rH   rG   r.   )	r/   r(   original_orderr%   rX   rY   prunable_nodesrZ   r)   s	          @@r   prunePrefixGraph.prune   s     

((tzz*OTOTteBesuz/AseBBu   # #&4&:&:&<# N
 "&!!$'!!$' '  5~F
 	# Cs    
C1
C,C,C1,C1c                B   ^ [        U4S jU R                   5       5      $ )Nc              3  J   >#    U  H  oR                   T:X  d  M  Uv   M     g 7fr   name)r   r"   rl   s     r   r   /PrefixGraph.get_node_by_name.<locals>.<genexpr>   s     B:CT1ACC:s   #	#)nextr(   )r/   rl   s    `r   get_node_by_namePrefixGraph.get_node_by_name   s    B4::BBBrB   c                  ^ U R                   nU VVs0 s H  oU Vs1 s H  o1X#   ;   d  M  UiM     sn_M!     nnnW/n[        5       mSnU[        U5      :  aN  XEU       H-  nUT;  d  M  TR                  U5        UR	                  U5        M/     US-  nU[        U5      :  a  MN  [        [        U4S jU5      5      $ s  snf s  snnf )Nr   r   c                   > U T;   $ r   r9   r%   
nodes_seens    r   r@   -PrefixGraph.all_descendants.<locals>.<lambda>   
    );rB   r(   r'   lenrE   appendr&   rG   )	r/   r%   r(   rX   rY   nodesq
child_nodert   s	           @r   rF   PrefixGraph.all_descendants   s    

KP
KP4%>%35:+=3%>>5 	 
 U
#e*n,1X6
Z/NN:.LL, 7 FA #e*n V;UCDD ?
s   
CCCCCc                &  ^ U R                   nU/n[        5       mSnU[        U5      :  aN  X#U       H-  nUT;  d  M  TR                  U5        UR	                  U5        M/     US-  nU[        U5      :  a  MN  [        [        U4S jU5      5      $ )Nr   r   c                   > U T;   $ r   r9   rs   s    r   r@   +PrefixGraph.all_ancestors.<locals>.<lambda>   rv   rB   rw   )r/   r%   r(   rz   r{   parent_nodert   s         @r   all_ancestorsPrefixGraph.all_ancestors   s    

U
#e*n$1Xj0NN;/LL-  / FA #e*n V;UCDDrB   c                    U R                   nX;  a  [        SU S35      eUR                  U5        U R                  R                  US5        UR	                  5        H  u  pUR                  US5        M     g)z/Removes this node and all edges referencing it.znode z does not existN)r(   KeyErrorpopr)   rW   )r/   r%   r(   edgess       r   rH   PrefixGraph._remove_node   sf    

U4&899		$dD) ;;=KDIIdD! )rB   c                   U R                   R                  5        VVs0 s H  u  pU[        R                  U5      _M     nnnU R	                  U5        [
        R                  (       a  [        U R                  U5      5      nO[        U R                  U5      5      nU R                   nU Vs0 s H  oXQ   _M	     snU l         U$ s  snnf s  snf r   )
r(   rW   r,   r-   _toposort_prepare_graphr   allow_cyclesr&   _topo_sort_handle_cycles_toposort_raise_on_cycles)r/   r%   parents
graph_copysorted_nodesoriginal_graphs         r   r.   PrefixGraph._toposort   s    >Bjj>N>N>P
>P]TD$--((>P 	 
 	$$Z0 !>!>z!JKL !?!?
!KLL=IJ\TN00\J

 Ks   "C.Cc              #    #    U(       d  g  [         R                  [        S UR                  5        5       S S95      nU(       d  OSU H  nUv   UR	                  US 5        M     UR                  5        H  nU H  nUR	                  US 5        M     M      M  [        U5      S:w  a  [        [        U5      5      eg 7f)Nc              3  L   #    U  H  u  p[        U5      S :X  d  M  Uv   M     g7f)r   N)rx   r   r%   r   s      r   r   8PrefixGraph._toposort_raise_on_cycles.<locals>.<genexpr>   s      R}mdGPQ@QTT}s   $	$c                    U R                   $ r   rk   xs    r   r@   7PrefixGraph._toposort_raise_on_cycles.<locals>.<lambda>   s    !&&rB   rX   r   )	r,   r-   sortedrW   r   valuesrx   r
   r&   )clsr(   no_parent_nodesr%   r   s        r   r   %PrefixGraph._toposort_raise_on_cycles   s     "mmRu{{}R(O #'
		$% ( !<<>+DKKd+ , * $ u:?)%,77 s   B<B>c              #  "  ^^#    TR                  5        H  u  p#UR                  US 5        M     TR                  5        VVs1 s H  oD  H  oUiM     M     snnmU4S jT 5       n[        U4S jU 5       S S9nU S h  vN   U R	                  T5      n  [        U5      n	U	v   M  s  snnf  N.! [         aE  n
[        R                  SU
5        U R                  T5      v   U R	                  T5      n S n
A
Me  S n
A
f[         a     g f = f7f)Nc              3  @   >#    U  H  nTU   (       a  M  Uv   M     g 7fr   r9   )r   r%   r(   s     r   r   7PrefixGraph._topo_sort_handle_cycles.<locals>.<genexpr>   s      K%$uT{%s   	c              3  8   >#    U  H  nUT;  d  M  Uv   M     g 7fr   r9   )r   r%   nodes_that_are_parentss     r   r   r      s#      1D55 1s   
	c                    U R                   $ r   rk   r   s    r   r@   6PrefixGraph._topo_sort_handle_cycles.<locals>.<lambda>  s    !&&rB   r   z%r)rW   r   r   r   r   rn   r
   logdebug_toposort_pop_keyStopIteration)r   r(   kvr   r%   nodes_without_parentsdisconnected_nodestvalueer   s    `         @r   r   $PrefixGraph._topo_sort_handle_cycles   s     KKMDAEE!TN "
 !&"
 .W74D7D"
 !L% K#1
 !
 &%%))%0Q !"
 	& +  		$"++E2211%8  sS   ?DB**DB0DB2 (	D2
D<:C<6D<D	DDDc                    [        S U R                  5        5       5      S   S   nU R                  U5        U R                  5        H  nUR                  US5        M     U$ )z
Pop an item from the graph that has the fewest parents.
In the case of a tie, use the node with the alphabetically-first package name.
c              3  ^   #    U  H#  u  p[        U5      UR                  5       U4v   M%     g 7fr   )rx   dist_strr   s      r   r   0PrefixGraph._toposort_pop_key.<locals>.<genexpr>"  s&      *
GTmdS\4==?D1}s   +-r   r   N)r   rW   r   r   )r(   node_with_fewest_parentsr   s      r   r   PrefixGraph._toposort_pop_key  sh     $* *
GL{{}*
 $

$$  			*+||~GKK0$7 & ('rB   c                   U  HO  nUR                   S:X  d  M  X   n[        U5       H'  nUR                   S:X  d  M  UR                  US 5        M)     MQ     [        S U  5       S 5      n[        S U  5       S 5      nU(       aJ  Uc  [	        S5      eX   nU R                  5        H$  u  pXR;   d  M  X;  d  M  UR                  U5        M&     [        (       a  [        S U  5       S 5      nU(       ai  X   nU R                  5        HP  u  p[        US5      (       d  M  UR                  [        R                  :X  d  M8  X;  d  M?  UR                  U5        MR     g g g )Npythonpipc              3  H   #    U  H  oR                   S :X  d  M  Uv   M     g7f)menuinstNrk   r   r%   s     r   r   6PrefixGraph._toposort_prepare_graph.<locals>.<genexpr><  s     Put		Z8Oddu   "	"c              3  H   #    U  H  oR                   S :X  d  M  Uv   M     g7f)r   Nrk   r   s     r   r   r   =  s     LUTii86KDDUr   z.Found menuinst without Python in prefix graph.c              3  H   #    U  H  oR                   S :X  d  M  Uv   M     g7f)condaNrk   r   s     r   r   r   N  s     Ng9Mttr   noarch)rl   r&   r   rn   RuntimeErrorrW   
setdefaultr	   hasattrr   r   r   )	r(   r%   r   parentmenuinst_nodepython_nodemenuinst_parents
conda_nodeconda_parentss	            r   r   #PrefixGraph._toposort_prepare_graph,  s1    DyyH$+#GnF{{e+FD1 -  PuPRVWLULdS ""#STT$3!&)d.J&&}5 "/ 6 NNPTUJ % 1%*[[]MDh// KK:+<+<< 5**:6 &3  rB   )r(   r)   Nr9   )r0   zIterable[PrefixRecord]r1   zIterable[MatchSpec])__name__
__module____qualname____firstlineno____doc__r5   rL   r[   propertyr0   rg   ro   rF   r   rH   r.   classmethodr   r   staticmethodr   r   __static_attributes__r9   rB   r   r   r       s     MO-6I.#:4    BCE"E	" 8 82 % %N ( ( +7 +7rB   r   c                  6   ^  \ rS rSrSrSU 4S jjrS rSrU =r$ )GeneralGraphi  a'  
Compared with PrefixGraph, this class takes in more than one record of a given name,
and operates on that graph from the higher view across any matching dependencies.  It is
not a Prefix thing, but more like a "graph of all possible candidates" thing, and is used
for unsatisfiability analysis
c                  > [        U5      n[        T
U ]	  X5        [        [        5      U l        U H  nU R
                  R                  UR                  0 5      n[        S UR                   5       5       H>  nUR                  UR                  0 5      nUR                  U5        XdUR                  '   M@     X@R
                  UR                  '   M     0 n[        [        U R                  R                  5       5      5       HZ  u  p8UR                  UR                  0 5      n	U	R                  [        R                  S U 5       5      5        XUR                  '   M\     Xpl        g )Nc              3  8   #    U  H  n[        U5      v   M     g 7fr   r   r   s     r   r   (GeneralGraph.__init__.<locals>.<genexpr>  s     @<aYq\\<r   c              3  8   #    U  H  oR                   v   M     g 7fr   rk   )r   _s     r   r   r     s     #ALqFFLr   )r&   superr5   r   r,   specs_by_namegetrl   r*   r   reversedlistr(   rW   rD   r-   graph_by_name)r/   r0   r1   r%   parent_dictdepdepsconsolidated_graphr3   cg	__class__s             r   r5   GeneralGraph.__init__  s   .((.D,,00B?K@4<<@@"sxx4$(,CHH% A -8tyy)   "*4

0@0@0B+C"DD#''		26BIIdmm#AL#AAB,.tyy) #E 0rB   c                V   / nUR                  U/5        / nU(       Ga  UR                  S5      nUS   nXd;   a  M%  UR                  U5        Xb:X  a  U$ / nU R                  R                  UR                  5      nUc  Mi  UR                  5        H  u  pUR                  [        U
5      5        M!     U Hf  nUR                  UR                  :X  a  UR                  UR                  :w  a  M9  [        U5      nUR                  U5        UR                  U5        Mh     U(       a  GM
  gg)z/Return shorted path from root_spec to spec_namer   N)	ry   r   r   r   rl   rW   extendr   version)r/   	root_spectarget_specqueuevisitedpathr%   rQ   r1   r   r   adjnew_paths                r   breadth_first_search_by_name)GeneralGraph.breadth_first_search_by_name  s    i[!99Q<D8DNN4 "H&&**4995E} ;;=T
+ )88{///CKK;CVCV4V#DzHOOC(LL*   erB   )r   r   r   )	r   r   r   r   r   r5   r   r   __classcell__)r   s   @r   r   r     s    0(+ +rB   r   N)r   
__future__r   collectionsr   loggingr   typingr   base.contextr   common.compatr	   
exceptionsr
   enumsr   
match_specr   collections.abcr   r0   r   r   r   r   r   r9   rB   r   <module>r     sS    # #    " " 0  !(%x7 x7j5+; 5+rB   