
    ^j^A                     T    d dl Z d dlmZ d dlmZ ddlmZmZ ddlm	Z	  G d d      Z
y)	    N)
ASSERTIONS)PreOrderIter   )	LoopError	TreeError)LightNodeMixinc                      e Zd ZdZdZed        Zej                  d        Zd Zd Z	d Z
ed        Zed	        Zed
        Zej                  d        Zej                  d        Zd Zd Zd Zd Zed        Zd Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Z ed        Z!d Z"d  Z#d! Z$d" Z%y#)$	NodeMixinu  
    The :any:`NodeMixin` class extends any Python class to a tree node.

    The only tree relevant information is the `parent` attribute.
    If `None` the :any:`NodeMixin` is root node.
    If set to another node, the :any:`NodeMixin` becomes the child of it.

    The `children` attribute can be used likewise.
    If `None` the :any:`NodeMixin` has no children.
    The `children` attribute can be set to any iterable of :any:`NodeMixin` instances.
    These instances become children of the node.

    >>> from anytree import NodeMixin, RenderTree
    >>> class MyBaseClass(object):  # Just an example of a base class
    ...     foo = 4
    >>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
    ...     def __init__(self, name, length, width, parent=None, children=None):
    ...         super(MyClass, self).__init__()
    ...         self.name = name
    ...         self.length = length
    ...         self.width = width
    ...         self.parent = parent
    ...         if children:
    ...             self.children = children

    Construction via `parent`:

    >>> my0 = MyClass('my0', 0, 0)
    >>> my1 = MyClass('my1', 1, 0, parent=my0)
    >>> my2 = MyClass('my2', 0, 2, parent=my0)

    >>> for pre, _, node in RenderTree(my0):
    ...     treestr = u"%s%s" % (pre, node.name)
    ...     print(treestr.ljust(8), node.length, node.width)
    my0      0 0
    ├── my1  1 0
    └── my2  0 2

    Construction via `children`:

    >>> my0 = MyClass('my0', 0, 0, children=[
    ...     MyClass('my1', 1, 0),
    ...     MyClass('my2', 0, 2),
    ... ])

    >>> for pre, _, node in RenderTree(my0):
    ...     treestr = u"%s%s" % (pre, node.name)
    ...     print(treestr.ljust(8), node.length, node.width)
    my0      0 0
    ├── my1  1 0
    └── my2  0 2

    Both approaches can be mixed:

    >>> my0 = MyClass('my0', 0, 0, children=[
    ...     MyClass('my1', 1, 0),
    ... ])
    >>> my2 = MyClass('my2', 0, 2, parent=my0)

    >>> for pre, _, node in RenderTree(my0):
    ...     treestr = u"%s%s" % (pre, node.name)
    ...     print(treestr.ljust(8), node.length, node.width)
    my0      0 0
    ├── my1  1 0
    └── my2  0 2
    /c                 4    t        | d      r| j                  S y)uD  
        Parent Node.

        On set, the node is detached from any previous parent node and attached
        to the new node.

        >>> from anytree import Node, RenderTree
        >>> udo = Node("Udo")
        >>> marc = Node("Marc")
        >>> lian = Node("Lian", parent=marc)
        >>> print(RenderTree(udo))
        Node('/Udo')
        >>> print(RenderTree(marc))
        Node('/Marc')
        └── Node('/Marc/Lian')

        **Attach**

        >>> marc.parent = udo
        >>> print(RenderTree(udo))
        Node('/Udo')
        └── Node('/Udo/Marc')
            └── Node('/Udo/Marc/Lian')

        **Detach**

        To make a node to a root node, just set this attribute to `None`.

        >>> marc.is_root
        False
        >>> marc.parent = None
        >>> marc.is_root
        True
        _NodeMixin__parentN)hasattrr   selfs    O/opt/ringagent/.cad-venv/lib/python3.12/site-packages/anytree/node/nodemixin.pyparentzNodeMixin.parentP   s    H 4-.==     c                     |'t        |t        t        f      sd|d}t        |      t	        | d      r| j
                  }nd }||ur4| j                  |       | j                  |       | j                  |       y y )NzParent node z is not of type 'NodeMixin'.r   )	
isinstancer
   r   r   r   r   _NodeMixin__check_loop_NodeMixin__detach_NodeMixin__attach)r   valuemsgr   s       r   r   zNodeMixin.parentx   s{    Z	>7R%S 	)EFCC. 4-.]]FFe$MM&!MM%  r   c                      |J| u rd}t        | fz        t         fd|j                         D              rd}t        | |fz        y y )Nz1Cannot set parent. %r cannot be parent of itself.c              3   &   K   | ]  }|u  
 y wN .0childr   s     r   	<genexpr>z)NodeMixin.__check_loop.<locals>.<genexpr>   s     GU5D=G   z&Cannot set parent. %r is parent of %r.)r   anyiter_path_reverse)r   noder   s   `  r   __check_loopzNodeMixin.__check_loop   sa    t|Itg..Gd.D.D.FGG>tTl 233 H	 r   c                      |q j                  |       |j                  }t        rt         fd|D              sJ d       |D cg c]	  }| us| c}|_        d  _         j                  |       y y c c}w )Nc              3   &   K   | ]  }|u  
 y wr   r   r   s     r   r"   z%NodeMixin.__detach.<locals>.<genexpr>   s     EU5D=Er#   Tree is corrupt.)_pre_detach_NodeMixin__children_or_emptyr   r$   _NodeMixin__childrenr   _post_detach)r   r   parentchildrenr!   s   `   r   __detachzNodeMixin.__detach   sz    V$#77NEnEEYGYYE4B X5eSWFW XF DMf%  !Ys   	A6A6c                      |h j                  |       |j                  }t        rt         fd|D              rJ d       |j	                          | _         j                  |       y y )Nc              3   &   K   | ]  }|u  
 y wr   r   r   s     r   r"   z%NodeMixin.__attach.<locals>.<genexpr>   s     Iu}Ir#   r*   )_pre_attachr,   r   r$   appendr   _post_attach)r   r   r/   s   `  r   __attachzNodeMixin.__attach   sg    V$#77NI.II]K]]I!!$'"DMf% r   c                 @    t        | d      sg | _        | j                  S )Nr-   )r   r-   r   s    r   __children_or_emptyzNodeMixin.__children_or_empty   s    t34 DOr   c                 ,    t        | j                        S )a  
        All child nodes.

        >>> from anytree import Node
        >>> n = Node("n")
        >>> a = Node("a", parent=n)
        >>> b = Node("b", parent=n)
        >>> c = Node("c", parent=n)
        >>> n.children
        (Node('/n/a'), Node('/n/b'), Node('/n/c'))

        Modifying the children attribute modifies the tree.

        **Detach**

        The children attribute can be updated by setting to an iterable.

        >>> n.children = [a, b]
        >>> n.children
        (Node('/n/a'), Node('/n/b'))

        Node `c` is removed from the tree.
        In case of an existing reference, the node `c` does not vanish and is the root of its own tree.

        >>> c
        Node('/c')

        **Attach**

        >>> d = Node("d")
        >>> d
        Node('/d')
        >>> n.children = [a, b, d]
        >>> n.children
        (Node('/n/a'), Node('/n/b'), Node('/n/d'))
        >>> d
        Node('/n/d')

        **Duplicate**

        A node can just be the children once. Duplicates cause a :any:`TreeError`:

        >>> n.children = [a, b, d, a]
        Traceback (most recent call last):
            ...
        anytree.node.exceptions.TreeError: Cannot add node Node('/n/a') multiple times as child.
        )tupler,   r   s    r   childrenzNodeMixin.children   s    b T--..r   c                     t               }| D ]Z  }t        |t        t        f      sd|d}t	        |      t        |      }||vr|j                  |       Kd|d}t	        |       y )NzCannot add non-node object z&. It is not a subclass of 'NodeMixin'.zCannot add node z multiple times as child.)setr   r
   r   r   idadd)r;   seenr!   r   childids        r   __check_childrenzNodeMixin.__check_children   sv    u 		%Eei%@A3E9<bcn$iGd"!(	1JKn$		%r   c                 @   t        |      }t        j                  |       | j                  }| `	 | j	                  |       |D ]	  }| |_         | j                  |       t        r$t        | j                        t        |      k(  sJ y y # t        $ r	 || _         w xY wr   )
r:   r
   _NodeMixin__check_childrenr;   _pre_attach_childrenr   _post_attach_childrenr   len	Exception)r   r;   old_childrenr!   s       r   r;   zNodeMixin.children   s     ?""8,}}M		%%h/! $#$&&x04==)S]:::  	(DM	s   AB Bc                     | j                   }| j                  |       | j                   D ]	  }d |_         t        rt	        | j                         dk(  sJ | j                  |       y )Nr   )r;   _pre_detach_childrenr   r   rG   _post_detach_children)r   r;   r!   s      r   r;   zNodeMixin.children  s[    ==!!(+]] 	 EEL	 t}}%***""8,r   c                      y)z(Method call before detaching `children`.Nr   r   r;   s     r   rK   zNodeMixin._pre_detach_children      r   c                      y)z'Method call after detaching `children`.Nr   rN   s     r   rL   zNodeMixin._post_detach_children  rO   r   c                      y)z(Method call before attaching `children`.Nr   rN   s     r   rE   zNodeMixin._pre_attach_children  rO   r   c                      y)z'Method call after attaching `children`.Nr   rN   s     r   rF   zNodeMixin._post_attach_children  rO   r   c                     | j                   S )a  
        Path from root node down to this `Node`.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.path
        (Node('/Udo'),)
        >>> marc.path
        (Node('/Udo'), Node('/Udo/Marc'))
        >>> lian.path
        (Node('/Udo'), Node('/Udo/Marc'), Node('/Udo/Marc/Lian'))
        )_pathr   s    r   pathzNodeMixin.path  s      zzr   c              #   <   K   | }|| |j                   }|yyw)ae  
        Iterate up the tree from the current node to the root node.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> for node in udo.iter_path_reverse():
        ...     print(node)
        Node('/Udo')
        >>> for node in marc.iter_path_reverse():
        ...     print(node)
        Node('/Udo/Marc')
        Node('/Udo')
        >>> for node in lian.iter_path_reverse():
        ...     print(node)
        Node('/Udo/Marc/Lian')
        Node('/Udo/Marc')
        Node('/Udo')
        Nr   r   r&   s     r   r%   zNodeMixin.iter_path_reverse,  s)     * J;;D s   c                 X    t        t        t        | j                                           S r   )r:   reversedlistr%   r   s    r   rT   zNodeMixin._pathF  s     Xd4#9#9#;<=>>r   c                 H    | j                   y| j                   j                  S )at  
        All parent nodes and their parent nodes.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.ancestors
        ()
        >>> marc.ancestors
        (Node('/Udo'),)
        >>> lian.ancestors
        (Node('/Udo'), Node('/Udo/Marc'))
        r   )r   rU   r   s    r   	ancestorszNodeMixin.ancestorsJ  s!      ;;{{r   c                 R    t        j                  dt        d       | j                  S )z
        All parent nodes and their parent nodes - see :any:`ancestors`.

        The attribute `anchestors` is just a typo of `ancestors`. Please use `ancestors`.
        This attribute will be removed in the 3.0.0 release.
        z;.anchestors was a typo and will be removed in version 3.0.0   )
stacklevel)warningswarnDeprecationWarningr]   r   s    r   
anchestorszNodeMixin.anchestors^  s!     	SUgtuv~~r   c                 0    t        t        |             dd S )aj  
        All child nodes and all their child nodes.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> soe = Node("Soe", parent=lian)
        >>> udo.descendants
        (Node('/Udo/Marc'), Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> marc.descendants
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> lian.descendants
        (Node('/Udo/Marc/Lian/Soe'),)
        r   Nr:   r   r   s    r   descendantszNodeMixin.descendantsi  s    $ \$'(,,r   c                 T    | }|j                   |j                   }|j                   |S )a>  
        Tree Root Node.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.root
        Node('/Udo')
        >>> marc.root
        Node('/Udo')
        >>> lian.root
        Node('/Udo')
        rW   rX   s     r   rootzNodeMixin.root}  s-      kk%;;D kk%r   c                 ^      j                   }|yt         fd|j                  D              S )a  
        Tuple of nodes with the same parent.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> lazy = Node("Lazy", parent=marc)
        >>> udo.siblings
        ()
        >>> marc.siblings
        ()
        >>> lian.siblings
        (Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
        >>> loui.siblings
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lazy'))
        r   c              3   ,   K   | ]  }|us|  y wr   r   )r    r&   r   s     r   r"   z%NodeMixin.siblings.<locals>.<genexpr>  s     JdT9ITJs   	)r   r:   r;   r   r   s   ` r   siblingszNodeMixin.siblings  s+    ( >JfooJJJr   c                 0    t        t        | d             S )a  
        Tuple of all leaf nodes.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> lazy = Node("Lazy", parent=marc)
        >>> udo.leaves
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
        >>> marc.leaves
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
        c                     | j                   S r   )is_leaf)r&   s    r   <lambda>z"NodeMixin.leaves.<locals>.<lambda>  s
    T\\ r   )filter_rf   r   s    r   leaveszNodeMixin.leaves  s      \$0IJKKr   c                 2    t        | j                        dk(  S )aI  
        `Node` has no children (External Node).

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_leaf
        False
        >>> marc.is_leaf
        False
        >>> lian.is_leaf
        True
        r   )rG   r,   r   s    r   rp   zNodeMixin.is_leaf  s      4++,11r   c                     | j                   du S )a6  
        `Node` is tree root.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_root
        True
        >>> marc.is_root
        False
        >>> lian.is_root
        False
        NrW   r   s    r   is_rootzNodeMixin.is_root  s      {{d""r   c                 J    | j                   }|rt        d |D              dz   S y)aI  
        Number of edges on the longest path to a leaf `Node`.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.height
        2
        >>> marc.height
        1
        >>> lian.height
        0
        c              3   4   K   | ]  }|j                     y wr   )height)r    r!   s     r   r"   z#NodeMixin.height.<locals>.<genexpr>  s     :u||:s   r   r   )r,   maxrN   s     r   ry   zNodeMixin.height  s+      ++:::Q>>r   c                 H    t        | j                               D ]  \  }} S )a4  
        Number of edges to the root `Node`.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.depth
        0
        >>> marc.depth
        1
        >>> lian.depth
        2
        )	enumerater%   )r   depth_s      r   r}   zNodeMixin.depth  s-    $ "$"8"8":; 	HE1	r   c                 @    t        t        |       d      D ]  \  }} S )a  
        Tree size --- the number of nodes in tree starting at this node.

        >>> from anytree import Node
        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> soe = Node("Soe", parent=lian)
        >>> udo.size
        5
        >>> marc.size
        4
        >>> lian.size
        2
        >>> loui.size
        1
        r   )r|   r   )r   sizer~   s      r   r   zNodeMixin.size  s+    , !d!3Q7 	GD!	r   c                      y)z+Method call before detaching from `parent`.Nr   rl   s     r   r+   zNodeMixin._pre_detach&  rO   r   c                      y)z*Method call after detaching from `parent`.Nr   rl   s     r   r.   zNodeMixin._post_detach)  rO   r   c                      y)z)Method call before attaching to `parent`.Nr   rl   s     r   r3   zNodeMixin._pre_attach,  rO   r   c                      y)z(Method call after attaching to `parent`.Nr   rl   s     r   r5   zNodeMixin._post_attach/  rO   r   N)&__name__
__module____qualname____doc__	separatorpropertyr   setterr   r   r   r,   r;   staticmethodrD   deleterrK   rL   rE   rF   rU   r%   rT   r]   rd   rg   ri   rm   rs   rp   rv   ry   r}   r   r+   r.   r3   r5   r   r   r   r
   r
   
   s   AF I% %N ]]! !4&&  
 0/ 0/d % % __ & - -7676  "4 ? ?    &   - -&  ( K K0 L L" 2 2" # #"  (  *  2:987r   r
   )ra   anytree.configr   anytree.iteratorsr   
exceptionsr   r   lightnodemixinr   r
   r   r   r   <module>r      s      % * , *f7 f7r   