o
    i_g                     @   sB  d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZ zddlmZ W n eyA   dd	lmZ Y nw dd
lmZ ddlmZmZmZ ddlmZ ddlmZmZ G dd deZG dd deZG dd deZ G dd deZ!dZ"dZ#defde" efde" de# e fde" de!fgZ$dS )zTornado handlers for kernels.

Preliminary documentation at https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping#kernels-api
    N)dedent)genweb)Future)IOLoop)protocol_version)json_default)date_default)cast_unicode)maybe_futureurl_path_join
url_escape   )
APIHandler)AuthenticatedZMQStreamHandlerdeserialize_binary_messagec                   @   4   e Zd Zejejdd Zejejdd ZdS )MainKernelHandlerc                 c   s.    | j }t| V }| tj|td d S Ndefault)kernel_managerr   list_kernelsfinishjsondumpsr   )selfkmkernels r   ]/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/notebook/services/kernels/handlers.pyget    s   zMainKernelHandler.getc                 c   s    | j }|  }|d u rd|ji}n|d|j t|j|d dV }t||V }t| jddt	|}| 
d| | d | tj|td d S )Nname)kernel_nameapir   Location   r   )r   get_json_bodydefault_kernel_name
setdefaultr   start_kernelkernel_modelr   base_urlr   
set_header
set_statusr   r   r   r   )r   r   model	kernel_idlocationr   r   r    post'   s   
zMainKernelHandler.postN)	__name__
__module____qualname__r   authenticatedr   	coroutiner!   r2   r   r   r   r    r          r   c                   @   r   )KernelHandlerc                 c   s0    | j }t||V }| tj|td d S r   )r   r   r+   r   r   r   r   )r   r0   r   r/   r   r   r    r!   =   s   zKernelHandler.getc                 c   s.    | j }t||V  | d |   d S )N   )r   r   shutdown_kernelr.   r   )r   r0   r   r   r   r    deleteD   s
   
zKernelHandler.deleteN)	r3   r4   r5   r   r6   r   r7   r!   r<   r   r   r   r    r9   ;   r8   r9   c                   @   s    e Zd Zejejdd ZdS )KernelActionHandlerc              
   c   s    | j }|dkrt||V  | d |dkrUz
t||V  W n tyB } z| jjddd | d W Y d }~nd }~ww t||V }| 	t
j|td |   d S )	N	interruptr:   restartzException restarting kernelTexc_infoi  r   )r   r   interrupt_kernelr.   restart_kernel	Exceptionlogerrorr+   writer   r   r   r   )r   r0   actionr   er/   r   r   r    r2   O   s    
zKernelActionHandler.postN)r3   r4   r5   r   r6   r   r7   r2   r   r   r   r    r=   M   s    r=   c                       s  e Zd ZdZi Zedd Zedd Zedd Zedd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Z fddZej fddZej fddZejdd Z fddZd d! Z fd"d#Z fd$d%Zd&d' Zd(d) Zd*d+ Zd,d- Z  ZS ).ZMQChannelsHandlerz]There is one ZMQChannelsHandler per running kernel and it oversees all
    the sessions.
    c                 C   s   | j j}| jd|S )Nkernel_info_timeout)r   rK   settingsr!   )r   
km_defaultr   r   r    rK   m   s   z&ZMQChannelsHandler.kernel_info_timeoutc                 C      | j ddS )Niopub_msg_rate_limitr   rL   r!   r   r   r   r    rO   r      z'ZMQChannelsHandler.iopub_msg_rate_limitc                 C   rN   )Niopub_data_rate_limitr   rP   rQ   r   r   r    rS   v   rR   z(ZMQChannelsHandler.iopub_data_rate_limitc                 C   rN   )Nrate_limit_windowg      ?rP   rQ   r   r   r    rT   z   rR   z$ZMQChannelsHandler.rate_limit_windowc                 C   s   | j j dt| dd dS )N(r0   uninitialized))	__class__r3   getattrrQ   r   r   r    __repr__~   s   zZMQChannelsHandler.__repr__c                 C   sH   | j }| jj}dD ]}t|d| }|| j|d | j|< }||_q	d S )N)iopubshellcontrolstdinconnect_)identity)r   sessionbsessionrY   r0   channelschannel)r   r   r`   rd   methstreamr   r   r    create_stream   s   z ZMQChannelsHandler.create_streamc                    sD  	j 	j}t|ddkr 	jd	j t }|d |S | 
|	 	j
d t t tg dfdd	d
fdd		} | 	fd
d}	fdd}	fdd}| 
| | t  	
fddjdddt 	j  }| |S )a  Nudge the zmq connections with kernel_info_requests

        Returns a Future that will resolve when we have received
        a shell or control reply and at least one iopub message,
        ensuring that zmq subscriptions are established,
        sockets are fully connected, and kernel is responsive.

        Keeps retrying kernel_info_request until these are both received.
        execution_statebusyz!Nudge: not nudging busy kernel %sNr[   c                    s$    fD ]} |   s| d qdS )zXEnsure all futures are resolved

            which in turn triggers cleanup
            N)done
set_resultf)info_futureiopub_futurer   r    r      s
   
z(ZMQChannelsHandler.nudge.<locals>.finishc                    s:        s    s   dS dS )zCommon cleanupN)remove_timeoutstop_on_recvclosedcloserl   )control_channeliopub_channelloopnudge_handleshell_channelr   r    cleanup   s   
z)ZMQChannelsHandler.nudge.<locals>.cleanupc                    :   j dj   sj dj  d  d S d S )Nz$Nudge: shell info reply received: %sz!Nudge: resolving shell future: %srE   debugr0   rj   rk   msgrn   r   r   r    on_shell_reply   
   z0ZMQChannelsHandler.nudge.<locals>.on_shell_replyc                    rz   )Nz&Nudge: control info reply received: %sz#Nudge: resolving control future: %sr{   r}   r   r   r    on_control_reply   r   z2ZMQChannelsHandler.nudge.<locals>.on_control_replyc                    sB   j dj  s   j dj d  d S d S )NzNudge: IOPub received: %sz!Nudge: resolving iopub future: %s)rE   r|   r0   rj   rq   rk   r}   )ru   ro   r   r   r    on_iopub   s   z*ZMQChannelsHandler.nudge.<locals>.on_iopubc                    s  | d7 } j d u sj  rjdj   d S jjvr.jdj   d S  r?jdj   d S  rPjdj   d S   s| d dkr^jjnjj}|d|  dj  j	
d	 j	
d	 d
| d S d S )N   z)Nudge: cancelling on closed websocket: %sz'Nudge: cancelling on stopped kernel: %sz*Nudge: cancelling on closed zmq socket: %s
   r   zNudge: attempt z on kernel kernel_info_requestg      ?)ws_connection
is_closingrE   r|   r0   r   rr   rj   warningra   send
call_later)countrE   )	both_donert   r   rv   nudgerw   r   rx   r   r    r      s<   z'ZMQChannelsHandler.nudge.<locals>.nudger   )r   N)r   
get_kernelr0   rY   rE   r|   r   rk   connect_shellconnect_controlrc   r   multiadd_done_callbackon_recvr   currentr   with_timeouttimerK   )r   kernelrm   ry   r   r   r   futurer   )r   rt   r   rn   ru   ro   rv   r   rw   r   rx   r    r      s6   


	




*
zZMQChannelsHandler.nudgec                    s    j }| j}z|j}W n2 ty@    jd j  jdu r)| j _ j	 j
  j jd  j|_Y  jS w | sK jd | fdd  jS )zsend a request for kernel_infozRequesting kernel info from %sNr   z'Waiting for pending kernel_info requestc                    s     |  S r   )_finish_kernel_inforesultrl   rQ   r   r    <lambda>!  s    z8ZMQChannelsHandler.request_kernel_info.<locals>.<lambda>)r   r   r0   _kernel_info_futureAttributeErrorrE   r|   kernel_info_channelr   r   _handle_kernel_info_replyra   r   rj   r   )r   r   r   r   r   rQ   r    request_kernel_info  s"   


z&ZMQChannelsHandler.request_kernel_infoc                 C   s   | j |\}}z| j |}W n   | jjddd | ji  Y dS |d }| jd| |d dks:d	|vrC| jd
| i }| | | j	rP| j	
  d| _	dS )zZprocess the kernel_info_reply

        enabling msg spec adaptation, if necessary
        zBad kernel_info replyTr@   NcontentzReceived kernel info: %smsg_typekernel_info_replyr   z/Kernel info request failed, assuming current %s)ra   feed_identitiesdeserializerE   rF   r   rk   r|   r   r   rs   )r   r~   identsinfor   r   r    r   $  s    


z,ZMQChannelsHandler._handle_kernel_info_replyc              	   C   sj   | dt}|tkr&t|dd | j_| jd| d| j dt d | j	
 s3| j	| dS dS )	zFinish handling kernel_info reply

        Set up protocol adaptation, if needed,
        and signal that connection can continue.
        r   .r   zAdapting from protocol version z	 (kernel z) to z
 (client).N)r!   client_protocol_versionintsplitra   adapt_versionrE   r   r0   r   rj   rk   )r   r   r   r   r   r    r   =  s   "
z&ZMQChannelsHandler._finish_kernel_infoc                    sZ   t    d | _i | _d | _d | _t | _t | _d| _	d| _
d| _d| _d| _g | _d S )N r   F)super
initialize
zmq_streamrc   r0   r   r   r   _close_futuresession_key_iopub_window_msg_count_iopub_window_byte_count_iopub_msgs_exceeded_iopub_data_exceeded_iopub_window_byte_queuerQ   rX   r   r    r   J  s   

zZMQChannelsHandler.initializec                 #   sn    t     V  jj}|jjj_   fdd}t	
 }|| j |  V  d S )Nc                      s*      rdS jdj  i  dS )z*Don't wait forever for the kernel to replyNz-Timeout waiting for kernel_info reply from %s)rj   rE   r   r0   rk   r   r   r   r   r    give_upk  s   z+ZMQChannelsHandler.pre_get.<locals>.give_up)r   pre_get_register_sessionr   r   r0   ra   keyr   r   r   add_timeoutr   rK   )r   r   r   rv   r   r   r    r   ^  s   


zZMQChannelsHandler.pre_getc                 #   s"    t |d| _t j|dV  d S )Nascii)r0   )r
   r0   r   r!   )r   r0   r   r   r    r!   v  s   zZMQChannelsHandler.getc                 c   sd    | j  d| jj | _| j| j}|r"| jd| j | V  | j | jv r0| | j| j< dS dS )a#  Ensure we aren't creating a duplicate session.

        If a previous identical session is still open, close it to avoid collisions.
        This is likely due to a client reconnecting from a lost network connection,
        where the socket on our side has not been cleaned up yet.
        :zReplacing stale connection: %sN)	r0   ra   r   _open_sessionsr!   rE   r   rs   r   )r   stale_handlerr   r   r    r   {  s   
z$ZMQChannelsHandler._register_sessionc           	   
      s*  t    j}|| ||j  r; d jkr;jdj  d _	 } fdd}|
| n<z
  	 }W n1 tjyv } z$jd| j D ]\}}| sf|  qZ  W Y d }~d S d }~ww |jj |jjd fdd	}|
| |S )
Nr   zRestoring connection for %src   c                    sJ    d }|r!j dt| |D ]\}}j| }|| qd S d S )NbufferzReplaying %s buffered messages)rE   r   lenrc   _on_zmq_reply)valuereplay_bufferrd   msg_listrf   buffer_infor   r   r    replay  s   
z'ZMQChannelsHandler.open.<locals>.replayzError opening stream: %sdeadc                    s$    j  D ]
\}}| j qd S r   )rc   itemson_recv_streamr   )r   rd   rf   rQ   r   r    	subscribe  s   z*ZMQChannelsHandler.open.<locals>.subscribe)r   openr   notify_connect
get_bufferr   rE   r   rc   r   r   rg   r   	HTTPErrorrF   r   rr   rs   add_restart_callbackr0   on_kernel_restartedon_restart_failed)	r   r0   r   	connectedr   rI   rd   rf   r   r   r   r    r     s8   




zZMQChannelsHandler.openc                 C   s   | j s| jd| d S t|trt|}nt|}|dd }|d u r.| j	d| d}|| j vr<| j	d| d S | j
j}|d d }|rX||vrX| j	d| d	 d S | j | }| j|| d S )
Nz'Received message on closed websocket %rrd   z(No channel specified, assuming shell: %sr\   zNo such channel: %rheaderr   zReceived message of type "z"", which is not allowed. Ignoring.)rc   rE   r|   
isinstancebytesr   r   loadspopr   r   allowed_message_typesra   r   )r   r~   rd   ammtrf   r   r   r    
on_message  s&   




zZMQChannelsHandler.on_messagec                    s  j |\}}j |}|d   fdd}t|dd }|d d }|dkrE|dkrE|d	 d
dkrEg _d_d_d_d_	|dkrM|dvrMt
  }	tjdkrjd }
|	|
d kr| j|
d 8  _ jd8  _jd= nntjdks\ jd7  _|dkrtdd |D }nd} j|7  _j|	j |f tjj }tjj }jdkr|jkr݈jsd_|tdj dj d njr|dj k rd_j	sjd jdkr|jkrj	sd_	|tdj dj d nj	r/|dj k r/d_	js/jd js7j	rM jd8  _ j|8  _jd d S t || d S )Nparent_headerc                    sH   j |  jjd| d dd d}d|d< tj|td d S )	Nrf   
stderr)textr"   )r   parentr[   rd   r   )rE   r   ra   r~   write_messager   r   r   )error_messager~   r   r   r   r    write_stderr  s   z6ZMQChannelsHandler._on_zmq_reply.<locals>.write_stderrrd   r   r   r[   statusr   rh   idler   F>   r   	comm_openexecute_inputr   rf   c                 s   s    | ]}t |V  qd S r   )r   ).0xr   r   r    	<genexpr>  s    z3ZMQChannelsHandler._on_zmq_reply.<locals>.<genexpr>Ta                      IOPub message rate exceeded.
                    The notebook server will temporarily stop sending output
                    to the client in order to avoid crashing it.
                    To change this limit, set the config variable
                    `--NotebookApp.iopub_msg_rate_limit`.

                    Current values:
                    NotebookApp.iopub_msg_rate_limit=z> (msgs/sec)
                    NotebookApp.rate_limit_window=z (secs)
                    g?ziopub messages resumeda                      IOPub data rate exceeded.
                    The notebook server will temporarily stop sending output
                    to the client in order to avoid crashing it.
                    To change this limit, set the config variable
                    `--NotebookApp.iopub_data_rate_limit`.

                    Current values:
                    NotebookApp.iopub_data_rate_limit=z? (bytes/sec)
                    NotebookApp.rate_limit_window=)ra   r   r   rY   r!   r   r   r   r   r   r   r   r   r   sumappendrT   floatrO   r   rE   r   rS   r   r   r   )r   rf   r   r   fed_msg_listr~   r   rd   r   nowqueued
byte_countmsg_rate	data_rater   r   r    r     s|   "

		z ZMQChannelsHandler._on_zmq_replyc                    s   t    | jS r   )r   rs   r   rQ   r   r   r    rs   >  s   
zZMQChannelsHandler.closec                 C   s   | j d| j | j| j| u r| j| j | j}| j|v rQ|| j |	| j| j
 |	| j| jd |j| j dkrQ|| j| j| j | jd  d S | j D ]\}}|d urk| sk|d  |  qVi | _| jd  d S )NzWebsocket closed %sr   r   )rE   r|   r   r   r!   r   r   r0   notify_disconnectremove_restart_callbackr   r   _kernel_connectionsstart_bufferingrc   r   rk   r   rr   r   rs   )r   r   rd   rf   r   r   r    on_closeB  s.   


zZMQChannelsHandler.on_closec                 C   sT   | j dd }|r| s|  | jdd|i}d|d< | tj|t	d d S )Nr[   r   rh   rd   r   )
rc   r!   rr   flushra   r~   r   r   r   r   )r   r   r[   r~   r   r   r    _send_status_messagec  s   z'ZMQChannelsHandler._send_status_messagec                 C      t d| j | d d S )Nzkernel %s restarted
restarting)loggingwarnr0   r  rQ   r   r   r    r   p     z&ZMQChannelsHandler.on_kernel_restartedc                 C   r  )Nzkernel %s restarted failed!r   )r  rF   r0   r  rQ   r   r   r    r   t  r  z$ZMQChannelsHandler.on_restart_failed)r3   r4   r5   __doc__r   propertyrK   rO   rS   rT   rZ   rg   r   r   r   r   r   r   r7   r   r!   r   r   r   r   rs   r  r  r   r   __classcell__r   r   r   r    rJ   c   sB    



 
.m!rJ   z"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)z(?P<action>restart|interrupt)z/api/kernelsz/api/kernels//z	/channels)%r	  r   r  textwrapr   tornador   r   tornado.concurrentr   tornado.ioloopr   jupyter_clientr   r   jupyter_client.jsonutilr   ImportErrorr	   ipython_genutils.py3compatr
   notebook.utilsr   r   r   base.handlersr   base.zmqhandlersr   r   r   r9   r=   rJ   _kernel_id_regex_kernel_action_regexdefault_handlersr   r   r   r    <module>   s@        