
    si@                         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  \" \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
    )defaultdict)	getLogger)
IndexedSet   )context)on_win)CyclicalDependencyError   )
NoarchType	MatchSpecc                       \ rS rSrSrSS 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                 v  ^^	 [        U5      n[        U5      n0 =U l        n0 =U l        nU Ht  m	[        S T	R                   5       5      nU V^s1 s H!  m[        U4S jU 5       5      (       d  M  TiM#     nnXsT	'   [        U	4S jU 5       5      nU(       d  Mp  XT	'   Mv     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>.   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   0   s     -WDVqggcllDVs    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   3   s     'J5aGGDM5s   )	))tuplesetgraphspec_matchesdependsanyr   	_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&&#-WDV-W*Ww   '$K''J5'JJN~%3T"  	s   B63B6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>J   s!     X|?Q?QRV?Ws   *	*c                    > U T;   $ r   r4   )r"   remove_theses    r   <lambda>)PrefixGraph.remove_spec.<locals>.<lambda>P   s
    1E    )r%   r   get_raw_valuer   updater$   addall_descendantsr#   filter_remove_noder)   )r*   specr"   node_matchesfeature_namer7   r:   s        @@r   remove_specPrefixGraph.remove_spec9   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   r4   r   r"   childrenr&   s      r   r   JPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<genexpr>c   s,      *
"8  $ 4 D"8   %%	%c                    > U T;   $ r   r4   )r"   youngest_nodes_with_specss    r   r;   IPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<lambda>i   s    (A Ar=   )r%   r&   r#   itemsrB   rC   r)   )r*   r%   r"   keyinverted_graphremoved_nodesr&   rP   s         @@r   +remove_youngest_descendant_nodes_with_specs7PrefixGraph.remove_youngest_descendant_nodes_with_specsV   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   r+   PrefixGraph.recordsp   s    DJJr=   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   r4   rK   s      r   r   $PrefixGraph.prune.<locals>.<genexpr>   s,      #&<ND $($< &<rN   c                    > U T;   $ r   r4   )r"   rU   s    r   r;   #PrefixGraph.prune.<locals>.<lambda>   s
     5r=   )	r%   r&   r#   r$   rR   r@   rC   rB   r)   )	r*   r%   original_orderr"   rS   rT   prunable_nodesrU   r&   s	          @@r   prunePrefixGraph.prunet   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   rg   s     r   r   /PrefixGraph.get_node_by_name.<locals>.<genexpr>   s     B:CT1ACC:s   #	#)nextr%   )r*   rg   s    `r   get_node_by_namePrefixGraph.get_node_by_name   s    B4::BBBr=   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   r4   r"   
nodes_seens    r   r;   -PrefixGraph.all_descendants.<locals>.<lambda>   
    );r=   r%   r$   lenr@   appendr#   rB   )	r*   r"   r%   rS   rT   nodesq
child_nodero   s	           @r   rA   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   r4   rn   s    r   r;   +PrefixGraph.all_ancestors.<locals>.<lambda>   rq   r=   rr   )r*   r"   r%   ru   rv   parent_nodero   s         @r   all_ancestorsPrefixGraph.all_ancestors   s    

U
#e*n$1Xj0NN;/LL-  / FA #e*n V;UCDDr=   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X;   d  M  UR                  U5        M     g)z/Removes this node and all edges referencing it.znode z does not existN)r%   KeyErrorpopr&   rR   remove)r*   r"   r%   edgess       r   rC   PrefixGraph._remove_node   si    

U4&899		$dD) ;;=KD}T" )r=   c                    U R                   R                  5        VVs0 s H  u  pU[        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%   rR   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    EIZZEUEUEWXEWMDdJw//EW
X$$Z0 !>!>z!JKL !?!?
!KLL=IJ\TN00\J
 Y Ks   B<$Cc              #   >  #    U(       d  g  [        [        S UR                  5        5       S S95      nU(       d  O<U H  nUv   UR                  US 5        M     UR	                  5        H  nXB-  nM	     Mm  [        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)rs   r   r"   r   s      r   r   8PrefixGraph._toposort_raise_on_cycles.<locals>.<genexpr>   s      R}mdGPQ@QTT}s   $	$c                     U R                   $ r   rf   xs    r   r;   7PrefixGraph._toposort_raise_on_cycles.<locals>.<lambda>   s    !&&r=   rS   r   )r   sortedrR   r   valuesrs   r	   r#   )clsr%   no_parent_nodesr"   r   s        r   r   %PrefixGraph._toposort_raise_on_cycles   s     (Ru{{}R(O #'
		$% ( !<<>* * " u:?)%,77 s   BBc              #      ^^#    TR                  5        H  u  p#UR                  U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   r4   )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   r4   )r   r"   nodes_that_are_parentss     r   r   r      s#      1D55 1s   
	c                     U R                   $ r   rf   r   s    r   r;   6PrefixGraph._topo_sort_handle_cycles.<locals>.<lambda>   s    !&&r=   r   z%r)rR   discardr   r   r   ri   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IIaL "
 !&"
 .W74D7D"
 !L% K#1
 !
 &%%))%0Q !"
 	& +  		$"++E2211%8  sS   >DB)*D B/DB1 '	D1
D;:C;5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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   )rs   dist_strr   s      r   r   0PrefixGraph._toposort_pop_key.<locals>.<genexpr>  s&      *
GTmdS\4==?D1}s   +-r   r   )r   rR   r   r   r   )r%   node_with_fewest_parentsr   s      r   r   PrefixGraph._toposort_pop_key  sf     $* *
GL{{}*
 $

$$  			*+||~GOO45 & ('r=   c                    U  HN  nUR                   S:X  d  M  X   n[        U5       H&  nUR                   S:X  d  M  UR                  U5        M(     MP     [        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)menuinstNrf   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   Nrf   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)condaNrf   r   s     r   r   r   @  s     Ng9Mttr   noarch)rg   r#   r   ri   RuntimeErrorrR   r@   r   hasattrr   r   r   )	r%   r"   r   parentmenuinst_nodepython_nodemenuinst_parents
conda_nodeconda_parentss	            r   r   #PrefixGraph._toposort_prepare_graph  s+    DyyH$+#GnF{{e+v. -  PuPRVWLULdS ""#STT$3!&)d.JKK. "/ 6 NNPTUJ % 1%*[[]MDh// KK:+<+<< 5J/ &3  r=   )r%   r&   Nr4   )__name__
__module____qualname____firstlineno____doc__r0   rG   rV   propertyr+   rb   rj   rA   r}   rC   r)   classmethodr   r   staticmethodr   r   __static_attributes__r4   r=   r   r   r      s    "#:4    BCE"E
#	 8 80 % %N ( ( +0 +0r=   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       HF  nUR                  UR                  [        5       5      nUR                  U5        XdUR                  '   MH     X@R
                  UR                  '   M     0 n[        [        U R                  R                  5       5      5       HO  u  p8UR                  UR                  [        5       5      n	U	R                  S U 5       5        XUR                  '   MQ     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   rf   )r   _s     r   r   r     s     3lfflr   )r#   superr0   r   dictspecs_by_namegetrg   r'   r$   r@   reversedlistr%   rR   r?   graph_by_name)r*   r+   r,   r"   parent_dictdepdepsconsolidated_graphr.   cg	__class__s             r   r0   GeneralGraph.__init__  s   .((.D,,00B?K@4<<@@"sxx7(,CHH% A -8tyy)   "*4

0@0@0B+C"DD#''		359BII3l33,.tyy) #E 0r=   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)	rt   r   r   r   rg   rR   extendr   version)r*   	root_spectarget_specqueuevisitedpathr"   rL   r,   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*   er=   )r   r   r   )	r   r   r   r   r   r0   r   r   __classcell__)r   s   @r   r   r     s    0(+ +r=   r   N)r   collectionsr   loggingr   boltons.setutilsr   base.contextr   common.compatr   
exceptionsr	   enumsr   
match_specr   r   r   r   r   r4   r=   r   <module>r     sG    $  ' " " 0  !p0 p0Z5+; 5+r=   