
    i^A                     T    S SK r S SKJr  S SKJr  SSKJrJr  SSKJ	r	   " S S5      r
g)	    N)
ASSERTIONS)PreOrderIter   )	LoopError	TreeError)LightNodeMixinc                      \ rS rSrSrSr\S 5       r\R                  S 5       rS r	S r
S r\S	 5       r\S
 5       r\S 5       r\R                  S 5       r\R                   S 5       rS rS rS rS r\S 5       rS r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       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'g%)&	NodeMixin
   u  
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                 >    [        U S5      (       a  U R                  $ g)ut  
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    C/app/mltbenv/lib/python3.13/site-packages/anytree/node/nodemixin.pyparentNodeMixin.parentP   s     H 4-..==     c                    Ub-  [        U[        [        45      (       d  SU< S3n[        U5      e[	        U S5      (       a  U R
                  nOS nX1La4  U R                  U5        U R                  U5        U R                  U5        g g )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   r   x   s    Z	>7R%S%S 	)EFCC. 4-..]]FFe$MM&!MM%  r   c                    ^  UbQ  UT L a  Sn[        UT 4-  5      e[        U 4S jUR                  5        5       5      (       a  Sn[        UT U4-  5      eg g )Nz1Cannot set parent. %r cannot be parent of itself.c              3   *   >#    U  H  oTL v   M
     g 7fN .0childr   s     r   	<genexpr>)NodeMixin.__check_loop.<locals>.<genexpr>   s     G.FUD=.F   z&Cannot set parent. %r is parent of %r.)r   anyiter_path_reverse)r   noder   s   `  r   __check_loopNodeMixin.__check_loop   sd    t|Itg..Gd.D.D.FGGG>tTl 233 H	 r   c                   ^  Ub  T R                  U5        UR                  n[        (       a!  [        U 4S jU 5       5      (       d   S5       eU Vs/ s H  o3T Ld  M	  UPM     snUl        S T l        T R                  U5        g g s  snf )Nc              3   *   >#    U  H  oTL v   M
     g 7fr   r    r!   s     r   r$   %NodeMixin.__detach.<locals>.<genexpr>   s     EnUD=nr&   Tree is corrupt.)_pre_detach_NodeMixin__children_or_emptyr   r'   _NodeMixin__childrenr   _post_detach)r   r   parentchildrenr#   s   `   r   __detachNodeMixin.__detach   s    V$#77NzEnEEEYGYYE4B XN5SWFWN XF DMf%  !Ys   BBc                    ^  Ubs  T R                  U5        UR                  n[        (       a!  [        U 4S jU 5       5      (       a   S5       eUR	                  T 5        UT l        T R                  U5        g g )Nc              3   *   >#    U  H  oTL v   M
     g 7fr   r    r!   s     r   r$   %NodeMixin.__attach.<locals>.<genexpr>   s     I.}.r&   r/   )_pre_attachr1   r   r'   appendr   _post_attach)r   r   r4   s   `  r   __attachNodeMixin.__attach   sl    V$#77NzI.III]K]]I!!$'"DMf% r   c                 J    [        U S5      (       d  / U l        U R                  $ )Nr2   )r   r2   r   s    r   __children_or_emptyNodeMixin.__children_or_empty   s!    t344 DOr   c                 ,    [        U R                  5      $ )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.
)tupler1   r   s    r   childrenNodeMixin.children   s    b T--..r   c                     [        5       nU  Hc  n[        U[        [        45      (       d  SU< S3n[	        U5      e[        U5      nXA;  a  UR                  U5        MS  SU< S3n[	        U5      e   g )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)rD   seenr#   r   childids        r   __check_childrenNodeMixin.__check_children   sr    uEei%@AA3E9<bcn$iG"!(	1JKn$ r   c                 N   [        U5      n[        R                  U5        U R                  nU ? U R	                  U5        U H	  nXl        M     U R                  U5        [        (       a%  [        U R                  5      [        U5      :X  d   eg g ! [         a    X l        e f = fr   )
rC   r
   _NodeMixin__check_childrenrD   _pre_attach_childrenr   _post_attach_childrenr   len	Exception)r   rD   old_childrenr#   s       r   rD   rE      s     ?""8,}}M		%%h/!# "&&x0z4==)S]:::  	(M	s   A B B$c                     U R                   nU R                  U5        U R                    H
  nS Ul        M     [        (       a  [	        U R                   5      S:X  d   eU R                  U5        g )Nr   )rD   _pre_detach_childrenr   r   rR   _post_detach_children)r   rD   r#   s      r   rD   rE     sX    ==!!(+]]EEL #:t}}%***""8,r   c                     g)z(Method call before detaching `children`.Nr    r   rD   s     r   rV   NodeMixin._pre_detach_children      r   c                     g)z'Method call after detaching `children`.Nr    rY   s     r   rW   NodeMixin._post_detach_children  r[   r   c                     g)z(Method call before attaching `children`.Nr    rY   s     r   rP   NodeMixin._pre_attach_children  r[   r   c                     g)z'Method call after attaching `children`.Nr    rY   s     r   rQ   NodeMixin._post_attach_children  r[   r   c                     U R                   $ )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   pathNodeMixin.path  s      zzr   c              #   B   #    U nUb  Uv   UR                   nUb  M  gg7f)a  
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(   NodeMixin.iter_path_reverse,  s(     * J;;D s   c                 X    [        [        [        U R                  5       5      5      5      $ r   )rC   reversedlistr(   r   s    r   rc   NodeMixin._pathF  s     Xd4#9#9#;<=>>r   c                 J    U R                   c  gU R                   R                  $ )a  
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   rd   r   s    r   	ancestorsNodeMixin.ancestorsJ  s!      ;;{{r   c                 N    [         R                  " S[        SS9  U R                  $ )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DeprecationWarningro   r   s    r   
anchestorsNodeMixin.anchestors^  s!     	SUgtuv~~r   c                 0    [        [        U 5      5      SS $ )a  
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rC   r   r   s    r   descendantsNodeMixin.descendantsi  s    $ \$'(,,r   c                 Z    U nUR                   b  UR                   nUR                   b  M  U$ )z
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')
rg   rh   s     r   rootNodeMixin.root}  s-      kk%;;D kk%r   c                 b   ^  T R                   nUc  g[        U 4S jUR                   5       5      $ )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   4   >#    U  H  oTLd  M	  Uv   M     g 7fr   r    )r"   r)   r   s     r   r$   %NodeMixin.siblings.<locals>.<genexpr>  s     JodT9ITTos   	)r   rC   rD   r   r   s   ` r   siblingsNodeMixin.siblings  s+    ( >JfooJJJr   c                 *    [        [        U S S95      $ )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                     U R                   $ r   )is_leaf)r)   s    r   <lambda>"NodeMixin.leaves.<locals>.<lambda>  s    T\\r   )filter_rz   r   s    r   leavesNodeMixin.leaves  s      \$0IJKKr   c                 2    [        U R                  5      S:H  $ )z
`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   )rR   r1   r   s    r   r   NodeMixin.is_leaf  s      4++,11r   c                     U R                   SL $ )z
`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
Nrg   r   s    r   is_rootNodeMixin.is_root  s      {{d""r   c                 T    U R                   nU(       a  [        S U 5       5      S-   $ g)z
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   8   #    U  H  oR                   v   M     g 7fr   )height)r"   r#   s     r   r$   #NodeMixin.height.<locals>.<genexpr>  s     :||s   r   r   )r1   maxrY   s     r   r   NodeMixin.height  s+      ++:::Q>>r   c                 J    [        U R                  5       5       H  u  pM     W$ )z
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   NodeMixin.depth  s&    $ "$"8"8":;HE <r   c                 B    [        [        U 5      S5       H  u  pM     W$ )aF  
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   NodeMixin.size  s$    , !d!3Q7GD 8r   c                     g)z+Method call before detaching from `parent`.Nr    r   s     r   r0   NodeMixin._pre_detach&  r[   r   c                     g)z*Method call after detaching from `parent`.Nr    r   s     r   r3   NodeMixin._post_detach)  r[   r   c                     g)z)Method call before attaching to `parent`.Nr    r   s     r   r:   NodeMixin._pre_attach,  r[   r   c                     g)z(Method call after attaching to `parent`.Nr    r   s     r   r<   NodeMixin._post_attach/  r[   r   )
__children__parentrD   N)(__name__
__module____qualname____firstlineno____doc__	separatorpropertyr   setterr   r   r   r1   rD   staticmethodrO   deleterrV   rW   rP   rQ   rd   r(   rc   ro   rw   r{   r~   r   r   r   r   r   r   r   r0   r3   r:   r<   __static_attributes__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
   )rt   anytree.configr   anytree.iteratorsr   
exceptionsr   r   lightnodemixinr   r
   r    r   r   <module>r      s      % * , *f7 f7r   