ó
Ý²k^c           @` sö   d  d l  m Z m Z m Z 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 m Z d d	 l m Z d d
 l m Z m Z m Z m Z d d l m Z e	 e ƒ Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   i    (   t   absolute_importt   divisiont   print_functiont   unicode_literals(   t   defaultdictt   OrderedDict(   t	   getLoggeri   (   t
   NoarchType(   t	   MatchSpeci   (   t
   IndexedSet(   t   context(   t	   iteritemst
   itervaluest   odictt   on_win(   t   CyclicalDependencyErrort   PrefixGraphc           B` s­   e  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 RS(   uR  
    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         ` s¿   t  | ƒ } t | ƒ } i  |  _ } i  |  _ } x| | D]t ‰  t  d „  ˆ  j Dƒ ƒ ‰ t ‡ f d †  | Dƒ ƒ } | | ˆ  <t ‡  f d †  | Dƒ ƒ } | r9 | | ˆ  <q9 q9 W|  j ƒ  d  S(   Nc         s` s   |  ] } t  | ƒ Vq d  S(   N(   R   (   t   .0t   d(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>'   s    c         3` s1   |  ]' ‰  t  ‡  f d  †  ˆ Dƒ ƒ r ˆ  Vq d S(   c         3` s   |  ] } | j  ˆ  ƒ Vq d  S(   N(   t   match(   R   t   m(   t   rec(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>*   s    N(   t   any(   R   (   t   parent_match_specs(   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>)   s    c         3` s$   |  ] } | j  ˆ  ƒ r | Vq d  S(   N(   R   (   R   t   s(   t   node(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>-   s    (   t   tuplet   sett   grapht   spec_matchest   dependsR	   t	   _toposort(   t   selft   recordst   specsR   R   t   parent_nodest   matching_specs(    (   R   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   __init__!   s    
c         ` sþ   t  ‡ f d †  |  j Dƒ ƒ } xL ˆ j d ƒ p4 d D]5 } t d | ƒ ‰  | j ‡  f d †  |  j Dƒ ƒ q5 Wt  ƒ  ‰ x1 | D]) } ˆ j | ƒ ˆ j |  j | ƒ ƒ q~ Wt t ‡ f d †  |  j ƒ ƒ ‰ x ˆ D] } |  j	 | ƒ qÓ W|  j
 ƒ  t ˆ ƒ S(   uÀ   
        Remove all matching nodes, and any associated child nodes.

        Args:
            spec (MatchSpec):

        Returns:
            Tuple[PrefixRecord]: The removed nodes.

        c         3` s$   |  ] } ˆ  j  | ƒ r | Vq d  S(   N(   R   (   R   R   (   t   spec(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>>   s    u   track_featurest   featuresc         3` s$   |  ] } ˆ  j  | ƒ r | Vq d  S(   N(   R   (   R   R   (   t   feature_spec(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>D   s    c         ` s
   |  ˆ  k S(   N(    (   R   (   t   remove_these(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   <lambda>K   s    (    (   R   R   t   get_raw_valueR   t   updatet   addt   all_descendantsR   t   filtert   _remove_nodeR   (   R    R&   t   node_matchest   feature_nameR   (    (   R(   R)   R&   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   remove_spec3   s    $	
c         ` s—   |  j  ‰  |  j ‰ ‡  f d †  ˆ  Dƒ } t ‡ f d †  t | ƒ Dƒ ƒ ‰ t t ‡ f d †  |  j  ƒ ƒ } x | D] } |  j | ƒ qr W|  j ƒ  | S(   u¥   
        A specialized method used to determine only dependencies of requested specs.

        Returns:
            Tuple[PrefixRecord]: The removed nodes.

        c         ` s2   i  |  ]( ‰  t  ‡ ‡  f d  †  ˆ Dƒ ƒ ˆ  “ q S(   c         3` s%   |  ] } ˆ ˆ  | k r | Vq d  S(   N(    (   R   t   key(   R   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>^   s    (   R   (   R   (   R   (   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys
   <dictcomp>^   s   	c         3` s.   |  ]$ \ } } | r | ˆ  k r | Vq d  S(   N(    (   R   R   t   children(   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>a   s    	c         ` s
   |  ˆ  k S(   N(    (   R   (   t   youngest_nodes_with_specs(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   d   s    (   R   R   R   R   R/   R0   R   (   R    t   inverted_grapht   removed_nodesR   (    (   R   R   R6   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt+   remove_youngest_descendant_nodes_with_specsS   s    		
"
c         C` s   t  |  j ƒ S(   N(   t   iterR   (   R    (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR!   l   s    c         ` sÐ   |  j  ‰  |  j ‰ t |  j  ƒ } t ƒ  ‰ xw t r£ ‡  f d †  ˆ  Dƒ } t ‡ f d †  t | ƒ Dƒ ƒ } | su Pn  x( | D]  } ˆ j | ƒ |  j | ƒ q| Wq- Wt t ‡ f d †  | ƒ ƒ ‰ |  j	 ƒ  ˆ S(   u”   Prune back all packages until all child nodes are anchored by a spec.

        Returns:
            Tuple[PrefixRecord]: The pruned nodes.

        c         ` s2   i  |  ]( ‰  t  ‡ ‡  f d  †  ˆ Dƒ ƒ ˆ  “ q S(   c         3` s%   |  ] } ˆ ˆ  | k r | Vq d  S(   N(    (   R   R4   (   R   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>~   s    (   R   (   R   (   R   (   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys
   <dictcomp>~   s   	c         3` s.   |  ]$ \ } } | r | ˆ  k r | Vq d  S(   N(    (   R   R   R5   (   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>   s    	c         ` s
   |  ˆ  k S(   N(    (   R   (   R8   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   Š   s    (
   R   R   R   R   t   TrueR   R-   R0   R/   R   (   R    t   original_orderR7   t   prunable_nodesR   (    (   R   R8   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   prunep   s$    				
"
c         ` s   t  ‡  f d †  |  j Dƒ ƒ S(   Nc         3` s$   |  ] } | j  ˆ  k r | Vq d  S(   N(   t   name(   R   R   (   R?   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>‘   s    (   t   nextR   (   R    R?   (    (   R?   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   get_node_by_name   s    c         ` s¸   |  j  ‰  ‡  f d †  ˆ  Dƒ } | g } t ƒ  ‰ d } xb | t | ƒ k  r› x? | | | D]/ } | ˆ k r[ ˆ j | ƒ | j | ƒ q[ q[ W| d 7} q: Wt t ‡ f d †  ˆ  ƒ ƒ S(   Nc         ` s2   i  |  ]( ‰  t  ‡ ‡  f d  †  ˆ Dƒ ƒ ˆ  “ q S(   c         3` s%   |  ] } ˆ ˆ  | k r | Vq d  S(   N(    (   R   R4   (   R   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>–   s    (   R   (   R   (   R   (   R   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys
   <dictcomp>–   s   	i    i   c         ` s
   |  ˆ  k S(   N(    (   R   (   t
   nodes_seen(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   ¥   s    (   R   R   t   lenR-   t   appendR   R/   (   R    R   R7   t   nodest   qt
   child_node(    (   R   RB   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR.   “   s     	
		c         ` s¢   |  j  } | g } t ƒ  ‰  d } xb | t | ƒ k  r… x? | | | D]/ } | ˆ  k rE ˆ  j | ƒ | j | ƒ qE qE W| d 7} q$ Wt t ‡  f d †  | ƒ ƒ S(   Ni    i   c         ` s
   |  ˆ  k S(   N(    (   R   (   RB   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   ·   s    (   R   R   RC   R-   RD   R   R/   (   R    R   R   RE   RF   t   parent_node(    (   RB   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   all_ancestorsª   s    			c         C` s…   |  j  } | | k r( t d | ƒ ‚ n  | j | ƒ |  j j | d ƒ x6 t | ƒ D]( \ } } | | k rU | j | ƒ qU qU Wd S(   u1    Removes this node and all edges referencing it. u   node %s does not existN(   R   t   KeyErrort   popR   t   NoneR   t   remove(   R    R   R   t   edges(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR0   ¼   s    	c         ` sŽ   t  d „  t |  j ƒ Dƒ ƒ } |  j | ƒ t j rM t |  j | ƒ ƒ } n t |  j | ƒ ƒ } |  j ‰  t  ‡  f d †  | Dƒ ƒ |  _ | S(   Nc         s` s'   |  ] \ } } | t  | ƒ f Vq d  S(   N(   R	   (   R   R   t   parents(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>É   s    c         3` s   |  ] } | ˆ  | f Vq d  S(   N(    (   R   R   (   t   original_graph(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>Ð   s    (	   R   R   R   t   _toposort_prepare_graphR
   t   allow_cyclesR   t   _topo_sort_handle_cyclest   _toposort_raise_on_cycles(   R    t
   graph_copyt   sorted_nodes(    (   RP   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR   È   s    		c         c` s¾   | s
 d  Sx† t  r’ t t d „  t | ƒ Dƒ d d „  ƒƒ } | sH Pn  x# | D] } | V| j | d  ƒ qO Wx t | ƒ D] } | | 8} q{ Wq Wt | ƒ d k rº t t	 | ƒ ƒ ‚ n  d  S(   Nc         s` s-   |  ]# \ } } t  | ƒ d  k r | Vq d S(   i    N(   RC   (   R   R   RO   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>Ú   s    R4   c         S` s   |  j  S(   N(   R?   (   t   x(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   Û   s    i    (
   R;   R	   t   sortedR   RK   RL   R   RC   R   R   (   t   clsR   t   no_parent_nodesR   RO   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyRT   Ó   s    	c   
      #` s#  x' t  ˆ  ƒ D] \ } } | j | ƒ q Wt d „  t ˆ  ƒ Dƒ ƒ ‰ ‡  f d †  ˆ  Dƒ } t ‡ f d †  | Dƒ d d „  ƒ} x | D] } | Vqˆ W|  j ˆ  ƒ } xv t ry t | ƒ } | VWq© t k
 r	}	 t	 j
 d |	 ƒ |  j ˆ  ƒ V|  j ˆ  ƒ } q© q© t k
 rd  SXq© Wd  S(   Nc         s` s"   |  ] } | D] } | Vq q d  S(   N(    (   R   RO   R   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>ñ   s    c         3` s   |  ] } ˆ  | s | Vq d  S(   N(    (   R   R   (   R   (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>ò   s    c         3` s!   |  ] } | ˆ  k r | Vq d  S(   N(    (   R   R   (   t   nodes_that_are_parents(    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>ô   s    R4   c         S` s   |  j  S(   N(   R?   (   RW   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR*   õ   s    u   %r(   R   t   discardR   R   RX   RT   R;   R@   R   t   logt   debugt   _toposort_pop_keyt   StopIteration(
   RY   R   t   kt   vt   nodes_without_parentst   disconnected_nodesR   t   tt   valuet   e(    (   R   R[   s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyRS   ê   s*    			c         C` sY   t  d „  t |  ƒ Dƒ ƒ d d } |  j | ƒ x! t |  ƒ D] } | j | ƒ q> W| S(   u    
        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         s` s0   |  ]& \ } } t  | ƒ | j ƒ  | f Vq d  S(   N(   RC   t   dist_str(   R   R   RO   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>  s    i    i   (   RX   R   RK   R   R\   (   R   t   node_with_fewest_parentsRO   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR_     s    c   	      C` s’  x` |  D]X } | j  d k r |  | } x6 t | ƒ D]% } | j  d k r3 | j | ƒ q3 q3 Wq q Wt rŽt d „  |  Dƒ d  ƒ } t d „  |  Dƒ d  ƒ } | r| d  k	 s³ t ‚ |  | } xE t |  ƒ D]4 \ } } | | k rÊ | | k rÊ | j | ƒ qÊ qÊ Wn  t d „  |  Dƒ d  ƒ } | rŽ|  | } xZ t |  ƒ D]I \ } } t	 | d ƒ r;| j
 t j k r;| | k r;| j | ƒ q;q;WqŽn  d  S(   Nu   pythonu   pipc         s` s$   |  ] } | j  d  k r | Vq d S(   u   menuinstN(   R?   (   R   R   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>.  s    c         s` s$   |  ] } | j  d  k r | Vq d S(   u   pythonN(   R?   (   R   R   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>/  s    c         s` s$   |  ] } | j  d  k r | Vq d S(   u   condaN(   R?   (   R   R   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>>  s    u   noarch(   R?   R   RM   R   R@   RL   t   AssertionErrorR   R-   t   hasattrt   noarchR   t   python(	   R   R   RO   t   parentt   menuinst_nodet   python_nodet   menuinst_parentst
   conda_nodet   conda_parents(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyRQ     s,    


!(    (   t   __name__t
   __module__t   __doc__R%   R3   R9   t   propertyR!   R>   RA   R.   RI   R0   R   t   classmethodRT   RS   t   staticmethodR_   RQ   (    (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR      s   	 		 					#t   GeneralGraphc           B` s#   e  Z d  Z d d „ Z d „  Z RS(   u;  
    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   
      C` s>  t  | ƒ } t t |  ƒ j | | ƒ t t ƒ |  _ x | D]‡ } |  j j | j t	 ƒ  ƒ } xS t  d „  | j
 Dƒ ƒ D]8 } | j | j t ƒ  ƒ } | j | ƒ | | | j <qv W| |  j | j <q; Wt	 ƒ  } x_ t |  j j ƒ  ƒ D]H \ } } | j | j t ƒ  ƒ }	 |	 j d „  | Dƒ ƒ |	 | | j <qå W| |  _ d  S(   Nc         s` s   |  ] } t  | ƒ Vq d  S(   N(   R   (   R   R   (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>Ž  s    c         s` s   |  ] } | j  Vq d  S(   N(   R?   (   R   t   _(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pys	   <genexpr>˜  s    (   R   t   superRz   R%   R   t   dictt   specs_by_namet   getR?   R   R   R   R-   t   reversedR   t   itemsR,   t   graph_by_name(
   R    R!   R"   R   t   parent_dictt   dept   depst   consolidated_graphR#   t   cg(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyR%   ˆ  s      	"c         C` s0  g  } | j  | g ƒ g  } x| r+| j d ƒ } | d } | | k rP q n  | j  | ƒ | | k rm | Sg  } |  j j | j ƒ } | d k rš q n  x- | j ƒ  D] \ }	 }
 | j t |
 ƒ ƒ q§ Wx[ | D]S } | j | j k rþ | j	 | j	 k rþ qÑ t | ƒ } | j  | ƒ | j  | ƒ qÑ Wq Wd S(   u/   Return shorted path from root_spec to spec_namei    iÿÿÿÿN(
   RD   RK   R~   R   R?   RL   R   t   extendt   listt   version(   R    t	   root_spect   target_spect   queuet   visitedt   pathR   R5   R"   R{   R…   t   adjt   new_path(    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   breadth_first_search_by_nameœ  s.    	
$(    (   Rt   Ru   Rv   R%   R’   (    (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyRz   €  s   N(   t
   __future__R    R   R   R   t   collectionsR   R   t   loggingR   t   enumsR   t
   match_specR   t   _vendor.boltons.setutilsR	   t   base.contextR
   t   common.compatR   R   R   R   t
   exceptionsR   Rt   R]   t   objectR   Rz   (    (    (    s8   lib/python2.7/site-packages/conda/models/prefix_graph.pyt   <module>   s   ""ÿ n