
    G@d
,                         d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	m
Z
mZ ddlZddlmZ ddlmZmZ ddlmZ  ej        e          Zej        ej        j        d<    G d	 d
ee	          ZdS )zk
In addition to the remote_call mechanism implemented in CommBase:
 - Send a message to a debugging kernel
    )contextmanagerN)
QEventLoopQObjectQTimerSignal)tunnel)CommBase	CommError)openssh_tunnelcommc                        e Zd ZdZ e            Z e            Z ee          Z fdZ	d Z
d Zd Zd Zedd            Zd fd		ZddZddZd Z	 	 d fd	Z fdZ fdZd Zd Z fdZd Z xZS )
KernelCommzf
    Class with the necessary attributes and methods to handle
    communications with a console.
    c                     t          t          |                                            d | _        d | _        |                     d| j                   |                     d| j                   d S )N_async_error_set_comm_port)superr   __init__remote_comm_portkernel_clientregister_call_handlerr   r   )self	__class__s    Nlib/python3.11/site-packages/spyder/plugins/ipythonconsole/comms/kernelcomm.pyr   zKernelComm.__init__(   sj    j$((*** $! 	"">43DEEE""#3T5HIIIII    c                 d    t           j        dk    rt          j        |i |S t	          d g|R i |S )Nnt)osname	zmqtunnelparamiko_tunnelr   )r   argskwargss      r   
ssh_tunnelzKernelComm.ssh_tunnel1   sA    7d??,d=f===!$8888888r   c           	         ||| j         k    rdS || _         | j        }t          |d          rL|j        \  }}}t	          j        d          d         }|}|j        }|                     ||||||d           |}t          |d          r|j        |k    sk||_        |j	        j
        }	|                    d|		          }
|                    |
|j	        |j                  |_        | j                                         dS dS )
zSet comm port.Nssh_parameters   r   
   )timeout	comm_portr   )identity)r   r   hasattrr%   r   select_random_portsipr#   r)   sessionbsession_create_connected_socketshell_channel_classioloopcomm_channel_sig_comm_port_changedemit)r   portclienthostnamesshkeypassword
local_portremote_port	remote_ipr*   sockets              r   r   zKernelComm._set_comm_port7   s7   <44#888F $#6+,, 		)/)>&Hfh"6q99!<JK	IOOK9f"  & & & D,, 	/1AT1I1I#F~.H44 5 + +F"("<"<#7 #7F ',,..... 2J1Ir   c                    	 | j         j        }n# t          $ r d}Y nw xY w|r^|                                 }|D ]9}| j         j                            dd|i          }|                    |           :d| j         _        dS dS )zShutdown the comm channel.Nshutdown_requestcomm_id)r   r3   AttributeErrorget_comm_id_listr.   msgsend)r   channelid_listrA   rD   s        r   shutdown_comm_channelz KernelComm.shutdown_comm_channelT   s    	(5GG 	 	 	GGG	  	3++--G" " "(044&G(<> >S!!!!.2D+++	3 	3s    c                     | j         j        duS )z'Check if the comm channel is connected.N)r   r3   )r   s    r   comm_channel_connectedz!KernelComm.comm_channel_connectede   s    !.d::r   Fc              #   (  K   |rdV  dS |                                  s5|                                                                  t          d          |                     |          }|D ]$}| j        j        | j        |         d         _        %	 dV  |                     |          }|D ]$}| j        j	        | j        |         d         _        %dS # |                     |          }|D ]$}| j        j	        | j        |         d         _        %w xY w)z*Use comm_channel instead of shell_channel.NzComm not connected.r   )
rJ   remote_call_send_comm_configr
   rC   r   r3   _comms_send_channelshell_channel)r   rA   queue_messagerG   s       r   comm_channel_managerzKernelComm.comm_channel_manageri   sH       	EEEF**,, 	3002221222''00 	1 	1G"/ K (66	6EEE++G44G" 6 6&4 G$V,::6 6 ++G44G" 6 6&4 G$V,::6s   C >Dc                     |                                   }|                     | j        |          5  t          t          |                               |||           ddd           dS # 1 swxY w Y   dS )z1Override to use the comm_channel for all replies.N)rJ   rR   calling_comm_idr   r   _set_call_return_value)r   	call_dictdatais_errorrQ   r   s        r   rU   z!KernelComm._set_call_return_value   s     !77999&&t';]KK 	+ 	+*d##::4+ + +	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+s   +A**A.1A.Nc                 J    |                      |          }|D ]
}| j        |= dS )zu
        Remove the comm without notifying the other side.

        Use when the other side is already down.
        N)rC   rN   )r   rA   rG   s      r   removezKernelComm.remove   s=     ''00 	% 	%GG$$	% 	%r   Tc                     |r|                                   |                     |          }|D ],}| j        |         d                             di ddd           -dS )z/Ask kernel to close comm and send confirmation.r   
comm_closeN)rH   rC   rN   	_send_msg)r   rA   shutdown_channelrG   s       r   closezKernelComm.close   s|     	)&&(((''00 	4 	4GK (22b$d4 4 4 4	4 	4r   c                 .   || _         d| j         _        	 |                     |j                            | j        dt          j        i                     dS # t          $ r3 t          
                    dt          |j                  z              Y dS w xY w)z$Open comm through the kernel client.Npickle_protocol)rW   zOUnable to open comm due to unexistent comm manager: kernel_client.comm_manager=)r   r3   _register_commcomm_managernew_comm
_comm_namepickleHIGHEST_PROTOCOLrB   loggerinfostr)r   r   s     r   	open_commzKernelComm.open_comm   s    **.'		*33DO%v'>K@3 A AB B B B B  	 	 	KK.03M4N0O0OP     	s   A A 9BBc                 `    t          t          |                               ||||||          S )zGet a handler for remote calls.)	interruptblockingcallbackrA   r(   display_error)r   r   rL   )r   rm   rn   ro   rA   r(   rp   r   s          r   rL   zKernelComm.remote_call   s=     Z&&22(XWM 3 K K 	Kr   c                     d|v r|                      |d                    t          t          |                               |          S )zA call was receivedr)   )r   r   r   on_incoming_call)r   rV   r   s     r   rr   zKernelComm.on_incoming_call   sE    )##	+ 6777Z&&77	BBBr   c                 R   |d         }d|v o|d         }| j                                         s;|rt          d          t                              dt          |                     dS |d         }d|v o|d         }|p|}|rw|                                 sc|                                                                  d}t          	                    dt          |          z              |rt          d	          	 |                     || 
          5  t          t          |                               |||          cddd           S # 1 swxY w Y   dS # t          $ rD}|r t                              dt          |          t          |                     Y d}~dS d}~ww xY w)z0
        Interupt the kernel if needed.
        settingsrn   Kernel is deadz+Dropping message because kernel is dead: %sNrm   Fz1Dropping interrupt because comm is disconnected: z#Cannot block on a disconnected comm)rQ   z'Dropping message because of exception: )r   is_aliveRuntimeErrorrh   ri   rj   rJ   rL   rM   debugr
   rR   r   r   _get_call_return_value)	r   rV   	call_datarA   rt   rn   rm   er   s	           r   ry   z!KernelComm._get_call_return_value   s<    Z()Bhz.B!**,, 		 "#3444 A	NN   Z(8+E0E	)	 
	GT88:: 
	G00222ILLCI    G EFFF	**y= + : : 3 3Z..EEy'3 33 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3  
	 
	 
	 	 =FF	NN  
 
	s<   <E *E>E EE EE 
F&"9F!!F&c                       fd}d                      j                  }                     | j        ||           dS )zWait for the other side reply.c                       j         v S N)_reply_inbox)call_idr   s   r   	got_replyz)KernelComm._wait_reply.<locals>.got_reply   s    d///r   zTimeout while waiting for {}N)format_reply_waitlist_wait_sig_got_reply)r   r   	call_namer(   r   timeout_msgs   ``    r   _wait_replyzKernelComm._wait_reply   s`    	0 	0 	0 	0 	0 	0 5;; " "

9d1;HHHHHr   c                     |            rdS | j                                         st          d          t          d          }t	          |           }|                    d           |j                            |j                   | j         j	        j
                            |j                   |                    |j                   |                    |dz              |            s|                                s|                    |j                   | j         j	        j
                            |j                    |            rdS | j                                         st          d          t          |          |                                  |            |                                 |                    |j                   | j         j	        j
                            |j                   dS )z
        Wait until condition() is True by running an event loop.

        signal: qt signal that should interrupt the event loop.
        timeout_msg: Message to display in case of a timeout.
        timeout: time in seconds before a timeout
        Nru   Ti  )r   rv   rw   r   r   setSingleShotr(   connectquit
hb_channelkernel_diedstartisActive
disconnectTimeoutErrorexec_stop)r   	conditionsignalr   r(   	wait_loopwait_timeouts          r   r   zKernelComm._wait   s    9;; 	F!**,, 	1/000 t$$	d||""4((( 	$$Y^444%199).IIIy~&&& 	7T>***)++ 
	((** 0!!).111"-9DDN$ $ $9;; F)2244 9&'7888";///OO )++ 
	 	).)))%1<<N	 	 	 	 	r   c                     t          t          |                               ||           | j                                         dS )z3
        A blocking call received a reply.
        N)r   r   _handle_remote_call_replyr   r5   )r   msg_dictbufferr   s      r   r   z$KernelComm._handle_remote_call_reply#  sG     	j$99f	 	 	  """""r   c                     |                                 D ]+}| j                            t          |d                     ,dS )zR
        Handle an error that was raised on the other side and sent back.
        T)textis_tracebackN)format_errorsig_exception_occurredr5   dict)r   error_wrapperlines      r   r   zKernelComm._async_error+  sY     "..00 	 	D',,$T222   	 	r   )Fr~   )NT)FFNNNF)__name__
__module____qualname____doc__r   r   r4   r   r   r   r#   r   rH   rJ   r   rR   rU   rZ   r_   rk   rL   rr   ry   r   r   r   r   __classcell__)r   s   @r   r   r      s        
 VXXN#VXX#VD\\J J J J J9 9 9/ / /:3 3 3"; ; ; 6 6 6 ^60+ + + + + +% % % %	4 	4 	4 	4   EI>CK K K K K KC C C C C0 0 0 0 0dI I I) ) )V# # # # #      r   r   )r   
contextlibr   loggingr   rf   jupyter_clientqtpy.QtCorer   r   r   r   zmqzmq.sshr   r   spyder_kernels.comms.commbaser	   r
   'spyder.plugins.ipythonconsole.utils.sshr   	getLoggerr   rh   DEALERr   channel_socket_typesr    r   r   <module>r      s    & % % % % %  				      ; ; ; ; ; ; ; ; ; ; ; ; 



 ' ' ' ' ' ' = = = = = = = = B B B B B B		8	$	$ 7:j  +F 3T T T T T7 T T T T Tr   