
    DIepA                         d Z ddlmZ ddlmZ 	 ddlmZ n# e$ r	 ddlmZ Y nw xY w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  ee          Z G d d          Z G d de          ZdS )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                       e Zd ZdZddZd Zd Zed             Zd Z	d Z
d	 Zd
 Zd Zd Zed             Zed             Zed             Zed             ZdS )PrefixGraphaR  
    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                 B   t          |          }t          |          }i x| _        }i x| _        }|D ]Ut          d j        D                       fd|D             }||<   t          fd|D                       }|r||<   V|                                  d S )Nc              3   4   K   | ]}t          |          V  d S Nr   .0ds     9lib/python3.11/site-packages/conda/models/prefix_graph.py	<genexpr>z'PrefixGraph.__init__.<locals>.<genexpr>0   s(      &J&Jy||&J&J&J&J&J&J    c                 L    h | ]t          fd D                        S )c              3   B   K   | ]}|                               V  d S r   match)r   mrecs     r   r   z1PrefixGraph.__init__.<locals>.<setcomp>.<genexpr>2   s-      -W-Wqaggcll-W-W-W-W-W-Wr   )any)r   r    parent_match_specss    @r   	<setcomp>z'PrefixGraph.__init__.<locals>.<setcomp>1   sM       #-W-W-W-WDV-W-W-W*W*W  r   c              3   F   K   | ]}|                               |V  d S r   r   )r   snodes     r   r   z'PrefixGraph.__init__.<locals>.<genexpr>5   s2      'J'JaAGGDMM'J'J'J'J'J'J'Jr   )tuplesetgraphspec_matchesdependsr   	_toposort)	selfrecordsspecsr)   r*   parent_nodesmatching_specsr&   r"   s	          @@r   __init__zPrefixGraph.__init__*   s    ..E


U+--L 	4 	4D!&&J&JT\&J&J&J!J!J   &  L 'E$K''J'J'J'J5'J'J'JJJN 4%3T"r   c                 2   fd| j         D             }                    d          pdD ]8}t          |          |                    fd| j         D                        9t	                      |D ]?}                    |                               |                     |                     @t          t          fd| j                             D ]}| 	                    |           | 
                                 t                    S )z
        Remove all matching nodes, and any associated child nodes.

        Args:
            spec (MatchSpec):

        Returns:
            tuple[PrefixRecord]: The removed nodes.

        c                 >    h | ]}                     |          |S r   r   )r   r&   specs     r   r#   z*PrefixGraph.remove_spec.<locals>.<setcomp>F   s*    HHHtzz$7G7GHHHHr   track_featuresr   )featuresc              3   F   K   | ]}                     |          |V  d S r   r   )r   r&   feature_specs     r   r   z*PrefixGraph.remove_spec.<locals>.<genexpr>L   s7      XX|?Q?QRV?W?WXXXXXXXr   c                     | v S r   r   )r&   remove_theses    r   <lambda>z)PrefixGraph.remove_spec.<locals>.<lambda>R   s    1E r   )r)   get_raw_valuer   updater(   addall_descendantsr'   filter_remove_noder,   )r-   r5   node_matchesfeature_namer&   r9   r;   s    `   @@r   remove_speczPrefixGraph.remove_spec;   s@    IHHHHHH !../?@@FB 	Y 	YL$l;;;LXXXXXXXXXXXuu  	< 	<DT""" 4 4T : :;;;;V$E$E$E$EtzRRSS  	$ 	$Dd####\"""r   c                 D   | j         | j        fdD             }t          fd|                                D                       t          t	          fd| j                             }|D ]}|                     |           |                                  |S )z
        A specialized method used to determine only dependencies of requested specs.

        Returns:
            tuple[PrefixRecord]: The removed nodes.

        c                 2    i | ]fd D             S )c                 (    h | ]}|         v |S r   r   r   keyr)   r&   s     r   r#   zUPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<dictcomp>.<setcomp>c   '    >>>345:+=+=3+=+=+=r   r   r   r&   r)   s    @r   
<dictcomp>zKPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<dictcomp>b   A     
 
 
CGD>>>>>%>>>
 
 
r   c              3   .   K   | ]\  }}|s|v |V  d S r   r   r   r&   childrenr*   s      r   r   zJPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<genexpr>e   sH       *
 *
h*
 !% 4 4  4 4 4 4*
 *
r   c                     | v S r   r   )r&   youngest_nodes_with_specss    r   r<   zIPrefixGraph.remove_youngest_descendant_nodes_with_specs.<locals>.<lambda>k   s    (A A r   )r)   r*   r'   itemsrA   rB   r,   )r-   inverted_graphremoved_nodesr&   r)   r*   rS   s       @@@r   +remove_youngest_descendant_nodes_with_specsz7PrefixGraph.remove_youngest_descendant_nodes_with_specsX   s     
(
 
 
 
KP
 
 
 %* *
 *
 *
 *
"0"6"6"8"8*
 *
 *
 %
 %
!
 AAAA4:NN
 
 " 	$ 	$Dd####r   c                 *    t          | j                  S r   )iterr)   )r-   s    r   r.   zPrefixGraph.recordsr   s    DJr   c                    | j         | j        t          | j                   }t                      	 fdD             }t          fd|                                D                       }|sn0|D ],}                    |           |                     |           -nt          t          fd|                    |                                  S )zPrune back all packages until all child nodes are anchored by a spec.

        Returns:
            tuple[PrefixRecord]: The pruned nodes.

        Tc                 2    i | ]fd D             S )c                 (    h | ]}|         v |S r   r   rI   s     r   r#   z/PrefixGraph.prune.<locals>.<dictcomp>.<setcomp>   s'    BBBstuSz/A/As/A/A/Ar   r   rL   s    @r   rM   z%PrefixGraph.prune.<locals>.<dictcomp>   sA       GKBBBBBeBBB  r   c              3   .   K   | ]\  }}|s|v|V  d S r   r   rP   s      r   r   z$PrefixGraph.prune.<locals>.<genexpr>   sH       # #"D(# %)$<$< $<$<$<$<# #r   c                     | v S r   r   )r&   rV   s    r   r<   z#PrefixGraph.prune.<locals>.<lambda>   s     5 r   )	r)   r*   r'   r(   rT   r?   rB   rA   r,   )r-   original_orderrU   prunable_nodesr&   r)   rV   r*   s        @@@r   prunezPrefixGraph.prunev   s*    
(tz**	(   OT  N # # # # #&4&:&:&<&<# # #  N
 " & ( (!!$'''!!$''''	( 5555~FF
 
 	r   c                 D    t          fd| j        D                       S )Nc              3   2   K   | ]}|j         k    |V  d S r   name)r   r    re   s     r   r   z/PrefixGraph.get_node_by_name.<locals>.<genexpr>   s/      BBCT1A1AC1A1A1A1ABBr   )nextr)   )r-   re   s    `r   get_node_by_namezPrefixGraph.get_node_by_name   s(    BBBB4:BBBBBBr   c                 j   | j         fdD             }|g}t                      d}|t          |          k     rW|||                  D ]0}|vr*                    |           |                    |           1|dz  }|t          |          k     Wt          t          fd                    S )Nc                 2    i | ]fd D             S )c                 (    h | ]}|         v |S r   r   rI   s     r   r#   z9PrefixGraph.all_descendants.<locals>.<dictcomp>.<setcomp>   rK   r   r   rL   s    @r   rM   z/PrefixGraph.all_descendants.<locals>.<dictcomp>   rN   r   r   r   c                     | v S r   r   r&   
nodes_seens    r   r<   z-PrefixGraph.all_descendants.<locals>.<lambda>       ); r   r)   r(   lenr?   appendr'   rA   )r-   r&   rU   nodesq
child_noder)   rm   s         @@r   r@   zPrefixGraph.all_descendants   s    

 
 
 
KP
 
 
 UU
#e**nn,U1X6 - -
Z//NN:...LL,,,FA #e**nn V;;;;UCCDDDr   c                 L   | j         }|g}t                      d}|t          |          k     rW|||                  D ]0}|vr*                    |           |                    |           1|dz  }|t          |          k     Wt          t          fd|                    S )Nr   r   c                     | v S r   r   rl   s    r   r<   z+PrefixGraph.all_ancestors.<locals>.<lambda>   rn   r   ro   )r-   r&   r)   rr   rs   parent_noderm   s         @r   all_ancestorszPrefixGraph.all_ancestors   s    
UU
#e**nn$U1X . .j00NN;///LL---FA #e**nn V;;;;UCCDDDr   c                    | j         }||vrt          d|z            |                    |           | j                            |d           |                                D ]\  }}||v r|                    |           dS )z/Removes this node and all edges referencing it.znode %s does not existN)r)   KeyErrorpopr*   rT   remove)r-   r&   r)   edgess       r   rB   zPrefixGraph._remove_node   s    
u3d:;;;		$dD))) ;;== 	# 	#KD%u}}T"""	# 	#r   c                 N   d | j                                         D             }|                     |           t          j        r#t          |                     |                    }n"t          |                     |                    }| j         fd|D             | _         |S )Nc                 4    i | ]\  }}|t          |          S r   r   r   r&   parentss      r   rM   z)PrefixGraph._toposort.<locals>.<dictcomp>   s&    XXXMD'dJw//XXXr   c                 "    i | ]}||         S r   r   )r   r&   original_graphs     r   rM   z)PrefixGraph._toposort.<locals>.<dictcomp>   s     JJJTdN40JJJr   )r)   rT   _toposort_prepare_graphr   allow_cyclesr'   _topo_sort_handle_cycles_toposort_raise_on_cycles)r-   
graph_copysorted_nodesr   s      @r   r,   zPrefixGraph._toposort   s    XXTZEUEUEWEWXXX
$$Z000 	M !>!>z!J!JKKLL !?!?
!K!KLLLJJJJ\JJJ
r   c              #   f  K   |sd S 	 t          t          d |                                D             d                     }|sn<|D ]}|V  |                    |d            |                                D ]}||z  }zt          |          dk    rt          t          |                    d S )NTc              3   F   K   | ]\  }}t          |          d k    |V  dS )r   N)rp   r   s      r   r   z8PrefixGraph._toposort_raise_on_cycles.<locals>.<genexpr>   s7      RRmdGGPQ@Q@QT@Q@Q@Q@QRRr   c                     | j         S r   rd   xs    r   r<   z7PrefixGraph._toposort_raise_on_cycles.<locals>.<lambda>   s    !& r   rJ   r   )r   sortedrT   r{   valuesrp   r
   r'   )clsr)   no_parent_nodesr&   r   s        r   r   z%PrefixGraph._toposort_raise_on_cycles   s       	F	+(RRu{{}}RRR((   O # ' & &


		$%%%% <<>> + +?*	+" u::??)%,,777 ?r   c              #   8  	K                                    D ]\  }}|                    |           d                                 D             	fdD             }t          	fd|D             d           }|E d {V  |                               }	 	 t          |          }|V  nj# t          $ rQ}t                              d|           | 	                              V  |                               }Y d }~ld }~wt          $ r Y d S w xY w)Nc                     h | ]	}|D ]}|
S r   r   )r   r   r&   s      r   r#   z7PrefixGraph._topo_sort_handle_cycles.<locals>.<setcomp>   s9     "
 "
 "
7"
 "
37D"
 "
 "
 "
r   c              3   ,   K   | ]}|         
|V  d S r   r   rL   s     r   r   z7PrefixGraph._topo_sort_handle_cycles.<locals>.<genexpr>   s,       K K$uT{ K K K K K K Kr   c              3   $   K   | ]
}|v|V  d S r   r   )r   r&   nodes_that_are_parentss     r   r   z7PrefixGraph._topo_sort_handle_cycles.<locals>.<genexpr>   s;        555 5555 r   c                     | j         S r   rd   r   s    r   r<   z6PrefixGraph._topo_sort_handle_cycles.<locals>.<lambda>   s    !& r   r   Tz%r)rT   discardr   r   r   rf   r
   logdebug_toposort_pop_keyStopIteration)
r   r)   kvnodes_without_parentsdisconnected_nodestvalueer   s
    `       @r   r   z$PrefixGraph._topo_sort_handle_cycles   s      KKMM 	 	DAqIIaLLLL"
 "
 %"
 "
 "
 !L K K K% K K K#   1  
 ! 
 
 
 &%%%%%%%))%00	Q*    		$"""++E2222211%88    	s   B1 1
D;ADDDc                     t          d |                                 D                       d         d         }|                     |           |                                 D ]}|                    |           |S )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   d   K   | ]+\  }}t          |          |                                |fV  ,d S r   )rp   dist_strr   s      r   r   z0PrefixGraph._toposort_pop_key.<locals>.<genexpr>  sL       *
 *
6CdGS\\4==??D1*
 *
 *
 *
 *
 *
r   r   r   )r   rT   r{   r   r   )r)   node_with_fewest_parentsr   s      r   r   zPrefixGraph._toposort_pop_key  s     $* *
 *
GL{{}}*
 *
 *
 $
 $

$$  			*+++||~~ 	6 	6GOO45555''r   c                    | D ]G}|j         dk    r:| |         }t          |          D ]"}|j         dk    r|                    |           #Ht          rt	          d | D             d           }t	          d | D             d           }|rC|J | |         }|                                 D ]"\  }}||v r||vr|                    |           #t	          d | D             d           }|rb| |         }|                                 D ]G\  }}t          |d          r.|j        t          j
        k    r||vr|                    |           Dd S d S d S )Npythonpipc              3   0   K   | ]}|j         d k    |V  dS )menuinstNrd   r   r&   s     r   r   z6PrefixGraph._toposort_prepare_graph.<locals>.<genexpr>2  s.      CC$49
+B+B+B+B+B+BCCr   c              3   0   K   | ]}|j         d k    |V  dS )r   Nrd   r   s     r   r   z6PrefixGraph._toposort_prepare_graph.<locals>.<genexpr>4  s.      PP$)x:O:O:O:O:O:OPPr   c              3   0   K   | ]}|j         d k    |V  dS )condaNrd   r   s     r   r   z6PrefixGraph._toposort_prepare_graph.<locals>.<genexpr>C  s.      NNg9M9Mt9M9M9M9MNNr   noarch)re   r'   r|   r	   rf   rT   r?   hasattrr   r   r   )	r)   r&   r   parentmenuinst_nodepython_nodemenuinst_parents
conda_nodeconda_parentss	            r   r   z#PrefixGraph._toposort_prepare_graph   s     	/ 	/DyH$$+#Gnn / /F{e++v...  	0 !CC%CCCT M PPPPPRVWWK 3 #...#(#7 %*[[]] 3 3MD'"g--$>N2N2NM222 NNNNNPTUUJ 	0 %j 1%*[[]] 0 0MD'h//0 K:+<<< 55J///A 	0  	0.	0 	00 0r   Nr   )__name__
__module____qualname____doc__r2   rE   rW   propertyr.   ra   rg   r@   rx   rB   r,   classmethodr   r   staticmethodr   r   r   r   r   r   r      s<           "# # #:  4     X   BC C CE E E"E E E
# 
# 
#	 	 	 8 8 [80 % % [%N ( ( \( ,0 ,0 \,0 ,0 ,0r   r   c                   *     e Zd ZdZd fd	Zd Z xZS )GeneralGrapha;  
    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
    r   c                    t          |          }t                                          ||           t          t                    | _        |D ]}| j                            |j        i           }t          d |j        D                       D ]H}|                    |j        t                                }|
                    |           |||j        <   I|| j        |j        <   i }t          t          | j                                                            D ]U\  }}|                    |j        t                                }	|	                    d |D                        |	||j        <   V|| _        d S )Nc              3   4   K   | ]}t          |          V  d S r   r   r   s     r   r   z(GeneralGraph.__init__.<locals>.<genexpr>  s(      @@aYq\\@@@@@@r   c              3   $   K   | ]}|j         V  d S r   rd   )r   _s     r   r   z(GeneralGraph.__init__.<locals>.<genexpr>  s$      33af333333r   )r'   superr2   r   dictspecs_by_namegetre   r+   r(   r?   reversedlistr)   rT   r>   graph_by_name)r-   r.   r/   r&   parent_dictdepdepsconsolidated_graphr0   cg	__class__s             r   r2   zGeneralGraph.__init__  sd   ..%((((.. 	8 	8D,00B??K@@4<@@@@@ - -"sx77(,CH%%,7Dty))"*4
0@0@0B0B+C+C"D"D 	/ 	/D,#''	35599BII33l333333,.ty))/r   c                 F   g }|                     |g           g }|r|                    d          }|d         }||v r%|                     |           ||k    r|S g }| j                            |j                  }|f|                                D ]'\  }	}
|                    t          |
                     (|D ]\}|j        |j        k    r|j        |j        k    r#t          |          }|                     |           |                     |           ]|dS dS )z/Return shorted path from root_spec to spec_namer   N)	rq   r{   r   r   re   rT   extendr   version)r-   	root_spectarget_specqueuevisitedpathr&   rQ   r/   r   r   adjnew_paths                r   breadth_first_search_by_namez)GeneralGraph.breadth_first_search_by_name  sJ   i[!!! 	+99Q<<D8DwNN4   {""H&**4955E} ;;== , ,4T

++++ + +8{///CK;CV4V4V#DzzHOOC(((LL****)  	+ 	+ 	+ 	+ 	+r   r   )r   r   r   r   r2   r   __classcell__)r   s   @r   r   r     sV         0 0 0 0 0 0(+ + + + + + +r   r   N)r   collectionsr   loggingr   boltons.setutilsr   ImportError_vendor.boltons.setutilsbase.contextr   common.compatr	   
exceptionsr
   enumsr   
match_specr   r   r   r   r   r   r   r   <module>r      sR    $ # # # # #      6+++++++ 6 6 6555555556 # " " " " " " " " " " " 0 0 0 0 0 0       ! ! ! ! ! !iq0 q0 q0 q0 q0 q0 q0 q0\5+ 5+ 5+ 5+ 5+; 5+ 5+ 5+ 5+ 5+s    %%