
    c-                        U d Z dZddlZddlmZmZmZ ddlmZm	Z	m
Z
mZ  G d de      ZdZeed	<   d
Zeed<   dZeed<   e	Z G d de      Z G d dee      Z G d de      Zej0                  dd dk\  reZnddlmZ eZ G d dee      Zefdee   dede
e   fdZefdee   dede
e   fdZ G d de      Z G d  d!e      Z y)"z.Base class to represent a tree structure.




zrestructuredtext en    N)VisitedMixInFilteredIterator	no_filter)OptionalAnyListCallablec                       e Zd ZdZy)NodeNotFoundz%raised when a node has not been foundN__name__
__module____qualname____doc__     5/usr/lib/python3/dist-packages/logilab/common/tree.pyr   r   "   s    /r   r   zNo such sibling as '%s'EX_SIBLING_NOT_FOUNDzNo such child as '%s'EX_CHILD_NOT_FOUNDzNo such node as '%s'EX_NODE_NOT_FOUNDc                   Z   e Zd ZdZd!dee   ddfdZd Zd"dZd Z	d	e
ddfd
Zd	e
ddfdZded	e
ddfdZde
de
ddfdZdede
fdZd Zd Zdede
fdZd!dedee   de
fdZdee   de
fdZdefdZdefdZdefdZde
fdZdee
   fdZd!deee
      dee
   fdZdee
   fd Zy)#Nodez)a basic tree node, characterized by an idNnidreturnc                 .    || _         d | _        g | _        y N)idparentchildrenselfr   s     r   __init__zNode.__init__4   s     +/(*r   c                 ,    t        | j                        S r   )iterr   r!   s    r   __iter__zNode.__iter__<   s    DMM""r   c                 D   d|z  | j                   j                  d| j                  g}|dz  }| j                  D ]#  }	 |j	                  |j                  |             % dj                  |      S # t        $ r" |j	                  |j                                Y aw xY w)N    
)	__class__r   r   r   append__str__	TypeErrorjoin)r!   indentschilds       r   r-   zNode.__str__?   s    ,(?(?IJ!]] 	*E*v./	*
 yy|  *)*s    A44(BBc                     | j                    S r   r   r%   s    r   is_leafzNode.is_leafI   s    ==  r   r2   c                 H    | j                   j                  |       | |_        yzadd a node to childrenN)r   r,   r   r!   r2   s     r   r,   zNode.appendL        	U#r   c                 H    | j                   j                  |       d|_        y)zremove a child nodeN)r   remover   r8   s     r   r;   zNode.removeR   r9   r   indexc                 J    | j                   j                  ||       | |_        y)zinsert a child nodeN)r   insertr   r!   r<   r2   s      r   r>   zNode.insertX   s     	UE*r   	old_child	new_childc                     | j                   j                  |      }| j                   j                  |       | j                   j                  ||       | |_        y)z!replace a child node with anotherN)r   r<   popr>   r   )r!   r@   rA   is       r   replacezNode.replace^   sD    MM	*!Q	*	r   c                     	 | j                   J | j                   j                  |      S # t        $ r t        t        |z        w xY w)z)return the sibling node that has given id)r   get_child_by_idr   r   r    s     r   get_siblingzNode.get_siblinge   sL    	;;;***;;..s33 	;3c9::	;s	   (+ Ac                     | j                   }|y|j                  j                  |       }	 |j                  |dz      S # t        $ r Y yw xY w)z>
        return the next sibling for this node if any
        N   )r   r   r<   
IndexErrorr!   r   r<   s      r   next_siblingzNode.next_siblingm   sS     >%%d+	??519-- 		s   > 	A
	A
c                     | j                   }|y|j                  j                  |       }|dkD  r|j                  |dz
     S y)zB
        return the previous sibling for this node if any
        Nr   rJ   )r   r   r<   rL   s      r   previous_siblingzNode.previous_sibling{   sF     >%%d+19??519--r   c                     | j                         }	 |j                  |d      S # t        $ r t        t        |z        w xY w)zB
        return node in whole hierarchy that has given id
        rJ   )rootrG   r   r   )r!   r   rQ   s      r   get_node_by_idzNode.get_node_by_id   sG     yy{	8''Q// 	803677	8s	   $ A recursec                     | j                   |k(  r| S | j                  D ],  }|r	 |j                  |d      c S |j                   |k(  s*|c S  t        t        |z        # t        $ r Y Lw xY w)z*
        return child of given id
        rJ   )r   r   rG   r   r   )r!   r   rS   cs       r   rG   zNode.get_child_by_id   s{     77c>K 	A,,S!44 tts{	 -344	 $ s   A	A+*A+pathc                     t        |      dkD  rI|d   | j                  k(  r7t        |      dk(  r| S | j                  D ]  }	 |j                  |dd       c S  t	        t
        |z        # t        $ r Y 8w xY w)zD
        return child of given path (path is a list of ids)
        r   rJ   N)lenr   r   get_child_by_pathr   r   )r!   rV   rU   s      r   rY   zNode.get_child_by_path   s     t9q=T!W/4yA~ A 2248<<
 -455 ( s   A**	A65A6c                 V    | j                   d| j                   j                         z   S y)z7
        return depth of this node in the tree
        rJ   r   )r   depthr%   s    r   r[   z
Node.depth   s)     ;;"t{{((***r   c                     | j                   r4dt        | j                   D cg c]  }|j                          c}      z   S yc c}w )z9
        return depth of the tree from this node
        rJ   )r   max
depth_down)r!   rU   s     r   r^   zNode.depth_down   s9     ==sDMMBqALLNBCCC Cs   A
c                 4    t        | j                               S )z=
        return the width of the tree from this node
        )rX   leavesr%   s    r   widthz
Node.width   s     4;;=!!r   c                 R    | j                   | j                   j                         S | S )z2
        return the root node of the tree
        )r   rQ   r%   s    r   rQ   z	Node.root   s&     ;;";;##%%r   c                 p    g }| j                   r&| j                   D ]  }||j                         z  } |S | gS )zS
        return a list with all the leaves nodes descendant from this node
        )r   r`   )r!   r`   r2   s      r   r`   zNode.leaves   s?     == )%,,.()M6Mr   _listc                 t    |g }|j                  |        | j                  D ]  }|j                  |        |S )zL
        return a list with all the nodes descendant from this node
        )r,   r   flatten)r!   rd   rU   s      r   rf   zNode.flatten   s>     =ET 	AIIe	r   c                 v    | g}| j                   )|j                  | j                   j                                |S )z8
        return list of parents up to root node
        )r   extendlineage)r!   lsts     r   ri   zNode.lineage   s3     f;;"JJt{{**,-
r   r   r   )r   r   r   r   r   strr"   r&   r-   r5   NodeTyper,   r;   intr>   rE   rH   rM   rO   rR   boolrG   r   rY   r[   r^   ra   rQ   r`   rf   ri   r   r   r   r   r   1   sZ   3+HSM +T +#!H  H  C  T    h  4  ;s ;x ;8# 8( 853 5$ 58 5 6d3i 6H 6s C "s "h 
X 
	Xd8n5 	h 	h r   r   c                       e Zd ZdZy)VNodeza visitable nodeNr   r   r   r   rq   rq      s    r   rq   c                   $    e Zd ZdZddZd Zd Zy)
BinaryNodez%a binary node (i.e. only two childrenNc                     t         j                  |        ||)|r|sJ | j                  |       | j                  |       y y r   )rq   r"   r,   )r!   lhsrhss      r   r"   zBinaryNode.__init__   s>    t?co3;KKKK .r   c                     | j                   j                  |       | j                  j                  | | j                   d          y)z;remove the child and replace this node with the other childr   N)r   r;   r   rE   r8   s     r   r;   zBinaryNode.remove   s1    U#D$--"23r   c                 >    | j                   d   | j                   d   fS )zP
        return the left hand side and the right hand side of this node
        r   rJ   r4   r%   s    r   	get_partszBinaryNode.get_parts  s!     }}Qq!111r   )NN)r   r   r   r   r"   r;   ry   r   r   r   rs   rs      s    /4
2r   rs   r)   )r)   r)   )UserListc                   <    e Zd ZdZd Zd
dZd Zd Zd Zd Z	d Z
y	)ListNodez!Used to manipulate Nodes as Listsc                 f    t         j                  |        t        j                  |        | | _        y r   )
list_classr"   rq   r   r%   s    r   r"   zListNode.__init__  s#    D!tr   c                     |dz  | j                   j                  ddj                  | D cg c]  }t        |       c}      S c c}w )Nr(   z, )r+   r   r/   rl   )r!   r0   vs      r   r-   zListNode.__str__  s@    SLNN##IIt,!s1v,-
 	
 -s   Ac                 >    t         j                  | |       | |_        yr7   )r~   r,   r   r8   s     r   r,   zListNode.append#      $&r   c                 @    t         j                  | ||       | |_        yr7   )r~   r>   r   r?   s      r   r>   zListNode.insert(  s    $u-r   c                 >    t         j                  | |       d|_        yr7   )r~   r;   r   r8   s     r   r;   zListNode.remove-  r   r   c                 >    t         j                  | |      }d|_        yr7   )r~   rC   r   r?   s      r   rC   zListNode.pop2  s    tU+r   c                 ,    t         j                  |       S r   )r~   r&   r%   s    r   r&   zListNode.__iter__7  s    ""4((r   Nrk   )r   r   r   r   r"   r-   r,   r>   r;   rC   r&   r   r   r   r|   r|     s(    +





)r   r|   nodefilter_funcr   c                 N   g g }}d\  }}| r ||       r`| j                   r'|s%|j                  | |f       d}| j                   d   } n/|j                  |        |dz  }	 |d   d   j                   |   } nd} d}| |r|j                         \  } }d}| r|S # t        $ r d} Y -w xY w)zq
    create a list with tree nodes for which the <filter> function returned true
    in a post order fashion
    r   r   r   rJ   N)r   r,   rK   rC   r   r   lstackpopedr<   s         r   post_order_listr   >  s    
 2uALE5
t}}UdE]+}}Q'
  9Q<007D D<E))+KD%E% & H "  D s   B B$#B$c                 j   g g }}d\  }}| r ||       rb|s|j                  |        | j                  r'|s%|j                  | |f       d}| j                  d   } n|dz  }	 |d   d   j                  |   } nd} d}| #t        |      dkD  r|j	                         \  } }d}| r|S # t        $ r d} Y 9w xY w)zp
    create a list with tree nodes for which the <filter> function returned true
    in a pre order fashion
    r   r   rJ   r   N)r,   r   rK   rX   rC   r   s         r   pre_order_listr   [  s    
 2uALE5
t}}UdE]+}}Q'
  9Q<007D D<CJN))+KD%E' ( H "  D s    B$ $B21B2c                   ,    e Zd ZdZddedee   ddfdZy)PostfixedDepthFirstIteratorzCa postfixed depth first iterator, designed to be used with visitorsNr   r   r   c                 <    t        j                  | |t        |       y r   )r   r"   r   r!   r   r   s      r   r"   z$PostfixedDepthFirstIterator.__init__|  s    !!$o{Kr   r   r   r   r   r   r   r   r   r"   r   r   r   r   r   y  s'    MLT L L Lr   r   c                   ,    e Zd ZdZddedee   ddfdZy)PrefixedDepthFirstIteratorzBa prefixed depth first iterator, designed to be used with visitorsNr   r   r   c                 <    t        j                  | |t        |       y r   )r   r"   r   r   s      r   r"   z#PrefixedDepthFirstIterator.__init__  s    !!$nkJr   r   r   r   r   r   r   r     s'    LKT K K Kr   r   )!r   __docformat__syslogilab.common.visitorr   r   r   typingr   r   r   r	   	Exceptionr   r   rl   __annotations__r   r   rm   objectr   rq   rs   version_infolistr~   rz   r|   r   r   r   r   r   r   r   <module>r      s&  $ & 
 L L 0 0
09 0 6 c 51 C 1/ 3 / }6 }@D, 
2 2, AaF"J!J$)uj $)T CL (4. x PTUYPZ : BK $ h tTXz <L"2 LK!1 Kr   