o
    i9                     @  s   d dl mZ d dlmZmZ d dlZd dlZd dlZd dlm	Z	m
Z
 d dlmZmZmZ e
Z
G dd deZG dd	 d	eZG d
d deZG dd dZ	ddddZG dd dZG dd deZdS )    )annotations)TypeLiteralN)is_linkExecutionBlocker)ComfyNodeABCInputTypeDictInputTypeOptionsc                   @     e Zd ZdS )DependencyCycleErrorN__name__
__module____qualname__ r   r   3/mnt/c/Users/fbmor/ComfyUI/comfy_execution/graph.pyr          r   c                   @  r
   )NodeInputErrorNr   r   r   r   r   r      r   r   c                   @  r
   )NodeNotFoundErrorNr   r   r   r   r   r      r   r   c                   @  sT   e Z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 )DynamicPromptc                 C  s   || _ i | _i | _i | _d S N)original_promptephemeral_promptephemeral_parentsephemeral_display)selfr   r   r   r   __init__   s   
zDynamicPrompt.__init__c                 C  s8   || j v r
| j | S || jv r| j| S td| d)NNode z
 not found)r   r   r   r   node_idr   r   r   get_node   s
   



zDynamicPrompt.get_nodec                 C  s   || j v p	|| jv S r   )r   r   r   r   r   r   has_node&      zDynamicPrompt.has_nodec                 C  s"   || j |< || j|< || j|< d S r   )r   r   r   )r   r   	node_info	parent_id
display_idr   r   r   add_ephemeral_node)   s   

z DynamicPrompt.add_ephemeral_nodec                 C  "   || j v r| j | }|| j v s|S r   )r   r   r   r   r   get_real_node_id.      


zDynamicPrompt.get_real_node_idc                 C  s   | j |d S r   )r   getr   r   r   r   get_parent_node_id3      z DynamicPrompt.get_parent_node_idc                 C  r'   r   )r   r   r   r   r   get_display_node_id6   r)   z!DynamicPrompt.get_display_node_idc                 C  s   t | j t | j S r   )setr   keysunionr   r   r   r   r   all_node_ids;   s   zDynamicPrompt.all_node_idsc                 C  s   | j S r   )r   r1   r   r   r   get_original_prompt>   s   z!DynamicPrompt.get_original_promptN)r   r   r   r   r    r!   r&   r(   r+   r-   r2   r3   r   r   r   r   r      s    r   	class_defType[ComfyNodeABC]
input_namestrvalid_inputsInputTypeDict | Nonereturnatuple[str, Literal['required', 'optional', 'hidden'], InputTypeOptions] | tuple[None, None, None]c                 C  s   |p|   }d}d}d|v r||d v rd}|d | }n%d|v r0||d v r0d}|d | }nd|v rB||d v rBd}|d | }|du rHdS |d }t|dkrW|d }ni }|||fS )a  Get the input type, category, and extra info for a given input name.

    Arguments:
        class_def: The class definition of the node.
        input_name: The name of the input to get info for.
        valid_inputs: The valid inputs for the node, or None to use the class_def.INPUT_TYPES().

    Returns:
        tuple[str, str, dict] | tuple[None, None, None]: The input type, category, and extra info for the input name.
    NrequiredoptionalhiddenNNNr      )INPUT_TYPESlen)r4   r6   r8   
input_infoinput_category
input_type
extra_infor   r   r   get_input_infoA   s&   

rG   c                   @  s^   e Zd Zdd Zdd Zdd Zdd ZdddZdd Zdd Z	dd Z
dd Zdd Zd
S )TopologicalSortc                 C  s,   || _ i | _i | _i | _d| _t | _d S Nr   )	dynpromptpendingNodes
blockCountblockingexternalBlocksasyncioEventunblockedEvent)r   rJ   r   r   r   r   l   s   zTopologicalSort.__init__c                 C  s$   | j |d }tj| }t||S N
class_type)rJ   r    nodesNODE_CLASS_MAPPINGSrG   )r   	unique_idr6   rS   r4   r   r   r   rG   t   s   

zTopologicalSort.get_input_infoc                 C  sn   | j |d }||vrtd| d| d|| }t|s*td| d| d|\}}| ||| d S )Ninputsr   z says it needs input z+, but there is no input to that node at allz, but that value is a constant)rJ   r    r   r   add_strong_link)r   
to_node_idto_inputrW   valuefrom_node_idfrom_socketr   r   r   make_input_strong_linky   s   z&TopologicalSort.make_input_strong_linkc                 C  s\   |  |s,| | || j| vr!i | j| |< | j|  d7  < d| j| | |< d S d S )Nr@   T)	is_cachedadd_noderM   rL   r   r\   r]   rY   r   r   r   rX      s   

zTopologicalSort.add_strong_linkFNc                 C  s  |g}g }t |dkrw| }|| jv rqd| j|< d| j|< i | j|< | j|d }|D ]B}|| }	t|	rp|	\}
}|d urE|
|vrEq.| ||\}}}|d uoYd|v oY|d }|s^|sp| 	|
sh|
|
 |
|
||f q.t |dks|D ]}| j|  qyd S )Nr   TrW   lazy)rB   poprK   rL   rM   rJ   r    r   rG   r_   appendrX   )r   node_unique_idinclude_lazysubgraph_nodesnode_idslinksrV   rW   r6   r[   r\   r]   _rC   is_lazylinkr   r   r   r`      s6   





zTopologicalSort.add_nodec                   sD    j v s	J d jd7  _j    d7  <  fdd}|S )Nz5Can't add external block to a node that isn't pendingr@   c                     s.    j d8  _ j   d8  < j  d S Nr@   )rN   rL   rQ   r.   r   r   r   r   r   unblock   s   z3TopologicalSort.add_external_block.<locals>.unblock)rL   rN   )r   r   ro   r   rn   r   add_external_block   s
   z"TopologicalSort.add_external_blockc                 C  s   dS )NFr   r   r   r   r   r_      s   zTopologicalSort.is_cachedc                   s    fdd j D S )Nc                   s   g | ]} j | d kr|qS r   )rL   .0r   r1   r   r   
<listcomp>   s    z3TopologicalSort.get_ready_nodes.<locals>.<listcomp>)rK   r1   r   r1   r   get_ready_nodes   r"   zTopologicalSort.get_ready_nodesc                 C  s6   | j |= | j| D ]}| j|  d8  < q	| j|= d S rm   )rK   rM   rL   )r   rV   blocked_node_idr   r   r   pop_node   s   zTopologicalSort.pop_nodec                 C  s   t | jdkS rI   )rB   rK   r1   r   r   r   is_empty   r,   zTopologicalSort.is_empty)FN)r   r   r   r   rG   r^   rX   r`   rp   r_   ru   rw   rx   r   r   r   r   rH   k   s    


rH   c                      st   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z fddZ	dd Z
dd Zdd Zdd Zdd Z  ZS )ExecutionListz
    ExecutionList implements a topological dissolve of the graph. After a node is staged for execution,
    it can still be returned to the graph after having further dependencies added.
    c                   s(   t  | || _d | _i | _i | _d S r   )superr   output_cachestaged_node_idexecution_cacheexecution_cache_listeners)r   rJ   r{   	__class__r   r   r      s
   
zExecutionList.__init__c                 C  s   | j |d uS r   )r{   	get_localr   r   r   r   r_      s   zExecutionList.is_cachedc                 C  sT   || j vr
i | j |< | j|| j | |< || jvr t | j|< | j| | d S r   )r}   r{   r   r~   r.   add)r   r\   rY   r   r   r   
cache_link   s   


zExecutionList.cache_linkc                 C  s<   || j vrd S | j | |}|d u rd S | j|| |S r   )r}   r*   r{   	set_local)r   r\   rY   r[   r   r   r   	get_cache   s   
zExecutionList.get_cachec                 C  s:   || j v r| j | D ]}|| jv r|| j| |< q
d S d S r   )r~   r}   )r   r   r[   rY   r   r   r   cache_update   s   

zExecutionList.cache_updatec                   s    t  ||| | || d S r   )rz   rX   r   ra   r   r   r   rX      s   zExecutionList.add_strong_linkc                   s   | j d u sJ |  rdS |  }t|dkr9| jdkr9| j I d H  | j  |  }t|dkr9| jdkst|dkrm|  }|d }|D ]}| j	
|}||krY|} nqItd}|t|dg g d}d ||fS | || _ | j d d fS )Nr?   r   zDependency cycle detectedzgraph.DependencyCycleError)r   exception_messageexception_type	tracebackcurrent_inputs)r|   rx   ru   rB   rN   rQ   waitclearget_nodes_in_cyclerJ   r-   r   r7   ux_friendly_pick_node)r   	availablecycled_nodesblamed_noder   display_node_idexerror_detailsr   r   r   stage_node_execution   s:   

z"ExecutionList.stage_node_executionc                   s    fdd} fdd}|D ]}||s||r|  S q|D ]} j | D ]}||r2|    S q&q|D ]} j | D ]} j | D ]}||rR|      S qDq=q6|d S )Nc                   s6    j | d }tj| }t|dr|jdkrdS dS )NrS   OUTPUT_NODETF)rJ   r    rT   rU   hasattrr   r   rS   r4   r1   r   r   	is_output  s
   
z6ExecutionList.ux_friendly_pick_node.<locals>.is_outputc                   s,    j | d }tj| }tt||jS rR   )rJ   r    rT   rU   inspectiscoroutinefunctiongetattrFUNCTIONr   r1   r   r   is_async  s   
z5ExecutionList.ux_friendly_pick_node.<locals>.is_asyncr   )rM   )r   	node_listr   r   r   rv   blocked_node_id1r   r1   r   r     s*   	z#ExecutionList.ux_friendly_pick_nodec                 C  s   | j d usJ d | _ d S r   )r|   r1   r   r   r   unstage_node_execution5  s   
z$ExecutionList.unstage_node_executionc                 C  s6   | j }| | | j|d  | j|d  d | _ d S r   )r|   rw   r}   rc   r~   r   r   r   r   complete_node_execution9  s
   

z%ExecutionList.complete_node_executionc                   s   dd | j D  | jD ]}| j| D ]}d| j| |  v r%d | |< qq fdd D }t|dkr]|D ]} D ]}| | v rI | |= q< |= q8 fdd D }t|dks6t  S )Nc                 S  s   i | ]}|i qS r   r   rr   r   r   r   
<dictcomp>D  s    z4ExecutionList.get_nodes_in_cycle.<locals>.<dictcomp>Tc                       g | ]}t  | d kr|qS rq   rB   rr   
blocked_byr   r   rt   I       z4ExecutionList.get_nodes_in_cycle.<locals>.<listcomp>r   c                   r   rq   r   rr   r   r   r   rt   P  r   )rK   rM   valuesrB   listr/   )r   r\   rY   	to_remover   r   r   r   r   @  s$   

z ExecutionList.get_nodes_in_cycle)r   r   r   __doc__r   r_   r   r   r   rX   r   r   r   r   r   __classcell__r   r   r   r   ry      s    
!'ry   r   )r4   r5   r6   r7   r8   r9   r:   r;   )
__future__r   typingr   r   rT   rO   r   comfy_execution.graph_utilsr   r   comfy.comfy_types.node_typingr   r   r	   	Exceptionr   r   r   r   rG   rH   ry   r   r   r   r   <module>   s     .*W