U
    Z+dQ#                     @   sn   d Z ddlmZ ddlmZ ddlmZmZ dZG dd dZ	G dd	 d	e
ZG d
d dZG dd dZdS )z Dependency graph implementation.    )Counter)dedent)bytes_to_strsafe_str)DOT
CycleErrorDependencyGraphGraphFormatterc                   @   s6   e Zd ZdZedZdZdZdZdZ	ddd	Z
d
ZdS )r   z$Constants related to the dot format.z=
        {IN}{type} {id} {{
        {INp}graph [{attrs}]
    z{name}={value}z{INp}"{0}" [{attrs}]z {INp}"{0}" {dir} "{1}" [{attrs}]z, z--z->)graphdigraphz{IN}}}N)__name__
__module____qualname____doc__r   HEADATTRNODEEDGEATTRSEPDIRSTAIL r   r   6/tmp/pip-unpacked-wheel-ucduq0nd/celery/utils/graph.pyr   
   s   
r   c                   @   s   e Zd ZdZdS )r   z)A cycle was detected in an acyclic graph.N)r   r   r   r   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZd+ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zd,ddZdd Zdd Zdd Zdd  Zd!d" Zd#d$ Ze ZZd%d& Zd-d)d*ZdS ).r   a6  A directed acyclic graph of objects and their dependencies.

    Supports a robust topological sort
    to detect the order in which they must be handled.

    Takes an optional iterator of ``(obj, dependencies)``
    tuples to build the graph from.

    Warning:
        Does not support cycle detection.
    Nc                 C   s(   |pt  | _i | _|d k	r$| | d S N)r	   	formatteradjacentupdate)selfitr   r   r   r   __init__*   s    zDependencyGraph.__init__c                 C   s   | j |g  dS )zAdd an object to the graph.N)r   
setdefaultr   objr   r   r   add_arc0   s    zDependencyGraph.add_arcc                 C   s   | |  | dS )z]Add an edge from object ``A`` to object ``B``.

        I.e. ``A`` depends on ``B``.
        N)append)r   ABr   r   r   add_edge4   s    zDependencyGraph.add_edgec                 C   s   | j |j  dS )zAdd nodes from another graph.N)r   r   )r   r
   r   r   r   connect;   s    zDependencyGraph.connectc           	      C   s~   t  }|  }dd |D }|D ]}|| q | D ]6}|| }| | D ] }|| }||krH||| qHq4dd | D S )zSort the graph topologically.

        Returns:
            List: of objects in the order in which they must be handled.
        c                 S   s   i | ]}|D ]
}||qqS r   r   ).0	componentnoder   r   r   
<dictcomp>H   s
       z+DependencyGraph.topsort.<locals>.<dictcomp>c                 S   s   g | ]}|d  qS )r   r   )r)   tr   r   r   
<listcomp>S   s     z+DependencyGraph.topsort.<locals>.<listcomp>)r   	_tarjan72r#   r'   _khan62)	r   r
   
componentsZNCr*   r+   Znode_c	successorZsuccessor_cr   r   r   topsort?   s    zDependencyGraph.topsortc                 C   sP   zt | | g}W n tk
r(   Y dS X | | D ]}|| | q2t|S )z5Return the valency (degree) of a vertex in the graph.r   )lenKeyErrorr$   
valency_ofsum)r   r"   lr+   r   r   r   r6   U   s    zDependencyGraph.valency_ofc                 C   sH   t |}|D ]\}}| | q|D ]\}}|D ]}| || q0q$dS )z=Update graph with data from a list of ``(obj, deps)`` tuples.N)listr#   r'   )r   r   Ztupsr"   _depsdepr   r   r   r   _   s    zDependencyGraph.updatec                 C   s   dd |   D S )z8Return generator that yields for all edges in the graph.c                 s   s   | ]\}}|r|V  qd S r   r   )r)   r"   Zadjr   r   r   	<genexpr>j   s      z(DependencyGraph.edges.<locals>.<genexpr>)itemsr   r   r   r   edgesh   s    zDependencyGraph.edgesc                    s   t   g }| D ]"}| | D ]} |  d7  < qq fdd| D }|r| }|| | | D ]*} |  d8  <  | dkrb|| qbqD|  |S )zPerform Khan's simple topological sort algorithm from '62.

        See https://en.wikipedia.org/wiki/Topological_sorting
           c                    s   g | ]} | s|qS r   r   )r)   r+   countr   r   r.   w   s      z+DependencyGraph._khan62.<locals>.<listcomp>r   )r   popr$   reverse)r   resultr+   r2   readyr   rB   r   r0   l   s    
zDependencyGraph._khan62c                    s:   g g i     fddD ]}| q(S )zPerform Tarjan's algorithm to find strongly connected components.

        See Also:
            :wikipedia:`Tarjan%27s_strongly_connected_components_algorithm`
        c                    s   |  krd S t  }| | < t }|  |  D ]"}| t |   |  | < q6| |  krt|d  }g |d < | |D ]}t  |< qd S r   )r4   r$   mintuple)r+   numZ	stack_posr2   r*   itemlowrF   r   stackvisitr   r   rO      s    

z(DependencyGraph._tarjan72.<locals>.visitr   r   r+   r   rL   r   r/      s
    
zDependencyGraph._tarjan72c                    s   t  |p| jfdd  fdd}   |  D ]>\}}|sX|j| |D ] }|j|  || q\q@   dS )zConvert the graph to DOT format.

        Arguments:
            fh (IO): A file, or a file-like object to write the graph to.
            formatter (celery.utils.graph.GraphFormatter): Custom graph
                formatter to use.
        c                    s   t t|  d d S )N)file)printr   )s)fhr   r   P   s    z!DependencyGraph.to_dot.<locals>.Pc                    s.    |kr* | |  | d S r   )labeladd)Zfunr"   )rU   drawseenr   r   if_not_seen   s    z+DependencyGraph.to_dot.<locals>.if_not_seenN)setr   headr>   terminal_noder+   edgetail)r   rT   r   rZ   r"   r   reqr   )rU   rX   rT   rY   r   to_dot   s    
zDependencyGraph.to_dotc                 C   s   | j r|  |S |S r   )r   r!   r   r   r   format   s    zDependencyGraph.formatc                 C   s
   t | jS r   )iterr   r?   r   r   r   __iter__   s    zDependencyGraph.__iter__c                 C   s
   | j | S r   r   rP   r   r   r   __getitem__   s    zDependencyGraph.__getitem__c                 C   s
   t | jS r   )r4   r   r?   r   r   r   __len__   s    zDependencyGraph.__len__c                 C   s
   || j kS r   re   r!   r   r   r   __contains__   s    zDependencyGraph.__contains__c                 C   s
   | j  S r   )r   r>   r?   r   r   r   _iterate_items   s    zDependencyGraph._iterate_itemsc                    s   d  fdd D S )N
c                 3   s   | ]}  |V  qd S r   )	repr_node)r)   Nr?   r   r   r=      s     z+DependencyGraph.__repr__.<locals>.<genexpr>)joinr?   r   r?   r   __repr__   s    zDependencyGraph.__repr__rA   {0}({1})c                 C   s|   | || |g}|| krr| | D ]L}| || |}|d| |  || ||d ddd   q$d|S )Nz     rA   rj   )rb   r6   r$   extendrk   splitrm   )r   r"   levelfmtoutputotherdr   r   r   rk      s    &zDependencyGraph.repr_node)NN)N)rA   ro   )r   r   r   r   r   r#   r'   r(   r3   r6   r   r@   r0   r/   ra   rb   rd   rf   rg   rh   ri   r>   	iteritemsrn   rk   r   r   r   r   r      s*   

	 
r   c                   @   s   e Zd ZdZej Zej Z	ej
 Zej Zej ZejZeejZdddddZddd	d
ZdddZdddZddiZd/ddZdd Zd0ddZdd Zdd Zdd  Zd!d" Z d#d$ Z!d%d& Z"d'd( Z#d)d* Z$d1d+d,Z%d2d-d.Z&dS )3r	   zFormat dependency graphs.ZboxZveeZfilledZHelveticaNeue)shapeZ	arrowheadstyleZfontnameZdarkseagreen4Zblackgffffff?)colorZ
arrowcolorZ	arrowsizeZ
palegreen3Z
palegreen4)Z	fillcolorrz   Z
palegreen1Z
palegreen2ZbgcolorZ	mintcreamNr       c                 K   sn   |pd| _ || _|pd| _| j| j | _||p0d | _| j| | _t| jf|| _t| j	| 
| jd| _	d S )NZdependenciesr   r   )root)idr|   type_dirs	directionININpdictschemegraph_schemerV   )r   r|   r~   r}   indentZinwr   r   r   r   r      s    

zGraphFormatter.__init__c                 C   s   d| d}| j | j||dS )N")namevalue)FMT_attr)r   r   r   r   r   r   attr  s    zGraphFormatter.attrc                    s@   t  jf|rt |f|pi n|} j fdd| D S )Nc                 3   s"   | ]\}}t  ||V  qd S r   )r   r   )r)   kvr?   r   r   r=     s    z'GraphFormatter.attrs.<locals>.<genexpr>)r   r   _attrseprm   r>   )r   rv   r   r   r?   r   attrs	  s    "zGraphFormatter.attrsc                 K   s"   | j | j| j| j| || jdS )N)r}   r~   r   )r   _headr}   r~   r   r   )r   r   r   r   r   r\     s      zGraphFormatter.headc                 C   s   |  | jS r   )r   _tailr?   r   r   r   r_     s    zGraphFormatter.tailc                 C   s   |S r   r   r!   r   r   r   rV     s    zGraphFormatter.labelc                 K   s   |  || j|S r   )	draw_nodenode_schemer   r"   r   r   r   r   r+     s    zGraphFormatter.nodec                 K   s   |  || j|S r   )r   term_schemer   r   r   r   r]     s    zGraphFormatter.terminal_nodec                 K   s   | j ||f|S r   )	draw_edge)r   abr   r   r   r   r^   !  s    zGraphFormatter.edgec                 C   s   | ddS )Nzutf-8ignore)encode)r   rS   r   r   r   _enc$  s    zGraphFormatter._encc              	   O   s    |  |j|t|| j| jdS )N)r   r   )r   rb   r   r   r   )r   rs   argskwargsr   r   r   r   '  s     zGraphFormatter.FMTc              	   C   s.   | j | j| || || j| || jdS )N)dirr   )r   _edgerV   r   r   edge_scheme)r   r   r   r   r   r   r   r   r   ,  s       zGraphFormatter.draw_edgec                 C   s    | j | j| || ||dS )N)r   )r   _noderV   r   )r   r"   r   r   r   r   r   r   2  s
      
zGraphFormatter.draw_node)NNNr   r{   )N)NN)NN)'r   r   r   r   r   r   stripr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r\   r_   rV   r+   r]   r^   r   r   r   r   r   r   r   r   r	      sH   







    


r	   N)r   collectionsr   textwrapr   Zkombu.utils.encodingr   r   __all__r   	Exceptionr   r   r	   r   r   r   r   <module>   s    D