a
    D¿be)  ã                   @   s>  d dl 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 d dl	m
Z
mZ d dlm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mZmZ d dlmZ d dlmZ d dlmZ ddl m!Z! e"e  #dd¡ƒZ$G dd„ deeƒZ%G dd„ deƒZ&G dd„ deƒZ'ddl(m)Z) ddl*m+Z+ de) e%fde+ e'fgZ,dS )é    Né   )Ú
APIHandlerÚIPythonHandler)Úurl_path_join)ÚgenÚweb)ÚFuture)ÚIOLoopÚPeriodicCallback)ÚWebSocketHandlerÚwebsocket_connect)ÚHTTPRequest)Ú
url_escapeÚjson_decodeÚutf8)Úcast_unicode)ÚSession)ÚLoggingConfigurableé   )ÚGatewayClientÚGATEWAY_WS_PING_INTERVAL_SECSé   c                       sš   e Zd ZdZdZdZdZddd„Zdd„ Zdd„ Z	dd	„ Z
d
d„ Zej‡ fdd„ƒZdd„ Zdd„ Zdd„ Zd‡ fdd„	Z‡ fdd„Zedd„ ƒZ‡  ZS )ÚWebSocketChannelsHandlerNc                 C   s   t  | |¡S ©N)r   Úcheck_origin)ÚselfÚorigin© r   ú8lib/python3.9/site-packages/notebook/gateway/handlers.pyr   $   s    z%WebSocketChannelsHandler.check_originc                 C   s   dS )zVUndo the set_default_headers in IPythonHandler which doesn't make sense for websocketsNr   ©r   r   r   r   Úset_default_headers'   s    z,WebSocketChannelsHandler.set_default_headersc                 C   s   i S r   r   r   r   r   r   Úget_compression_options+   s    z0WebSocketChannelsHandler.get_compression_optionsc                 C   sR   |   ¡ du r"| j d¡ t d¡‚|  dd¡rBt|  d¡ƒ| j_n| j d¡ dS )z™Run before finishing the GET request

        Extend this method to add logic that should fire before
        the websocket finishes completing.
        Nz*Couldn't authenticate WebSocket connectioni“  Z
session_idFzNo session ID specified)Zget_current_userÚlogÚwarningr   Z	HTTPErrorZget_argumentr   Úsessionr   r   r   r   Úauthenticate/   s    
z%WebSocketChannelsHandler.authenticatec                 C   s6   | j  d| jj¡ t| jd| _tt 	¡ j
d| _d S )Nz$Initializing websocket connection %s)Úconfig)Zgateway_url)r"   ÚdebugÚrequestÚpathr   r&   r$   ÚGatewayWebSocketClientr   ÚinstanceÚurlÚgatewayr   r   r   r   Ú
initialize?   s    z#WebSocketChannelsHandler.initializec                 /   s0   |   ¡  t|dƒ| _tƒ j|d|i|¤ŽV  d S )NÚasciiÚ	kernel_id)r%   r   r0   ÚsuperÚget©r   r0   ÚargsÚkwargs©Ú	__class__r   r   r2   D   s    zWebSocketChannelsHandler.getc                 C   s0   | j d u r"| jd ur"| j ¡  d S |  d¡ d S )Nó    )Úws_connectionÚping_callbackÚstopZpingr   r   r   r   Ú	send_pingJ   s    
z"WebSocketChannelsHandler.send_pingc                 O   s8   t | jtd ƒ| _| j ¡  | jj|| j|  ¡ d dS )z`Handle web socket connection open to notebook server and delegate to gateway web socket handler iè  )r0   Úmessage_callbackZcompression_optionsN)	r
   r<   r   r:   Ústartr-   Úon_openÚwrite_messager!   r3   r   r   r   ÚopenQ   s    
ýzWebSocketChannelsHandler.openc                 C   s   | j  |¡ dS )z.Forward message to gateway web socket handler.N)r-   Ú
on_message)r   Úmessager   r   r   rB   \   s    z#WebSocketChannelsHandler.on_messageFc                    s\   | j r&t|tƒrd}tƒ j||d n2| j tj¡rXt	 
tt|ƒƒ¡}| j d |¡¡ dS )zdSend message back to notebook client.  This is called via callback from self.gateway._read_messages.T)ÚbinaryzANotebook client closed websocket connection - message dropped: {}N)r9   Ú
isinstanceÚbytesr1   r@   r"   ZisEnabledForÚloggingÚDEBUGr   Ú_get_message_summaryr   r   r'   Úformat)r   rC   rD   Zmsg_summaryr6   r   r   r@   `   s    
z&WebSocketChannelsHandler.write_messagec                    s*   | j  d| jj¡ | j ¡  tƒ  ¡  d S )NzClosing websocket connection %s)r"   r'   r(   r)   r-   Úon_closer1   r   r6   r   r   rK   j   s    
z!WebSocketChannelsHandler.on_closec                 C   sˆ   g }| d }|  d |¡¡ |dkr>|  d | d d ¡¡ n@|dkrt|  d | d d	 | d d
 | d d ¡¡ n
|  d¡ d |¡S )NZmsg_typeztype: {}Zstatusz, state: {}ZcontentZexecution_stateÚerrorz
, {}:{}:{}ZenameZevalueÚ	tracebackz, ...Ú )ÚappendrJ   Újoin)rC   ZsummaryZmessage_typer   r   r   rI   o   s    

þ
z-WebSocketChannelsHandler._get_message_summary)N)F)Ú__name__Ú
__module__Ú__qualname__r$   r-   r0   r:   r   r    r!   r%   r.   r   Ú	coroutiner2   r<   rA   rB   r@   rK   ÚstaticmethodrI   Ú__classcell__r   r   r6   r   r      s$   

r   c                       sl   e Zd ZdZ‡ fdd„Zejdd„ ƒZdd„ Zdd	„ Z	ejd
d„ ƒZ
dd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )r*   z;Proxy web socket connection to a kernel/enterprise gateway.c                    s6   t ƒ jf i |¤Ž d | _d | _tƒ | _d| _d| _d S )NFr   )r1   Ú__init__r0   Úwsr   Ú	ws_futureÚdisconnectedÚretry)r   r5   r6   r   r   rW   „   s    zGatewayWebSocketClient.__init__c                 C   s€   d | _ || _tt ¡ jt ¡ jt|ƒdƒ}| j 	d 
|¡¡ i }t ¡ jf i |¤Ž}t|fi |¤Ž}t|ƒ| _| j | j¡ d S )NZchannelszConnecting to {})rX   r0   r   r   r+   Úws_urlZkernels_endpointr   r"   ÚinforJ   Zload_connection_argsr   r   rY   Zadd_done_callbackÚ_connection_done)r   r0   r\   r5   r(   r   r   r   Ú_connectŒ   s    þ
zGatewayWebSocketClient._connectc                 C   sX   | j s8| ¡ d u r8| ¡ | _d| _| j d | j¡¡ n| j d | j	t
 ¡ j¡¡ d S )Nr   zConnection is ready: ws: {}z‹Websocket connection has been closed via client disconnect or due to error.  Kernel with ID '{}' may not be terminated on GatewayClient: {})rZ   Z	exceptionÚresultrX   r[   r"   r'   rJ   r#   r0   r   r+   r,   )r   Zfutr   r   r   r^      s    

þz'GatewayWebSocketClient._connection_donec                 C   sH   d| _ | jd ur| j ¡  n(| j ¡ sD| j ¡  | j d | j ¡¡ d S )NTz/_disconnect: future cancelled, disconnected: {})	rZ   rX   ÚcloserY   ZdoneZcancelr"   r'   rJ   r   r   r   r   Ú_disconnect§   s    


z"GatewayWebSocketClient._disconnectc              
   #   sD  ˆj durŽd}ˆjsŽzˆj  ¡ V }W n6 tyZ } zˆj d |¡¡ W Y d}~n
d}~0 0 |du r€ˆjsŽˆj d ˆj¡¡ qŽˆ |ƒ q qŽq ˆjs@ˆj	t
 ¡ jk r@t dd¡d }tt
 ¡ jdˆj	  t
 ¡ jƒ| }ˆ j	d7  _	ˆj d	|ˆj	t
 ¡ jˆj¡ t |¡V  ˆ ˆj¡ t ¡ }| ˆj‡ ‡fd
d„¡ dS )z"Read messages from gateway server.Nz,Exception reading message from websocket: {}zLost connection to Gateway: {}é
   éd   g{®Gáz„?r   r   zKAttempting to re-establish the connection to Gateway in %s secs (%s/%s): %sc                    s
   ˆ  ˆ ¡S r   ©Ú_read_messages©Zfuture©Úcallbackr   r   r   Ú<lambda>Î   r8   z7GatewayWebSocketClient._read_messages.<locals>.<lambda>)rX   rZ   Zread_messageÚ	Exceptionr"   rL   rJ   r#   r0   r[   r   r+   Zgateway_retry_maxÚrandomZrandintÚminZgateway_retry_intervalZgateway_retry_interval_maxr]   r   Úsleepr_   r	   ÚcurrentÚ
add_futurerY   )r   ri   rC   ÚeZjitterZretry_intervalÚloopr   rh   r   rf   ±   s8    
(
ÿÿÿz%GatewayWebSocketClient._read_messagesc                    s.   ˆ  |¡ t ¡ }| ˆj‡ ‡fdd„¡ dS )z2Web socket connection open against gateway server.c                    s
   ˆ  ˆ ¡S r   re   rg   ©r=   r   r   r   rj   Ö   r8   z0GatewayWebSocketClient.on_open.<locals>.<lambda>N)r_   r	   ro   rp   rY   )r   r0   r=   r5   rr   r   rs   r   r?   Ð   s    
þzGatewayWebSocketClient.on_openc                    s:   ˆj du r,t ¡ }| ˆj‡ ‡fdd„¡ n
ˆ ˆ ¡ dS )úSend message to gateway server.Nc                    s
   ˆ  ˆ ¡S r   )Ú_write_messagerg   ©rC   r   r   r   rj   ß   r8   z3GatewayWebSocketClient.on_message.<locals>.<lambda>)rX   r	   ro   rp   rY   ru   )r   rC   rr   r   rv   r   rB   Ù   s    
þz!GatewayWebSocketClient.on_messagec              
   C   s\   z | j s| jdur| j |¡ W n6 tyV } z| j d |¡¡ W Y d}~n
d}~0 0 dS )rt   Nz*Exception writing message to websocket: {})rZ   rX   r@   rk   r"   rL   rJ   )r   rC   rq   r   r   r   ru   ä   s
    z%GatewayWebSocketClient._write_messagec                 C   s   |   ¡  dS )zWeb socket closed event.N)rb   r   r   r   r   rK   ì   s    zGatewayWebSocketClient.on_close)rQ   rR   rS   Ú__doc__rW   r   rT   r_   r^   rb   rf   r?   rB   ru   rK   rV   r   r   r6   r   r*      s   



	r*   c                   @   s&   e Zd ZdZejejddd„ƒƒZdS )ÚGatewayResourceHandlerzWRetrieves resources for specific kernelspec definitions from kernel/enterprise gateway.Tc                 c   sV   | j }| ||¡V }|d u r2| j d ||¡¡ n|  dt |¡d ¡ |  |¡ d S )NzWKernelspec resource '{}' for '{}' not found.  Gateway may not support resource serving.zContent-Typer   )	Zkernel_spec_managerZget_kernel_spec_resourcer"   r#   rJ   Z
set_headerÚ	mimetypesZ
guess_typeZfinish)r   Zkernel_namer)   Zinclude_bodyZksmZkernel_spec_resr   r   r   r2   ô   s    
ÿzGatewayResourceHandler.getN)T)	rQ   rR   rS   rw   r   Zauthenticatedr   rT   r2   r   r   r   r   rx   ñ   s   rx   )Ú_kernel_id_regex)Úkernel_name_regexz/api/kernels/%s/channelsz/kernelspecs/%s/(?P<path>.*))-ÚosrG   ry   rl   Zbase.handlersr   r   Zutilsr   Ztornador   r   Ztornado.concurrentr   Ztornado.ioloopr	   r
   Ztornado.websocketr   r   Ztornado.httpclientr   Ztornado.escaper   r   r   Zipython_genutils.py3compatr   Zjupyter_client.sessionr   Ztraitlets.config.configurabler   Zmanagersr   ÚintÚgetenvr   r   r*   rx   Zservices.kernels.handlersrz   Zservices.kernelspecs.handlersr{   Zdefault_handlersr   r   r   r   Ú<module>   s0   dp

þ