
    i:                         S SK r S SKrS SKrS SKrS SKJrJr  S SKJr  S SK	J
r
  S SKJr  \R                  " S5      r " S S5      r " S	 S
\5      rg)    N)pathremove)
check_call)NamedTemporaryFile)PreOrderIterz["\\]c                       \ rS rSrSr           SS jrS r\S 5       r\S 5       r	\S 5       r
\S	 5       r\S
 5       rS rS rS rS rS rS r\S 5       rSrg)DotExporter   a  
Dot Language Exporter.

Args:
    node (Node): start node.

Keyword Args:
    graph: DOT graph type.

    name: DOT graph name.

    options: list of options added to the graph.

    indent (int): number of spaces for indent.

    nodenamefunc: Function to extract node name from `node` object.
                  The function shall accept one `node` object as
                  argument and return the name of it.

    nodeattrfunc: Function to decorate a node with attributes.
                  The function shall accept one `node` object as
                  argument and return the attributes.

    edgeattrfunc: Function to decorate a edge with attributes.
                  The function shall accept two `node` objects as
                  argument. The first the node and the second the child
                  and return the attributes.

    edgetypefunc: Function to which gives the edge type.
                  The function shall accept two `node` objects as
                  argument. The first the node and the second the child
                  and return the edge (i.e. '->').

    filter_: Function to filter nodes to include in export.
             The function shall accept one `node` object as
             argument and return True if it should be included,
             or False if it should not be included.

    stop: stop iteration at `node` if `stop` function returns `True` for `node`.

    maxlevel (int): Limit export to this number of levels.

>>> from anytree import Node
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root, edge=2)
>>> s0b = Node("sub0B", parent=s0, foo=4, edge=109)
>>> s0a = Node("sub0A", parent=s0, edge="")
>>> s1 = Node("sub1", parent=root, edge="")
>>> s1a = Node("sub1A", parent=s1, edge=7)
>>> s1b = Node("sub1B", parent=s1, edge=8)
>>> s1c = Node("sub1C", parent=s1, edge=22)
>>> s1ca = Node("sub1Ca", parent=s1c, edge=42)

.. note:: If the node names are not unique, see :any:`UniqueDotExporter`.

A directed graph:

>>> from anytree.exporter import DotExporter
>>> for line in DotExporter(root):
...     print(line)
digraph tree {
    "root";
    "sub0";
    "sub0B";
    "sub0A";
    "sub1";
    "sub1A";
    "sub1B";
    "sub1C";
    "sub1Ca";
    "root" -> "sub0";
    "root" -> "sub1";
    "sub0" -> "sub0B";
    "sub0" -> "sub0A";
    "sub1" -> "sub1A";
    "sub1" -> "sub1B";
    "sub1" -> "sub1C";
    "sub1C" -> "sub1Ca";
}

The resulting graph:

.. image:: ../static/dotexporter0.png

An undirected graph:

>>> def nodenamefunc(node):
...     return '%s:%s' % (node.name, node.depth)
>>> def edgeattrfunc(node, child):
...     return 'label="%s:%s"' % (node.name, child.name)
>>> def edgetypefunc(node, child):
...     return '--'
        >>> from anytree.exporter import DotExporter
>>> for line in DotExporter(root, graph="graph",
...                             nodenamefunc=nodenamefunc,
...                             nodeattrfunc=lambda node: "shape=box",
...                             edgeattrfunc=edgeattrfunc,
...                             edgetypefunc=edgetypefunc):
...     print(line)
graph tree {
    "root:0" [shape=box];
    "sub0:1" [shape=box];
    "sub0B:2" [shape=box];
    "sub0A:2" [shape=box];
    "sub1:1" [shape=box];
    "sub1A:2" [shape=box];
    "sub1B:2" [shape=box];
    "sub1C:2" [shape=box];
    "sub1Ca:3" [shape=box];
    "root:0" -- "sub0:1" [label="root:sub0"];
    "root:0" -- "sub1:1" [label="root:sub1"];
    "sub0:1" -- "sub0B:2" [label="sub0:sub0B"];
    "sub0:1" -- "sub0A:2" [label="sub0:sub0A"];
    "sub1:1" -- "sub1A:2" [label="sub1:sub1A"];
    "sub1:1" -- "sub1B:2" [label="sub1:sub1B"];
    "sub1:1" -- "sub1C:2" [label="sub1:sub1C"];
    "sub1C:2" -- "sub1Ca:3" [label="sub1C:sub1Ca"];
}

The resulting graph:

.. image:: ../static/dotexporter1.png

To export custom node implementations or :any:`AnyNode`, please provide a proper `nodenamefunc`:

>>> from anytree import AnyNode
>>> root = AnyNode(id="root")
>>> s0 = AnyNode(id="sub0", parent=root)
>>> s0b = AnyNode(id="s0b", parent=s0)
>>> s0a = AnyNode(id="s0a", parent=s0)

>>> from anytree.exporter import DotExporter
>>> for line in DotExporter(root, nodenamefunc=lambda n: n.id):
...     print(line)
digraph tree {
    "root";
    "sub0";
    "s0b";
    "s0a";
    "root" -> "sub0";
    "sub0" -> "s0b";
    "sub0" -> "s0a";
}
Nc                     Xl         X l        X0l        X@l        XPl        X`l        Xpl        Xl        Xl        Xl	        Xl
        Xl        g N)nodegraphnameoptionsindentnodenamefuncnodeattrfuncedgeattrfuncedgetypefuncfilter_maxlevelstop)selfr   r   r   r   r   r   r   r   r   r   r   r   s                I/app/mltbenv/lib/python3.13/site-packages/anytree/exporter/dotexporter.py__init__DotExporter.__init__   sD     	
	(((( 	    c                 |   SU R                   -  nU R                  =(       d    U R                  nU R                  =(       d    U R                  nU R
                  =(       d    U R                  nU R                  =(       d    U R                  nU R                  =(       d    U R                  nU R                  XX4XV5      $ )N )r   r   _default_nodenamefuncr   _default_nodeattrfuncr   _default_edgeattrfuncr   _default_edgetypefuncr   _default_filter_DotExporter__iterr   r   r   r   r   r   r   s          r   __iter__DotExporter.__iter__   s    t{{"((FD,F,F((FD,F,F((FD,F,F((FD,F,F,,6$"6"6{{6\ccr   c                     U R                   $ r   r   r   s    r   r    !DotExporter._default_nodenamefunc   s    yyr   c                     g r    r+   s    r   r!   !DotExporter._default_nodeattrfunc        r   c                     g r   r.   r   childs     r   r"   !DotExporter._default_edgeattrfunc   r0   r   c                     g)Nz->r.   r2   s     r   r#   !DotExporter._default_edgetypefunc   r0   r   c                     g)NTr.   r+   s    r   r$   DotExporter._default_filter   r0   r   c              #      #    U R                    SU R                   S3v   U R                  U5       S h  vN   U R                  XX65       S h  vN   U R	                  XXEU5       S h  vN   Sv   g  N> N& N7f)Nr   z {})r   r   _DotExporter__iter_options_DotExporter__iter_nodes_DotExporter__iter_edgesr&   s          r   __iterDotExporter.__iter   ss     Adii[,,&&v...$$V<QQQ$$V<W^___	 	/Q_s3   3A:A4A:A6A:*A8+
A:6A:8A:c              #   V   #    U R                   nU(       a  U H  nU U 3v   M     g g 7fr   )r   )r   r   r   options       r   __iter_optionsDotExporter.__iter_options   s/     ,,!)) " s   ')c              #      #    [        U R                  X@R                  U R                  S9 H>  nU" U5      nU" U5      nUb  SU S3OSnU S[        R                  U5       SU S3v   M@     g 7f)Nr   r   r    [] ";)r   r   r   r   r	   esc)r   r   r   r   r   r   nodenamenodeattrs           r   __iter_nodesDotExporter.__iter_nodes   st      G))VZVcVcdD#D)H#D)H+3+?H:Q'RHHAkooh78(1EE	 es   A-A/c              #     #    U R                   (       a  U R                   S-
  OS n[        U R                  XPR                  US9 H  nU" U5      nUR                   Hn  n	U" U	5      (       d  M  U" U	5      n
U" Xy5      nU" Xy5      nUb  SU S3OSnU S[
        R                  U5       SU S[
        R                  U
5       SU S	3
v   Mp     M     g 7f)
N   rE   rF   rG   rH   rI   z" z "rJ   )r   r   r   r   childrenr	   rK   )r   r   r   r   r   r   r   r   rL   r3   	childnameedgeattredgetypes                r   __iter_edgesDotExporter.__iter_edges   s     (,4==1$4 G))V^_D#D)Hu~~(/	'4'4/7/CRz++//(";!<Bxj;??[dKeJffghpgqqrss ' `s   CCc                     [         R                  " USS5       nU  H  nUR                  U S35        M     SSS5        g! , (       d  f       g= f)aW  
Write graph to `filename`.

>>> from anytree import Node
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)

>>> from anytree.exporter import DotExporter
>>> DotExporter(root).to_dotfile("tree.dot")

The generated file should be handed over to the `dot` tool from the
http://www.graphviz.org/ package::

    $ dot tree.dot -T png -o tree.png
wzutf-8
N)codecsopenwrite)r   filenamefilelines       r   
to_dotfileDotExporter.to_dotfile   s>    . [[30D

dV2;'  100s   A  
Ac                    [         R                  " U5      S   SS n[        SSS9 nUR                  nU  H%  nUR	                  U S3R                  5       5        M'     UR                  5         SUSUS	U/n[        U5        SSS5         [        W5        g! , (       d  f       N= f! [         a-    [        R                  " [        5      R                  S
W5         gf = f)z
Write graph to a temporary file and invoke `dot`.

The output file type is automatically detected from the file suffix.

*`graphviz` needs to be installed, before usage of this method.*
rQ   NwbF)deleterZ   dotz-Tz-oz"Could not remove temporary file %s)r   splitextr   r   r]   encodeflushr   r   	Exceptionlogging	getLogger__name__warning)r   r^   
fileformatdotfiledotfilenamer`   cmds          r   
to_pictureDotExporter.to_picture  s     ]]8,Q/3
U3w!,,K$r{2245 MMO+tZxHCsO 4	c; 43  	ch'//0TVab	cs   ABB( 
B%(4CCc                 B    [         R                  S [        U 5      5      $ )zEscape Strings.c                 *    SU R                  S5       3$ )N\r   )group)ms    r   <lambda>!DotExporter.esc.<locals>.<lambda>3  s    !''!*%6r   )_RE_ESCsubstr)values    r   rK   DotExporter.esc0  s     {{6E
CCr   )r   r   r   r   r   r   r   r   r   r   r   r   digraphtreeN   NNNNNNN)rm   
__module____qualname____firstlineno____doc__r   r'   staticmethodr    r!   r"   r#   r$   r%   r;   r<   r=   ra   rs   rK   __static_attributes__r.   r   r   r	   r	      s    Oh 8d          *Ft(6c, D Dr   r	   c                   \   ^  \ rS rSrSr           SU 4S jjrS r\S 5       rSr	U =r
$ )UniqueDotExporteri6  a	  
Unique Dot Language Exporter.

Handle trees with random or conflicting node names gracefully.

Args:
    node (Node): start node.

Keyword Args:
    graph: DOT graph type.

    name: DOT graph name.

    options: list of options added to the graph.

    indent (int): number of spaces for indent.

    nodenamefunc: Function to extract node name from `node` object.
                    The function shall accept one `node` object as
                    argument and return the name of it.

    nodeattrfunc: Function to decorate a node with attributes.
                    The function shall accept one `node` object as
                    argument and return the attributes.

    edgeattrfunc: Function to decorate a edge with attributes.
                    The function shall accept two `node` objects as
                    argument. The first the node and the second the child
                    and return the attributes.

    edgetypefunc: Function to which gives the edge type.
                    The function shall accept two `node` objects as
                    argument. The first the node and the second the child
                    and return the edge (i.e. '->').

    filter_: Function to filter nodes to include in export.
             The function shall accept one `node` object as
             argument and return True if it should be included,
             or False if it should not be included.

    stop: stop iteration at `node` if `stop` function returns `True` for `node`.

    maxlevel (int): Limit export to this number of levels.

>>> from anytree import Node
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("s0", parent=s0)
>>> s0a = Node("s0", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("s1", parent=s1)
>>> s1b = Node("s1", parent=s1)
>>> s1c = Node("s1", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)

>>> from anytree.exporter import UniqueDotExporter
>>> for line in UniqueDotExporter(root):
...     print(line)
digraph tree {
    "0x0" [label="root"];
    "0x1" [label="sub0"];
    "0x2" [label="s0"];
    "0x3" [label="s0"];
    "0x4" [label="sub1"];
    "0x5" [label="s1"];
    "0x6" [label="s1"];
    "0x7" [label="s1"];
    "0x8" [label="sub1Ca"];
    "0x0" -> "0x1";
    "0x0" -> "0x4";
    "0x1" -> "0x2";
    "0x1" -> "0x3";
    "0x4" -> "0x5";
    "0x4" -> "0x6";
    "0x4" -> "0x7";
    "0x7" -> "0x8";
}

The resulting graph:

.. image:: ../static/uniquedotexporter2.png

To export custom node implementations or :any:`AnyNode`, please provide a proper `nodeattrfunc`:

>>> from anytree import AnyNode
>>> root = AnyNode(id="root")
>>> s0 = AnyNode(id="sub0", parent=root)
>>> s0b = AnyNode(id="s0", parent=s0)
>>> s0a = AnyNode(id="s0", parent=s0)

>>> from anytree.exporter import UniqueDotExporter
>>> for line in UniqueDotExporter(root, nodeattrfunc=lambda n: 'label="%s"' % (n.id)):
...     print(line)
digraph tree {
    "0x0" [label="root"];
    "0x1" [label="sub0"];
    "0x2" [label="s0"];
    "0x3" [label="s0"];
    "0x0" -> "0x1";
    "0x1" -> "0x2";
    "0x1" -> "0x3";
}
c                 x   > [         TU ]  UUUUUUUUU	U
UUS9  0 U l        [        R                  " 5       U l        g )N)r   r   r   r   r   r   r   r   r   r   r   )superr   _UniqueDotExporter__node_ids	itertoolscount _UniqueDotExporter__node_counter)r   r   r   r   r   r   r   r   r   r   r   r   r   	__class__s                r   r   UniqueDotExporter.__init__  sS     	%%%% 	 	
 'oo/r   c                     [        U5      n U R                  U   n[        U5      $ ! [         a&    [        U R                  5      =o0R                  U'    N:f = fr   )idr   KeyErrornextr   hex)r   r   node_idnums       r   r    'UniqueDotExporter._default_nodenamefunc  sY    T(	G//'*C 3x  	G-1$2E2E-FFC//'*	Gs   ' -AAc                 "    SU R                    S3$ )Nzlabel="rI   r*   r+   s    r   r!   'UniqueDotExporter._default_nodeattrfunc  s    1%%r   )__node_counter
__node_idsr   )rm   r   r   r   r   r   r    r   r!   r   __classcell__)r   s   @r   r   r   6  sL    fV 0B & &r   r   )r[   r   rk   reosr   r   
subprocessr   tempfiler   anytreer   compiler|   r	   r   r.   r   r   <module>r      sH       	  ! '  
**X
eD eDP	T& T&r   