
    Fog                        d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ ddZ G d d      Zdd	Z	 d	 	 	 	 	 dd
Z	 	 	 	 	 	 	 	 	 	 	 	 ddZy)z^Graph manipulation utilities.

(dot generation adapted from pypy/translator/tool/make_dot.py)
    )annotationsN)Sequence)Anyc                   t         j                  j                  |       }t         j                  j                  t         j                  j	                  |             }t         j                  j                  |       d   dd }|||fS )zDTransforms /some/path/foo.png into ('/some/path', 'foo.png', 'png').   N)ospathbasenamedirnameabspathsplitext)filenamer   storedirtargets       ,lib/python3.12/site-packages/pylint/graph.pytarget_info_from_filenamer      sb    ww)Hwwrwwx89HWWh'+AB/FXv%%    c                      e Zd ZdZ	 	 	 	 	 	 d		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d
dZddZ ee      Z	 d	 	 	 	 	 ddZddZ	ddZ
ddZy)
DotBackendzDot File back-end.Nc                   |i }|| _         || _        g | _        d | _        | j	                  dt        |       d       |r| j	                  d|        |r| j	                  d|        |r| j	                  d| d       |r1|j                         dv s
J d|        | j	                  d	| d       |j                         D ]"  }| j	                  d
j                  |             $ y )Nzdigraph z {zrankdir=zratio=zsize="">   
iso-8859-1latin1utf-8zunsupported charset z	charset="=)		graphnamerendererlines_sourceemitnormalize_node_idloweritemsjoin)	selfr   rankdirsizeratiocharsetr   additional_paramparams	            r   __init__zDotBackend.__init__    s     #!"  "
#'		H.y9:#>?II	*+IIug&'IItfA&'==? '  0 &gY/	0 
 II	'!,-%++-EIIchhuo& .r   c                    | j                   3| j                  d       dj                  | j                        | _         | `| j                   S )zReturns self._source.z}

)r    r!   r%   r   )r&   s    r   
get_sourcezDotBackend.get_sourceA   s;    <<IIe99TZZ0DL
||r   c                d   d}| j                   }|_d}t        j                  d|      \  }}t        j                  d|      \  }}t        j                  |       t        j                  |       nPt        |      \  }	}	}|s
d}|dz   |z   }||vr/t        j                  d|      \  }}t        j                  |       n|}t        j                  |dd	      5 }
|
j                  | j                         ddd       ||vrt        j                  | j                        t        d
| d| j                   d      |r+t        j                  | j                  dd|d||d|g	d       n't        j                  | j                  d||d|gd       t        j                   |       |S # 1 sw Y   xY w)a+  Generates a graph file.

        :param str outputfile: filename and path [defaults to graphname.png]
        :param str mapfile: filename and path

        :rtype: str
        :return: a path to the generated file
        :raises RuntimeError: if the executable for rendering was not found
        )dotgvNpngz.gvz.png.wutf8)encodingzCannot generate `z` because 'zg' executable not found. Install graphviz, or specify a `.gv` outputfile to produce the DOT source code.z-Tcmapxz-oz-TT)check)r   tempfilemkstempr	   closer   codecsopenwritesourceshutilwhichr   RuntimeError
subprocessrununlink)r&   
outputfilemapfilegraphviz_extensionsnamer   pdotdot_sourcepathppng_files              r   generatezDotBackend.generateK   s    ,~~F#+#3#3E4#@ D.'//=D*HHTNHHTN4Z@LAq&'#-6
00'/'7'7t'D$n!+[[v>$JJt{{# ?,,||DMM*2"'
|;t}}o NA A 
 !&"
  ]]D&.$
S IIn%= ?>s   F&&F/c                :    | j                   j                  |       y)zAdds <line> to final output.N)r   append)r&   lines     r   r!   zDotBackend.emit   s    

$r   c                    |j                         D cg c]  \  }}| d| d }}}t        |      t        |      }}| j                  | d| ddj                  t	        |             d       yc c}}w )z}Emit an edge from <name1> to <name2>.

        For edge properties: see https://www.graphviz.org/doc/info/attrs.html
        ="r   z ->  [, ];N)r$   r"   r!   r%   sorted)	r&   name1name2propspropvalueattrsn_fromn_tos	            r   	emit_edgezDotBackend.emit_edge   sv    
 9>FuD6E7!$F(/1B51I		VHDb6%=)A(B"EF Gs   A2c           	         |j                         D cg c]  \  }}| d| d }}}| j                  t        |       ddj                  t	        |             d       yc c}}w )zzEmit a node with given properties.

        For node properties: see https://www.graphviz.org/doc/info/attrs.html
        rU   r   rV   rW   rX   N)r$   r!   r"   r%   rY   )r&   rJ   r\   r]   r^   r_   s         r   	emit_nodezDotBackend.emit_node   sc    
 9>FuD6E7!$F		&t,-R		&-0H/ILM Gs   A")NNNr   r2   N)r   strr'   
str | Noner(   r   r)   r   r*   re   r   re   r+   zdict[str, Any] | NonereturnNone)rg   re   )NN)rG   rf   rH   rf   rg   re   )rS   re   rg   rh   )rZ   re   r[   re   r\   r   rg   rh   )rJ   re   r\   r   rg   rh   )__name__
__module____qualname____doc__r-   r0   propertyr@   rP   r!   rb   rd    r   r   r   r      s    
 #26'' ' 	'
 ' ' ' 0' 
'B j!F DH=$=6@=	=~ GNr   r   c                    d|  dS )z)Returns a suitable DOT node id for `nid`.r   rn   )nids    r   r"   r"      s    se1:r   c                    | syg }|t        | j                               }|D ]  }t        | g t               ||        |S )zReturn a list of detected cycles based on an ordered graph (i.e. keys are
    vertices and values are lists of destination vertices representing edges).
    rn   )listkeys_get_cyclesset)
graph_dictverticesresultvertices       r   
get_cyclesrz      sG      F
)*JCE67; Mr   c                   ||v rf|g}|ddd   D ]  }||k(  r n|j                  d|        t        |      }|j                  |      }||d |d| z   }||vr|j                  |       y|j                  |       	 | |   D ]'  }||vst	        | ||||       |j                  |       ) 	 |j                          y# t        $ r Y w xY w)z6Recursive function doing the real work for get_cycles.Nr   r   )insertminindexrR   rt   addKeyErrorpop)	rv   r
   visitedrx   ry   cyclenode
start_fromr~   s	            r   rt   rt      s     $	2JDwLLD! 
 Z
J'efa.MM% KKw'D7"JgvtDD!	 ( 	HHJ  s   =B> 
"B> >	C
	C
)r   re   rg   ztuple[str, str, str])rp   re   rg   re   )N)rv   dict[str, set[str]]rw   zlist[str] | Nonerg   zSequence[list[str]])rv   r   r
   z	list[str]r   zset[str]rx   zlist[list[str]]ry   re   rg   rh   )rl   
__future__r   r=   r	   rA   rD   r:   collections.abcr   typingr   r   r   r"   rz   rt   rn   r   r   <module>r      s   

 #  	    $ &@N @NF CG#/? #
  	
  
r   