o
    Rŀg                     @   sP   d Z ddlmZ G dd deZG dd deZG dd dZG d	d
 d
ZdS )aN  Linked list functionality for use in Bio.Nexus.

Provides functionality of a linked list.
Each node has one (or none) predecessor, and an arbitrary number of successors.
Nodes can store arbitrary data in a NodeData class.

Subclassed by Nexus.Trees to store phylogenetic trees.

Bug reports to Frank Kauff (fkauff@biologie.uni-kl.de)
    )Optionalc                   @      e Zd ZdZdS )ChainExceptionz1Provision for the management of Chain exceptions.N__name__
__module____qualname____doc__ r
   r
   C/var/www/html/myenv/lib/python3.10/site-packages/Bio/Nexus/Nodes.pyr          r   c                   @   r   )NodeExceptionz0Provision for the management of Node exceptions.Nr   r
   r
   r
   r   r      r   r   c                   @   s   e Zd ZdZdddZdefddZdee fdd	Zdd
dde	e defddZ
dd Zdd Zdd Zdd Zdd Zdd ZdS )Chainz0Stores a list of nodes that are linked together.returnNc                 C   s   i | _ d| _dS )zInitialize a node chain.N)chainidselfr
   r
   r   __init__!   s   
zChain.__init__c                 C   s   |  j d7  _ | j S )z/Get a new id for a node in the chain (PRIVATE).   r   r   r
   r
   r   _get_id&   s   zChain._get_idc                 C   s   t | j S )zReturn a list of all node ids.)listr   keysr   r
   r
   r   all_ids+   s   zChain.all_idsnodeNodeprevc                 C   sd   |dur|| j vrtdt| |  }|| || |dur+| j | | || j |< |S )zAttach node to another.NzUnknown predecessor: )r   r   strr   set_idset_prevadd_succ)r   r   r   r   r
   r
   r   add/   s   


z	Chain.addc                 C   s   || j vrtdt| | j |  }| j | | | j |  }|D ]
}| j | | q%| j | | | j | }| | |S )z=Delete node from chain and relinks successors to predecessor.Unknown ID: )	r   r   r   get_prevremove_succget_succr!   r"   kill)r   r   prev_idsucc_idsir   r
   r
   r   collapse<   s   


zChain.collapsec                 C   s&   || j vrtdt| | j |= dS )z>Kill a node from chain without caring to what it is connected.r$   N)r   r   r   r   r   r
   r
   r   r(   J   s   
z
Chain.killc                 C   s^   || j vrtdt| | j | j}|dur'| j | j| j | j| d| j | _|S )z%Disconnect node from his predecessor.r$   N)r   r   r   r   succpopindex)r   r   r)   r
   r
   r   unlinkQ   s   
 zChain.unlinkc                 C   sd   || j vrtdt| || j vrtdt| | | | j | j| | j | | dS )zConnect son to parent.r$   N)r   r   r   r1   r.   appendr!   )r   parentchildr
   r
   r   link\   s   


z
Chain.linkc                 C   sH   ||ks|| j |  v rdS | j |  D ]}| ||r! dS qdS )z+Check if grandchild is a subnode of parent.TF)r   r'   is_parent_of)r   r3   
grandchildsnr
   r
   r   r6   g   s   zChain.is_parent_ofc                 C   sn   || j vs
|| j vrtd| ||r||krg S | j |  D ]}| ||r4|g| ||   S q!dS )zQReturn a list of all node_ids between two nodes (excluding start, including end).zUnknown node.N)r   r   r6   r'   trace)r   startfinishr8   r
   r
   r   r9   r   s   zChain.trace)r   NN)r   r   r   r	   r   intr   r   r   r   r#   r,   r(   r1   r5   r6   r9   r
   r
   r
   r   r      s    
r   c                   @   sj   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )r   zA single node.Nc                 C   s   d| _ || _d| _g | _dS )z>Represent a node with one predecessor and multiple successors.N)r   datar   r.   r   r>   r
   r
   r   r      s   
zNode.__init__c                 C   s   | j dur	td|| _ dS )z%Set the id of a node, if not set yet.NzNode id cannot be changed.)r   r   r-   r
   r
   r   r       s   

zNode.set_idc                 C      | j S )zReturn the node's id.r   r   r
   r
   r   get_id      zNode.get_idc                 C   r@   )z'Return a list of the node's successors.)r.   r   r
   r
   r   r'      rB   zNode.get_succc                 C   r@   )z(Return the id of the node's predecessor.r   r   r
   r
   r   r%      rB   zNode.get_prevc                 C   s.   t |tg r| j| dS | j| dS )z'Add a node id to the node's successors.N)
isinstancetyper.   extendr2   r-   r
   r
   r   r"      s   zNode.add_succc                 C   s   | j | dS )z,Remove a node id from the node's successors.N)r.   remover-   r
   r
   r   r&      s   zNode.remove_succc                 C   s    t |tg std|| _dS )zSet the node's successors.z$Node successor must be of list type.N)rD   rE   r   r.   )r   new_succr
   r
   r   set_succ   s   
zNode.set_succc                 C   
   || _ dS )zSet the node's predecessor.NrC   r-   r
   r
   r   r!         
zNode.set_prevc                 C   r@   )zReturn a node's data.r>   r   r
   r
   r   get_data   rB   zNode.get_datac                 C   rJ   )zSet a node's data.NrL   r?   r
   r
   r   set_data   rK   zNode.set_datar<   )r   r   r   r	   r   r    rA   r'   r%   r"   r&   rI   r!   rM   rN   r
   r
   r
   r   r   }   s    
r   N)r	   typingr   	Exceptionr   r   r   r   r
   r
   r
   r   <module>   s   _