a
    oDfY                     @  s   d dl mZ d dlZd dlZd dlmZ d dlmZm	Z	 d dl
Z
ddlmZmZ ddlmZmZ ddl
mZ dd	lmZ dd
lmZ ddlmZmZ G dd deZdd Zdd Zdd Zdd ZdddZdddZ G dd deZ!dZ"dS )    )annotationsN)defaultdict)ClassVarTuple   )ColumnRow)	HoloViewsMarkdown)Param)param_reprs)Viewer)ButtonSelectc                   @  s   e Zd ZdZdS )PipelineErrorzb
    Custom error type which can be raised to display custom error
    message in a Pipeline.
    N)__name__
__module____qualname____doc__ r   r   [/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/panel/pipeline.pyr      s   r   c                 C  s6   d||< |  |g D ]}|| dkrt| || qdS )zC
    Traverse the graph from a node and mark visited vertices.
    TFN)gettraverse)graphvvisitedir   r   r   r      s    r   c                 C  sX   |  |}|du rdS ||v r$|gS |D ]&}t| ||}|du rBq(|g|   S dS dS )z@
    Find a route to the target node from the current node.
    N)r   
find_route)r   currenttargetZ
next_nodesnrouter   r   r   r   %   s    
r   c                 C  sd   g }dd |   D }| D ]}||vr|| qt|dkrHtdnt|dkr\td|d S )zC
    Search for the root node by finding nodes without inputs.
    c                 S  s   g | ]}|D ]}|qqS r   r   ).0tstr   r   r   
<listcomp>=       zget_root.<locals>.<listcomp>r   ziGraph has more than one node with no incoming edges. Ensure that the graph only has a single source node.r   z^Graph has no source node. Ensure that the graph is not cyclic and has a single starting point.)valuesappendlen
ValueError)r   rootstargetssrcr   r   r   get_root7   s    
r.   c                   s>    fdd|  D }dgt  }t| | | t|S )zE
    Check if the graph is fully traversable from the root node.
    c                   s.   i | ]&\}}  |t fd d|D qS )c                 3  s   | ]}  |V  qd S N)indexr"   r$   stagesr   r   	<genexpr>R   r&   z,is_traversable.<locals>.<dictcomp>.<genexpr>)r0   tuple)r"   stgtsr2   r   r   
<dictcomp>R   s   z"is_traversable.<locals>.<dictcomp>F)itemsr)   r   r0   all)rootr   r3   Z	int_graphr   r   r2   r   is_traversableM   s    
r<   c                 C  s@   g }| | g D ]}|t|||d  q|r8t|S |d S Nr   )r   r(   	get_depthmax)noder   depthZdepthssubr   r   r   r>   Y   s    r>   c                 C  sh   |d u rt t}|| |  || g D ]8}|||d  vrP||d  | t|||d | q*|S r=   )r   listr(   r   get_breadths)r@   r   rA   breadthsrB   r   r   r   rD   `   s    rD   c                      sj  e Zd ZU dZejdddZejdddZejdddZej	ddd	d
Z
ej	dddd
ZejdddZejdd dZejdd dZdZded< g i f f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ed(d) Zed*d+ Zd,d- Zd.d/ Z ej!d0dd1d2d3 Z"ej!d4dd1d5d6 Z#d7d8 Z$d9d: Z%d;d< Z&d?d=d>Z'  Z(S )@PipelineaJ  
    A Pipeline represents a directed graph of stages, which each
    return a panel object to render. A pipeline therefore represents
    a UI workflow of multiple linear or branching stages.

    The Pipeline layout consists of a number of sub-components:

    * header:

      * title: The name of the current stage.
      * error: A field to display the error state.
      * network: A network diagram representing the pipeline.
      * buttons: All navigation buttons and selectors.
      * prev_button: The button to go to the previous stage.
      * prev_selector: The selector widget to select between
        previous branching stages.
      * next_button: The button to go to the previous stage
      * next_selector: The selector widget to select the next
        branching stages.

    * stage: The contents of the current pipeline stage.

    By default any outputs of one stage annotated with the
    param.output decorator are fed into the next stage. Additionally,
    if the inherit_params parameter is set any parameters which are
    declared on both the previous and next stage are also inherited.

    The stages are declared using the add_stage method and must each
    be given a unique name. By default any stages will simply be
    connected linearly, but an explicit graph can be declared using
    the define_graph method.
    FzI
        Whether to automatically advance if the ready parameter is True.)defaultdocz]
        Whether to raise errors, useful for debugging while building
        an application.TzP
        Whether parameters should be inherited between pipeline
        stages.NzU
        Parameter name to watch to switch between different branching
        stages)rG   Z
allow_refsrH   zC
        Parameter name to watch to check whether a stage is ready.zY
        Whether to show the header with the title, network diagram,
        and buttons.c                 C  s   | j dS )Nnextparamtriggerxr   r   r   <lambda>   r&   zPipeline.<lambda>)rG   c                 C  s   | j dS )NpreviousrJ   rM   r   r   r   rO      r&   )next_parameterready_parameterzClassVar[Tuple[str, ...]]_ignored_refsc                   s  zdd l }W n ty(   tdd Y n0 t jf i | d | _i | _i | _d | _d| _	d| _
d | _i | _g | _|j | _| j| j t| jjjd | _d| j_tdd| _t| jjjd | _d| j_tdd| _d| j_| jj| j d t!dd	| _"t#d
dd| _$t%dd| _&t%| j| j| _'t%t(| j$| j&| j"| j'dd| _)| * | j"_+t% | _,t(| j)| j,dd| _|D ]N}i }t-|dkr|\}}nt-|dkr|\}}}| j.||fi | qx| /| d S )Nr   z+Pipeline requires holoviews to be installedTF}   )widthvaluebokeh)backendz# Headerr   r   r      )margind   Zstretch_width)Zsizing_mode      )0	holoviews	ExceptionImportErrorsuper__init___stage_stages_states_state_linear_block_error_graph_routeZstreamsZSelection1D_progress_selZadd_subscriber
_set_stager   rK   rP   layoutprev_buttonrU   r   prev_selectorrI   next_buttonnext_selectordisabledwatch_update_progressr	   networkr
   titler   errorbuttonsr   header_make_progressobjectstager)   	add_stagedefine_graph)selfr3   r   paramshvr~   kwargsname	__class__r   r   rc      sZ    

zPipeline.__init__c                 C  s   | j S r/   )ro   r   r   r   r   	__panel__   s    zPipeline.__panel__c                   sX   t  fdd| j D r*td  n*t tr@t tjsTt tjsTtdd S )Nc                 3  s   | ]\}\}} |u V  qd S r/   r   )r"   r    r6   kwr~   r   r   r4      r&   z%Pipeline._validate.<locals>.<genexpr>zStage %s is already in pipelinez;Pipeline stages must be Parameterized classes or instances.)	anyre   r9   r*   
isinstancetype
issubclassrK   Parameterized)r   r~   r   r   r   	_validate   s    
zPipeline._validatec                 C  sh   d}t | j D ]P\}\}\}}t|tjr:t|j}n|j}dt	|}|d||||f 7 }q|S )Nz	Pipeline:z, z
    [%d] %s: %s(%s))
	enumeratere   r9   r   rK   r   r   r   joinr   )r   repr_strr   r   r~   _cls_namer   r   r   r   __repr__   s    zPipeline.__repr__c                 C  s   |   S r/   )r   r   r   r   r   __str__   s    zPipeline.__str__c                 C  s   | j | d S )Nr   )re   )r   r0   r   r   r   __getitem__   s    zPipeline.__getitem__c                 C  sx   | j |jus| jrd| _d S | j}|jr6|jr6d|_n|jsH|jsHd|_| j| j d }|jrt|d| j	rt| 
  d S )NFTauto_advance)rg   objri   rr   rt   newre   rd   r   r   _next)r   eventbuttonstage_kwargsr   r   r   _unblock   s    zPipeline._unblockc                 C  s&   | j |jurd S |j| j_|   d S r/   )rg   r   r   rs   rV   rv   )r   r   r   r   r   _select_next
  s    
zPipeline._select_nextc                   s  j j \g }j D ]\}}j|v r|| qfdd|D }g }i i  }}|D ]}|j  D ]V\}	\}
}}|	jvrqr||vr| ||< || }|d ur|| }|||	< ||	 qrdjr`fdddD   fdd|j	d D |
fdd	|j  D  q`ttjrXjj
f i | _nf i |_|D ]}d
jj| _qldj}|r|jv rjjjj|dd dj}|r|jv rjjjj|dd jjj< j S )Nc                   s    g | ]}| j v r j | qS r   )rf   )r"   prevr   r   r   r%     r&   z(Pipeline._init_stage.<locals>.<listcomp>inherit_paramsc                   s"   g | ]} |pt |d qS r/   )r   getattr)r"   p)r   r   r   r   r%   '  s   )rR   rQ   c                   s   g | ]\}}| vr|qS r   r   r"   kr   )ignoredr   r   r%   )  s   existingc                   s0   i | ](\}}|j v r|d kr| v r||qS )r   )rK   r   )r   r~   r   r   r8   +  s   z(Pipeline._init_stage.<locals>.<dictcomp>r   rR   F)ZonlychangedrQ   )re   rd   rk   r9   r(   rK   outputsr   r   Zobjectsupdater'   r   r   rg   
precedencerR   ru   r   rQ   r   rf   panel)r   rP   r-   r7   Zprev_statesr   r   resultsstater   r   methodr0   resultoutputready_param
next_paramr   )r   r   r   r~   r   r   _init_stage  sN    



&zPipeline._init_stagec                 C  s  |sd S | j jj|d df }|| jjv r@|| j_| jd n|| jjv rb|| j_| jd n|| j	v rt
| j	dkr| jd qlntt| j| j|}|d u rt| j| j|}|d u rtdn| jg| }|D ](}|| jjvr q|| j_| jd qd S )Nr   r]   rI   rP   r   z$Could not find route to target node.)rm   sourceZilocrs   optionsrV   rK   rL   rq   rl   r)   r   rk   _next_stagerd   r*   )r   r0   r~   r!   rr   r   r   rn   C  s.    

zPipeline._set_stagec                 C  s   | j jS r/   )rs   rV   r   r   r   r   r   a  s    zPipeline._next_stagec                 C  s   | j jS r/   )rq   rV   r   r   r   r   _prev_stagee  s    zPipeline._prev_stagec                 C  sF  | j | j \}}t| j| jg }|d| j}|rL||jv rLt| j|nd }|d u rh|rd|d nd }|| j	_
|| j	_t| | j	_g }| j D ]\}}| j|v r|| q|| j_
|r| jd nd | j_t| | j_| jd u rd| j_nd| j_| jd u rd| j_n2|d| j}	|	|jv r6t||	 nd}
|
| j_d S )NrQ   r   r   TFrR   )re   rd   rC   rk   r   rQ   rK   r   rg   rs   r   rV   boolrt   r9   r(   rq   rl   r   rp   r   rr   rR   )r   r~   r   r   r   optionrP   r-   r7   readyrt   r   r   r   _update_buttoni  s0    



zPipeline._update_buttonc           	      C  s   t |trt|nd}| jrdt \}}}t|d t|| }d|d	|dd |d f }n|pjd}t
dddd	d
d}|jdj|dd |S )N z(%s

Traceback (innermost last):
%-20s %sr   z#Undefined error, enable debug mode.ErrorZdangerr\   centerrY   )r   Zbutton_typerU   Zalignr[   zalert(`{tb}`))tb)code)r   r   strdebugsysexc_infor   	format_tbformat_exception_onlyr   r   Zjs_on_clickformat)	r   emsgr   rV   ZtrbZtb_list	tracebackr   r   r   r   _get_error_button  s    zPipeline._get_error_buttonrI   )ru   c              
   C  sR  | j | j }}| j| _d| j_zz|  | jd< W n| ty } zd| j| _|| _|| _ | | jd< | 	|g| j
d d < | jr||W  Y d }~W |   d| j_S d }~0 0 g | j
d d < d | _|   | j| j | j| j d }|d| j}|r(t| j |dr(|d| jr(|   W |   d| j_n|   d| j_0 d S )NTr   Fr   rR   r   )rg   rd   r   r~   Zloadingr   r`   rj   r   r   ry   r   rv   r   rl   r(   re   r   rR   r   r   r   )r   
prev_state
prev_stager   r   r   r   r   r   r     s>    

zPipeline._nextrP   c              
   C  s   | j | j }}| j| _zzD| j| jv rF| j| j | _ | j  | jd< n|  | jd< d| _W nX ty } z@| 	|g| j
d d < | j| _|| _|| _ | jr|W Y d }~n0d }~0 0 g | j
d d < d | _|   | j  W |   n
|   0 d S )Nr   T)rg   rd   r   rf   r   r~   r   ri   r`   r   ry   rj   r   r   rl   poprv   )r   r   r   r   r   r   r   	_previous  s(    
zPipeline._previousc                 G  s   d| j  | j_|  | j_d S )Nz
## Stage: )rd   rx   r}   r|   rw   )r   argsr   r   r   rv     s    zPipeline._update_progressc                 C  s  dd l }dd l}| jrPt| j}t|| j}t|| j}tdd | D }nd }d\}}i }d|d d  }g }| j D ] \}	}
|
D ]}|	|	|f qq~g }| D ]\}}t
|}d| }t|d d d	 D ]\\}}|| jkrd
}n&|| jkrd}n|| jkrd}nd}|	||d ||  ||f qqddddd}dd }||g ddjddg|gddddddd	}|| j_|||fjdd|g dgd dddd 	}||d!d"gd#jd$g ddd%}| jr|| | n|| }|jd d d&dd'|d(|d) fd*dgd dd+ |S ),Nr   c                 s  s   | ]}t |V  qd S r/   )r)   )r"   r   r   r   r   r4     r&   z*Pipeline._make_progress.<locals>.<genexpr>)r   r   P   r      g      ?r   activery   rI   inactiveg       @Zwhitez#5cb85cZredZyellow)r   r   ry   rI   c                 S  s.   ddl m} | jd }| j|}|g|_d S )Nr   )TapToolZglyph_renderer)Zbokeh.modelsr   Zhandlesr   Z
select_oneZ	renderers)plotelementr   Zgrtapr   r   r   tap_renderer  s    
z-Pipeline._make_progress.<locals>.tap_renderer)rN   yStageStater   T
   rW   )	alphadefault_toolshooksZhover_alphaZselection_alphaZnonselection_alphaaxiswisesizerX   ZblackZhoverZgray)	Zedge_hover_line_colorZ
node_colorcmapZtoolsr   Zselection_policyZnode_hover_fill_colorr   rX   rN   r   r   g333333ӿ)Zyoffsetr   r   rX   i  Fg      пg      ?)r   r   )ZxaxisZyaxisZ	min_widthZ
responsiveZ
show_frameheightZxlimZylimr   ZtoolbarrX   )r_   Zholoviews.plotting.bokehrk   r.   r>   rD   r?   r'   r9   r(   r)   r   rd   rj   r   ZNodesoptsrm   r   ZGraphZLabelsrh   )r   r   r_   r;   rA   rE   Zmax_breadthr   edgesr-   r7   r$   nodesZsubnodesZbreadthstepr   r    r   r   r   r   labelsr   r   r   r   r|     sj    


"

zPipeline._make_progressc                   s     | |D ]}| jvrtd| q js> jr>td||f j|< t jdkr| _|g _	i  _ 
 g jdd< n$ fdd jD d }|f j|<       dS )ad  
        Adds a new, named stage to the Pipeline.

        Arguments
        ---------
        name: str
          A string name for the Pipeline stage
        stage: param.Parameterized
          A Parameterized object which represents the Pipeline stage.
        **kwargs: dict
          Additional arguments declaring the behavior of the stage.
        z.Keyword argument %s is not a valid parameter. z.Cannot add stage after graph has been defined.r   Nc                   s   g | ]}| j vr|qS r   )rk   )r"   r6   r   r   r   r%   5  r&   z&Pipeline.add_stage.<locals>.<listcomp>r   )r   rK   r*   rh   rk   RuntimeErrorre   r)   rd   rl   r   r~   rv   r   )r   r   r~   r   r   rP   r   r   r   r     s     

zPipeline.add_stagec                   sh  t | j  si | _dS dd | D }g }| D ]0\}}| vrP|| | fdd|D 7 }q6|rtdt|dkr|d n| |r| js|std	d
| _n$dd t dd  dd D }t	|}t
|| std| || ju}|| _|| _|g| _| js:t| j| jt| j| jg| jdd< |rT|  g| jdd< |   |   dS )a  
        Declares a custom graph structure for the Pipeline overriding
        the default linear flow. The graph should be defined as an
        adjacency mapping.

        Arguments
        ---------
        graph: dict
          Dictionary declaring the relationship between different
          pipeline stages. Should map from a single stage name to
          one or more stage names.
        Nc                 S  s&   i | ]\}}|t |tr|n|fqS r   )r   r5   r   r   r   r   r8   L  r&   z)Pipeline.define_graph.<locals>.<dictcomp>c                   s   g | ]}| vr|qS r   r   r1   r2   r   r   r%   R  r&   z)Pipeline.define_graph.<locals>.<listcomp>zZPipeline stage(s) %s not found, ensure all stages referenced in the graph have been added.r   r   z?Graph has already been defined, cannot override existing graph.Fc                 S  s   i | ]\}}||fqS r   r   )r"   r6   r$   r   r   r   r8   `  r&   r   z.Graph is not fully traversable from stage: %s.)rC   re   rk   r9   r(   r*   r)   rh   zipr.   r<   rd   rl   r   rq   rp   rs   rr   rz   r   r~   rv   r   )r   r   force	not_foundr   r,   r;   reinitr   r2   r   r   :  sL    


$
zPipeline.define_graph)F))r   r   r   r   rK   Booleanr   r   r   StringrQ   rR   Zshow_headerActionrI   rP   rS   __annotations__rc   r   r   r   r   r   r   r   r   rn   propertyr   r   r   r   dependsr   r   rv   r|   r   r   __classcell__r   r   r   r   rF   l   sD   
!63

 

F!rF   )rF   )r   )r   N)#
__future__r   r   r   r   collectionsr   typingr   r   rK   ro   r   r   Zpaner	   r
   r   utilr   Zviewabler   Zwidgetsr   r   r   r   r   r   r.   r<   r>   rD   rF   __all__r   r   r   r   <module>   s0   

    