a
    aRo                     @   s  d dl mZ d dl mZ d dlmZ d dlZd dlmZmZ dZ	dd Z
dCd
dZdDddZg dddfddZdEddZejejfejejejejejdejejfejejejejejdededfejdddededededededed fejejd!ed"ed#fejdddejdddejdddejdddejdddejdddejdddejd ddfejejd!d$d%d%d%d%d%dd&Zd'd(d)d*d+d,d-d.d+d/d0d+d1d-d2Zd3d4 Zd5d6 ZdFd7d8ZdGd:d;Zd<d= Z dHdAdBZ!dS )I    )print_function)division)colourN)cyclegroupby
   c                 C   s   t | dk r| S | dd} g }| dD ]}t |dkrd|dd v r\|dd\}}n2t |d }t || }|d	| ||d	  }}||d  q.|r*|| q*d
|S )zBreak DNs over multiple lines, for better shaped and arguably more
    readable nodes. We try to split after commas, and if necessary
    after hyphens or failing that in arbitrary places.   ,z,

   -      Nz\n)lenreplacesplitappendjoin)spiecespqnb r   -/usr/lib/python3/dist-packages/samba/graph.pyreformat_graph_label   s    r   Fc                 C   s    |  dd} |rt| } d|  S )z%Escape a string as graphvis requires."z%s)r   r   )r   Zreformatr   r   r   quote_graph_label6   s    r   ,...c           
         s  t dd | D }g }t|dkrd t| }z:t fdd|D }t|dksld|v rbql d8  q6W n ty   ||f Y S 0  d7  |d } t|k r|  dkr d7  q t| kr||fS ||| d	 f | D ]\}}	|	d	  | ||< q|r| D ]}	d
|	vr qTqt dd | D }|d | D ]}	|	ds\ qq\t dd | D }|d ||fS )a~  Replace the common suffix (in practice, the base DN) of a number of
    vertices with a short string (default ",..."). If this seems
    pointless because the replaced string is very short or the results
    seem strange, the original vertices are retained.

    :param vertices: a sequence of vertices to shorten
    :param suffix: the replacement string [",..."]
    :param aggressive: replace certain common non-suffix strings

    :return: tuple of (rename map, replacements)

    The rename map is a dictionary mapping the old vertex names to
    their shortened versions. If no changes are made, replacements
    will be empty.
    c                 s   s   | ]}||fV  qd S Nr   .0vr   r   r   	<genexpr>P       z'shorten_vertex_names.<locals>.<genexpr>r   c                 3   s   | ]}|  V  qd S r    r   r"   xir   r   r$   Z   r%   *r   r	   N,CN=Servers,c                 s   s$   | ]\}}|| d ddfV  qdS )r,   z,**,r   Nr   r"   kr#   r   r   r   r$   {   s   )z**z
CN=ServersCN=NTDS Settings,c                 s   s$   | ]\}}|| d ddfV  qdS )r0   z*,r   Nr-   r.   r   r   r   r$      s   )r+   zCN=NTDS Settings)	dictr   listvaluesset
IndexErrorr   items
startswith)
verticessuffix
aggressivevmapreplacementsvlistcr(   r/   r#   r   r)   r   shorten_vertex_names@   sJ    





r?   Zkey_r   c              	   C   s  g }g }g }g }g }	t | D ]\}
}|\}}}d||
f }t|}d| }|rx|	| || |d|||f  q|| d| }d| }|	| |d|  |d||f  |d||f  |d	|||f  |d
|||f  |d qd}|rt t|D ]f\}
}|	d|
  |\}}|d dkrj|d dkrj|dd }|dd }|d|
||f 7 }qg }|	r|D ]}|d||	d f  qdd|d|d||d|d|	f }|S )a  Generate a dot file snippet that acts as a legend for a graph.

    :param key_items: sequence of items (is_vertex, style, label)
    :param nodes_above: list of vertices (pushes key into right position)
    :param elision: tuple (short, full) indicating suffix replacement
    :param prefix: string used to generate key node names ["key_"]
    :param width: default width of node lines

    Each item in key_items is a tuple of (is_vertex, style, label).
    is_vertex is a boolean indicating whether the item is a vertex
    (True) or edge (False). Style is a dot style string for the edge
    or vertex. label is the text associated with the key item.
    z%s%d_z%s_labelz%s[label="%s"; %s]z%se1z%se2zsubgraph cluster_%s {z,%s[label=src; color="#000000"; group="%s_g"]z-%s[label=dest; color="#000000"; group="%s_g"]z!%s -> %s [constraint = false; %s]z8%s[shape=plaintext; style=solid; width=%f; label="%s\r"]} z	elision%dr   r	   r   NuO   
elision%d[shape=plaintext; style=solid; label="\“%s”  means  “%s”\r"]
z"%s" -> %s [style=invis]zsubgraph cluster_key {
label="Key";
subgraph cluster_key_nodes {
label="";
color = "invis";
%s
}
subgraph cluster_key_edges {
label="";
color = "invis";
%s
{%s}
}
%s
}
%s
%s [style=invis; weight=9]
z;
r
    z -> )	enumerater   r   reversedr   )	key_itemsnodes_aboveelisionsprefixwidthZ
edge_linesZ
edge_namesZvertex_linesZvertex_namesZorder_linesr*   itemZ	is_vertexZstylelabeltagnameZe1Ze2Zelision_strZelisionZshortZlongZabove_linesr   r   r   r   r   compile_graph_key   sz    








rN   Tc           !   	      s8  g }|j }| du r6tdd |D tdd |D B } |rttdd |D tdd |D B t| B }t|\ } fdd| D }  fd	d|D }nd}|
du rd
}
|rd}d}nd}d}|d |d||
f  |dur|d|f  |dt  |dt  d}d}g }t| D ]\}}t||}| | g }|r|| r|| }||kr|durr|d |}t|}|r|d|  |d7 }|d |d |d|  |r|| r| ||  |r|| r| dt||   |r|d|d|f  n|d|f  q|r6|d t|D ]\}}|\}}|du r\d}|du rjd }t||}t||}g }|rt|| }| d!|  |r| dt||   |	r| |	|  |r|d"|||d|f  n|d#|||f  q>|r&t|||d$} ||  |d% d&|S )'a  Generate a Graphviz representation of a list of vertices and edges.

    :param vertices: list of vertex names (optional).
    :param edges:    list of (vertex, vertex) pairs
    :param directed: bool: whether the graph is directed
    :param title: optional title for the graph
    :param reformat_labels: whether to wrap long vertex labels
    :param vertex_colors: if not None, a sequence of colours for the vertices
    :param edge_colors: if not None, colours for the edges
    :param edge_labels: if not None, labels for the edges
    :param vertex_styles: if not None, DOT style strings for vertices
    :param edge_styles: if not None, DOT style strings for edges
    :param graph_name: if not None, name of graph
    :param shorten_names: if True, remove common DN suffixes
    :param key: (is_vertex, style, description) tuples
    :param vertex_clusters: list of subgraph cluster names

    Colour, style, and label lists must be the same length as the
    corresponding list of edges or vertices (or None).

    Colours can be HTML RGB strings ("#FF0000") or common names
    ("red"), or some other formats you don't want to think about.

    If `vertices` is None, only the vertices mentioned in the edges
    are shown, and their appearance can be modified using the
    vertex_colors and vertex_styles arguments. Vertices appearing in
    the edges but not in the `vertices` list will be shown but their
    styles can not be modified.
    Nc                 s   s   | ]}|d  V  qdS r   Nr   r'   r   r   r   r$     r%   zdot_graph.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS r   Nr   r'   r   r   r   r$     r%   c                 s   s   | ]}|d  V  qdS rO   r   r'   r   r   r   r$     r%   c                 s   s   | ]}|d  V  qdS rP   r   r'   r   r   r   r$     r%   c                    s   g | ]} | qS r   r   r'   r;   r   r   
<listcomp>  r%   zdot_graph.<locals>.<listcomp>c                    s    g | ]\}} |  | fqS r   r   r"   ar   rQ   r   r   rR     r%   ZA_samba_tool_productionZdigraphz->Zgraphz--z/* generated by samba */z%s %s {zlabel="%s";zfontsize=%s;
z'node[fontname=Helvetica; fontsize=%s];
r   r@   zsubgraph cluster_%d {r   zstyle = "rounded,dotted";z'node [style="filled"; fillcolor=white];zlabel = "%s";z
color="%s"z
"%s" [%s];z, z"%s";zMissing source valuezMissing destination valuez
label="%s"z"%s" %s "%s" [%s];z"%s" %s "%s";)rF   rG   z}
r
   )	r   r4   r2   r?   	FONT_SIZErC   r   r   rN   )!r8   edgesZdirectedtitleZreformat_labelsZvertex_colorsZedge_colorsZedge_labelsZvertex_stylesZedge_stylesZ
graph_nameshorten_namesrE   Zvertex_clustersoutwriter=   rG   Z
graph_typeZ	connectorZprev_clusterZ	cluster_nZquoted_verticesr*   r#   attrsZclusterr   ZedgerT   r   rK   keyr   rQ   r   	dot_graph   s    *$







r]   )alternate rowsdisconnected	connected
transitiveheaderreset'   -   |   )Zbgp                  )r^   r_   r`   ra   transitive scalerb   rc         rA   rA   )ansizansi-heatmapzxterm-256colorzxterm-256color-heatmapNu   │u   ─u   ╭   ·r   u   ←)vertical
horizontalcornerdiagonalmissingright_arrow|r	   0z<-)utf8asciic                 C   s~  t | t dd |D B t dd |D B }|t | krRtd|t |   tjd t|}i }|D ]}|di||< qb|D ] \}}|| |d|| |< qxt|D ]}d}	i }
| D ]h\}}| }||
|< | D ]F\}}||  D ]0\}}|| }|||}||k r|||< d	}	qqq|
}|	s q0qi }| D ]@}i ||< | D ],}|| ||}||k rH||| |< qHq8|S )
Nc                 s   s   | ]}|d  V  qdS rO   r   r"   er   r   r   r$     r%   z+find_transitive_distance.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS rP   r   r}   r   r   r   r$     r%   zthere are unknown vertices: %s)filer   r   FT)	r4   printsysstderrr   getranger6   copy)r8   rV   Zall_verticesinfZ	distancesr#   srcdestr*   ZchangedZnew_distancesdZnew_dZcostZleafZcost2Znew_costZold_costZanswerv2rT   r   r   r   find_transitive_distance  sR    


r   c                    sJ   d v r: d t dt|d  fdd}n fdd}|S )Nrm   r   g      ?c                    s(   t | tsdS t|     d  S )NrA   r   )
isinstanceintminlink)mr   scaler   r   f  s    
z"get_transitive_colourer.<locals>.fc                    s    d S )Nra   r   r   )coloursr   r   r   	  s    )r   r   )r   Z
n_verticesr   r   )r   r   r   r   r   get_transitive_colourer  s    r   c           +         s.  g }|j }	t|rdnd }
|
d }|
d }|
d }|
d }|
d }|
d }t| }t|d	d
| d u rttdd |D tdd |D B } |d urt| |d} g }t| |dD ](\}}t |	 fdd|D  qnfdd| D }|r`t
tdd |D tdd |D B t| B }t|ddd\}fdd| D } fdd|D }tdtdd | D }|dd}|dd}|dd}|dd}t|t| }d | }d}|	d!|dd t|  ||f  t| D ]p\}}t| | } ||  | d"kr&d#|d d$ ||f }!n|}!|	d%|!|| |||  ||f  | | 7 }qt| |}"t| D ]\}}||  |"| }#g }$| D ]}%|#|%}&|&d u r|$ d&||f  q|&d'kr|$ d(| ||f  nH|&d"kr|$ d)||f  n*||&}'|&d*krd+}&|$ d,|'|&|f  q|d urV|| rV|$ d-|||| f  |	d. |||d|$|f  qlt}(|r|	d t|D ]"\})}*|	d/|(|)||(|*|f  q|r$|	d |	d0||||f  |	d1|(||f  |	d2||f  |	d3|d4|f  |	d5|||f  d6|S )7Nr{   r|   rs   rt   ru   rv   rw   rx   r^   rp   c                 s   s   | ]}|d  V  qdS rO   r   r'   r   r   r   r$   &  r%   z"distance_matrix.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS rP   r   r'   r   r   r   r$   &  r%   r\   c                 3   s   | ]
} V  qd S r    r   r'   r>   r   r   r$   /  r%   c                    s   g | ]}t  qS r   nextr!   colour_cycler   r   rR   1  r%   z#distance_matrix.<locals>.<listcomp>c                 s   s   | ]}|d  V  qdS rO   r   r'   r   r   r   r$   4  r%   c                 s   s   | ]}|d  V  qdS rP   r   r'   r   r   r   r$   5  r%   +Tr:   c                    s   g | ]} | qS r   r   r'   rQ   r   r   rR   9  r%   c                    s    g | ]\}} |  | fqS r   r   rS   rQ   r   r   rR   :  r%      c                 s   s   | ]}t |V  qd S r    r   r!   r   r   r   r$   <  r%   rb   rA   r_   r`   rc   rB   z%*s %s  %sdestination%sr   z%s%ssource%si%s %s%s%s%s%s %s%s%s%sr   %s%s%s%sz%s1%s	   >%s%s%s%s %s %s%s%*s%s %s%s'%s%s%s' stands for '%s%s%s'zQData can get from %ssource%s to %sdestination%s in the indicated number of steps.z+%s%s%s means zero steps (it is the same DC)z%s1%s means a direct linkzL%s2%s means a transitive link involving two steps (i.e. one intermediate DC)r   z;%s%s%s means there is no connection, even through other DCsr
   )r   CHARSETSCOLOUR_SETSr   r   sortedr4   r   r   extendr2   r?   maxr   r   rC   r   r   rD   )+r8   rV   r{   r   rX   generate_keygrouping_functionrow_commentslinesrZ   charsetrs   rt   ru   rv   rw   rx   r   colour_listr/   r#   r=   r<   vlenc_header	c_disconnc_connc_resetcolour_transitivevspace	verticalsr*   jstartZconnectionslinksrowr   r   ct	example_c
substituteoriginalr   r>   r   r;   r   distance_matrix  s    (


	







r   rB   c                 C   s    |dkrd}d|d  |  | S )Nr   rA   rB   r   )chardigitsZpaddingr   r   r   pad_char  s    r   c                 C   s<   i }|   D ]*\}}|  D ]\}}|||i |< qq|S r    )r6   
setdefault)r   Zm2Zk1r   Zk2Zdistr   r   r   transpose_dict_matrix  s
    r   r   sourcedestinationc           6         s`  g }|j }|rt| } |dk}t|r(dnd }t|d |}|d ||  }t|d ||d }t|d |}t|d |}td	|}|d
 }td|}t| }t|ddt|  }|d ur|j	|d g }t
||dD ](\}}t | fdd|D  qnfdd|D }|rt|ddd\}i }|  D ],\}} tfdd|  D || < qD|} t|  }tdt|
tdd |D }!|dd}"|dd}#|dd}$|dd}%|d u rt| }t||}&d|! }'d}(|d|'|t| d  |"|
|%f  t|D ]|\})}t| |) }*||)  |*dkrhd|'d t|	  |"|	|%f }+n|'}+|d |+|(|% |||* ||%f  |(d! |f 7 }(q"d!d| |%f },d"}-t|D ]\})}| | }.||)  g }/|D ]}0|0|.vr|/ d#|#||%f  n||0kr$|/ d|% ||%f  nh|.|0 }1|1d$| kr^|&|1}2|/ d#|2||%f  d}-q|1d%krn|$}2n|&|1}2|/ d&|2||1|,f  q|d ur||) r|/ d'|%|||) f  |d( |!||%d|/|%f  q|-s|r|d |-r|d)|&d$| ||%d$| d f  |rVt}3t|D ]"\}4}5|d*|3|4|%|3|5|%f  q2d+|S ),Nr   r{   r|   rs   rt   ru   rv   rw   r   rx   rB   r^   rp   r   c                 3   s   | ]
} V  qd S r    r   r'   r   r   r   r$     r%   zfull_matrix.<locals>.<genexpr>c                    s   g | ]}t  qS r   r   r!   r   r   r   rR     r%   zfull_matrix.<locals>.<listcomp>r   Tr   c                 3   s   | ]\}} | |fV  qd S r    r   r.   rQ   r   r   r$     r%   r   c                 s   s   | ]}t |V  qd S r    r   r!   r   r   r   r$     r%   rb   rA   r_   r`   rc   z%s %s %s%s%sr   r   r   Fr   r   r   z%s%*s%sr   r   z'%s%s%s' means greater than %d r   r
   )r   r   r   r   r   r   r   r2   keyssortr   r   r   r?   r6   r1   r   r   r   rC   r   rD   )6Zrowsr{   r   rX   r   r   r   Zcolour_scaler   ZylabelZxlabelZ	transposer   rZ   Zuse_paddingr   rs   rt   ru   rv   rw   Ztoobigrx   emptyr   r8   r   r/   r#   r<   Zrows2Zvertrr   r   r   r   r   r   r   r   r*   r   r   Zend_cellZoverflowr   r   r   r   r   r   r   r   r   r   r   full_matrix  s    




&


	





r   )F)r   F)FNTNNNNNNFNN)FNFFNN)rB   )FNFFNNNr   r   r   T)"Z
__future__r   r   Zsambar   r   	itertoolsr   r   rU   r   r   r?   rN   r]   Z
DARK_WHITEZBLACKZREDZGREENZDARK_YELLOWZ	UNDERLINEZC_NORMALZREV_REDZ	REV_GREENZREV_DARK_YELLOWZxterm_256_colourr   r   r   r   r   r   r   r   r   r   r   r   <module>   s   


J
`            
 
	
	?4      
 
	           