
    Je
,                         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j0                  ej2                  j4                  d<    G d	 d
ee	      Zy)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 | _        | j                  d| j                         | j                  d| j                         y )N_async_error_set_comm_port)superr   __init__remote_comm_portkernel_clientregister_call_handlerr   r   )self	__class__s    P/usr/lib/python3/dist-packages/spyder/plugins/ipythonconsole/comms/kernelcomm.pyr   zKernelComm.__init__(   sO    j$(* $! 	"">43D3DE""#3T5H5HI    c                 p    t         j                  dk(  rt        j                  |i |S t	        d g|i |S )Nnt)osname	zmqtunnelparamiko_tunnelr   )r   argskwargss      r   
ssh_tunnelzKernelComm.ssh_tunnel1   s8    77d?,,d=f==!$8888r   c           	      *   ||| j                   k(  ry|| _         | j                  }t        |d      rP|j                  \  }}}t	        j
                  d      d   }|}|j                  }| j                  ||||||d       |}t        |d      r|j                  |k(  sw||_        |j                  j                  }	|j                  d|		      }
|j                  |
|j                  |j                        |_        | j                  j!                          yy)
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   s   <44#8#88 $##6+,)/)>)>&Hfh"66q9!<JK		IOOK9f"  & D,1A1AT1I#F~~..H44 5 +F"("<"<#7F '',,. 2Jr   c                    	 | j                   j                  }|rb| j                         }|D ];  }| j                   j                  j                  dd|i      }|j                  |       = d| j                   _        yy# t        $ r d}Y rw xY w)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    	((55G ++-G" "((0044&G(<>S!" /3D+   	G	s   A= =B
Bc                 2    | 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   c              #   2  K   |rd y| j                         s)| j                         j                          t        d      | j	                  |      }|D ]-  }| j
                  j                  | j                  |   d   _        / 	 d | j	                  |      }|D ]-  }| j
                  j                  | j                  |   d   _        / y# | j	                  |      }|D ]-  }| j
                  j                  | j                  |   d   _        / w xY w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   s     **,002122''0 	1G""// KK (6	1	6++G4G" 6&&44 G$V,:6 ++G4G" 6&&44 G$V,:6s    BDC ADADDc                     | j                          }| j                  | j                  |      5  t        t        |   |||       ddd       y# 1 sw Y   yxY w)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   sW     !7799&&t';';]K 	+*d:4+	+ 	+ 	+s   AAc                 N    | j                  |      }|D ]  }| j                  |=  y)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 	%GG$	%r   c                     |r| j                          | j                  |      }|D ]'  }| j                  |   d   j                  di ddd       ) y)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   sW    &&(''0 	4GKK (22b$d4	4r   c                 6   || _         d| j                   _        	 | j                  |j                  j	                  | j
                  dt        j                  i             y# t        $ r. t        j                  dt        |j                        z          Y y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3DOO%v'>'>K@3 AB  	KK.03M4N4N0OP	s   AA! !4BBc                 6    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(XWM 3 K 	Kr   c                 Z    d|v r| j                  |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   s0    )#	+ 67Z7	BBr   c                    |d   }d|v xr |d   }| j                   j                         s-|rt        d      t        j	                  dt        |             y|d   }d|v xr |d   }|xs |}|r^| j                         sN| j                         j                          d}t        j                  dt        |      z          |rt        d	      	 | j                  || 
      5  t        t        | ;  |||      cddd       S # 1 sw Y   yxY w# t        $ r6}|r t        j	                  dt        |      t        |             Y d}~y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   sb    Z()Bhz.B!!**,"#344 A	N Z(8+E0E	)	T88:002ILLCI  EFF	**y= + : 3ZEy'33 3 3  
	 =F	N
 
	s6   D $D9	D DD D 	E,E		Ec                       fd}dj                   j                        } j                  | j                  ||       y)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 5;;  "

9d11;Hr   c                     |       ry| j                   j                         st        d      t        d      }t	        |       }|j                  d       |j                  j                  |j                         | j                   j                  j                  j                  |j                         |j                  |j                         |j                  |dz          |       s|j                         s|j                  |j                         | j                   j                  j                  j                  |j                          |       ry| j                   j                         st        d      t        |      |j                           |       s|j!                          |j                  |j                         | j                   j                  j                  j                  |j                         y)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    ;!!**,/00 t$	d|""4( 	$$Y^^4%%1199)..Iy~~& 	7T>*+((*!!)..1""--99DDNN$;))224&'788";//OO + 	)..)%%11<<NN	r   c                 b    t         t        |   ||       | j                  j	                          y)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#  s+     	j$9f	  "r   c                 z    |j                         D ](  }| j                  j                  t        |d             * y)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+  s:     "..0 	D'',,$T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    
 XN#X#D\J9/:3"; 6 60+%	4 EI>CKC0d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      sk    &  	   ; ; 
 ' = B			8	$ 7:jj   + +F 3T7 Tr   