
    eC                    
   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Zddl	Z	ddl
Z
ddl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ZddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddl m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z'm(Z(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m1Z1 ddl2m3Z3m4Z4m5Z5 ddl6m6Z6  e	j7        e8          Z9dZ:dZ; e5j<        d          Z=d-dZ>d  Z?d! Z@d"ZAd.d'ZB G d( d)e,          ZC G d* d+e%e,          ZDd, ZEeEZFdS )/a!  
The Panel jupyter_server_extension implements Jupyter RequestHandlers
that allow a Panel application to run inside Jupyter kernels. This
allows Panel applications to be served in the kernel (and therefore
the environment) they were written for.

The `PanelJupyterHandler` may be given the path to a notebook, .py
file or Lumen .yaml file. It will then attempt to resolve the
appropriate kernel based on the kernelspec or a query parameter. Once
the kernel has been provisioned the handler will execute a code snippet
on the kernel which creates a `PanelExecutor`. The `PanelExecutor`
creates a `bokeh.server.session.ServerSession` and connects it to a
Jupyter Comm. The `PanelJupyterHandler` will then serve the result of
executor.render().

Once the frontend has rendered the HTML it will send a request to open
a WebSocket will be sent to the `PanelWSProxy`. This in turns forwards
any messages it receives via the kernel.shell_channel and the Comm to
the PanelExecutor. This way we proxy any WS messages being sent to and
from the server to the kernel.
    )annotationsN)Empty)Any	Awaitable)urljoin)extension_dirs)Protocol)ProtocolError)Receiver)DEFAULT_KEEP_ALIVE_MS)MultiRootStaticHandler)StaticHandler)	WSHandler)generate_jwt_tokengenerate_session_idget_session_idget_token_payload)JupyterHandler)PeriodicCallback)StaticFileHandler   )config   )DIST_DIRERROR_TEMPLATE_env)state<      zkernel_error.htmlobjAwaitable | Anyreturnr   c                   K   t          j        |           r9	 |  d{V }n-# t          $ r }t          |          dk    r| cY d}~S  d}~ww xY w|S | S )zmConvert a non-awaitable object to a coroutine if needed,
    and await it if it was not already awaited.
    Nz&cannot reuse already awaited coroutine)inspectisawaitableRuntimeErrorstr)r    resultes      Alib/python3.11/site-packages/panel/io/jupyter_server_extension.pyensure_asyncr+   D   s       3 	YYYYYYFF 	 	 	1vvAAA





		
 Js   ! 
AAAAAc                     | d                              d          }| d                             d          }d | D             }d                    d |D                       }|rd|z   }|r|dz   }|dk    rd}|S )zJoin components of url into a relative url
    Use to prevent double slash when joining subpath. This will leave the
    initial and final / in place
    r   /c                8    g | ]}|                     d           S )r-   )strip.0ss     r*   
<listcomp>z!url_path_join.<locals>.<listcomp>[   s"    ------    c              3     K   | ]}||V  	d S N r1   s     r*   	<genexpr>z url_path_join.<locals>.<genexpr>\   s'      //AQ/a//////r5   z//)
startswithendswithjoin)piecesinitialfinalstrippedr(   s        r*   url_path_joinrA   T   s    
 Qi""3''G2J$$E--f---HXX///////F%v#v|f~~vMr5   c                x    d| v r	| d         }n| d         }|j         }t          j                            |          S )Nserver_root_dircontents_manager)root_dirospath
expanduser)settingsrE   rD   s      r*   get_server_root_dirrJ   b   sF    H$$-. $$67#,7h'''r5   a  
import os
import pathlib
import sys

app = r'{{ path }}'
os.chdir(str(pathlib.Path(app).parent))
sys.path = [os.getcwd()] + sys.path[1:]

from panel.io.jupyter_executor import PanelExecutor
executor = PanelExecutor(app, '{{ token }}', '{{ root_url }}')
executor.render()
rG   r'   tokenroot_urlc                    t          j        t                    }t          j        |                    | ||                    S )a  
    Generates the code to instantiate a PanelExecutor that is to
    be be run on the kernel to start a server session.

    Arguments
    ---------
    path: str
       The path of the Panel application to execute.
    token: str
       The Bokeh JWT token containing the session_id, request arguments,
       headers and cookies.
    root_url: str
        The root_url the server is running on.

    Returns
    -------
    The code to be executed inside the kernel.
    )rG   rK   rL   )r   from_stringEXECUTION_TEMPLATEtextwrapdedentrender)rG   rK   rL   execute_templates       r*   generate_executorrT   {   sB    & '(:;;?TJJ  r5   c                  ^     e Zd ZdZ fdZefdZej        j	        dd            Z
d Z xZS )PanelJupyterHandlera  
    The PanelJupyterHandler expects to be given a path to a notebook,
    .py file or Lumen .yaml file. Based on the kernelspec in the
    notebook or the kernel query parameter it will then provision
    a Jupyter kernel to run the Panel application in.

    Once the kernel is launched it will instantiate a PanelExecutor
    inside the kernel and serve the HTML returned by it. If successful
    it will store the kernel and comm_id on `panel.state`.
    c                ~     t                      j        di | |                    dg           | _        d| _        d S )Nnotebook_pathFr8   )super
initializepoprX   kernel_started)selfkwargs	__class__s     r*   rZ   zPanelJupyterHandler.initialize   sD    $$V$$$#ZZ<<#r5   c                  K   t          j                    |z   }d\  }}}|||t          j                    |k    rt          d          	 t          | j        j                            d                      d {V }nS# t          $ rF}t          | j                                                   d {V st          d          |Y d }~d }~ww xY w|d         
                    d          |k    r|d         d         }	|	d	k    r8|d
         d         }
d|
v rt          |
d                   |
d         }|
d         }n|	dk    r&|d
         d         | j        k    r|d
         d         }nk|	dk    r9|d
         d         dk    r't                              |d
         d                    n,|	dk    r&t                              |d
         d                    ||||||fS )N)NNNzMTimed out while waiting for kernel to open Comm channel to Panel application.timeoutzEKernel died before establishing Comm connection to Panel application.parent_headermsg_idheadermsg_typeexecute_resultcontentdataz
text/errorzapplication/bokeh-extensions	text/html	comm_opentarget_namecomm_idstreamnamestderrtexterror	traceback)time	monotonicTimeoutErrorr+   kerneliopub_channelget_msgr   is_aliver&   get
session_idloggerrr   )r]   rd   rb   deadliner(   rm   r   msgr)   rf   ri   s              r*   	_get_infozPanelJupyterHandler._get_info   s/     >##g-*:'n>3I~(**"#rsss()B)J)JSW)J)X)XYYYYYYYY   )$+*>*>*@*@AAAAAAAA w&'noouvv ?#''11V;;8}Z0H+++9~f-4''&tL'9:::!%&D!Ek*[((S^M-Jdo-]-]i.3X%%#i.*@H*L*LS^F34444W$$S^K8999/ n>3I0 w..s   3B 
C<CCNc           
     
  K   t          | j        j                  }t          j        | j        p|          }|                                rt          |          }n$t          ||z                                            }| j        r|r| 	                    |           d S t          j                            |          }t          | j        d          }|                     dd           |                     dd           |                     dd           |                     dd	           | j        j                            d
          r9| j        j                            d
          d                             d          }n|                    d          ryt-          |          5 }t/          j        |          }	d d d            n# 1 swxY w Y   |	                    di                               di                               d          }nd }|rt3          | j        j                                                  }
||
vrXt:                              d|           t>                               | d|
dd| dd          }| !                    |           d S i t          j"        }tG          | j        $                    |||                     d {V }| j        %                    |          }tG          |           d {V }|&                                | _'        tG          | j'        (                                           d {V  tG          | j'        )                    d                      d {V  tU                      | _+        d | j        j        ,                                D             }|t[          | j        j.        ,                                          t[          | j        j/        ,                                          d}ta          | j+        |          }tc          |||          }| j'        2                    |          }	 | 3                    |           d {V \  }}}ti          j5        |           | j'        ||dftl          j7        | j+        <   tp          j9        j:        ;                                }|<                    tz          | j>                   | !                    |           d S # t~          t          f$ rv}| j        A                    |d           d {V  t          j         t          jD        | ddd t          |          d!"          }| !                    |           Y d }~d S d }~ww xY w)#Nzpanel-previewzContent-Typerj   zCache-Controlz#no-cache, no-store, must-revalidatePragmazno-cacheExpires0rw   r   utf-8z.ipynbmetadata
kernelspecro   z2Could not start server session, no such kernel %r.r-   zKernel errorzNo such kernel ''zPanel: Kernel not found)base_urlkernels
error_typerr   title)kernel_namerG   envra   c                .    i | ]\  }}|d  |D             S )c                8    g | ]}|                     d           S )r   )decode)r2   vs     r*   r4   z6PanelJupyterHandler.get.<locals>.<dictcomp>.<listcomp>  s$    ...a!!...r5   r8   )r2   kvss      r*   
<dictcomp>z+PanelJupyterHandler.get.<locals>.<dictcomp>  s=     
 
 
2 ..2...
 
 
r5   )	argumentsheaderscookies)extra_payloadFTnowzFailed to start kernelzPanel: Kernel Error)npm_cdnr   r   rr   	error_msgr   )ErJ   applicationrI   pathlibPathrX   is_absoluter'   absoluteredirect_to_filerF   rG   dirnamerA   r   
set_headerrequestr   r{   r[   r   r;   openjsonloadlistkernel_managerkernel_spec_managerfind_kernel_specsr}   rr   KERNEL_ERROR_TEMPLATErR   finishenvironr+   start_kernel
get_kernelclientrw   start_channelswait_for_readyr   r|   itemsdictr   r   r   rT   executer   r   updater   _kernelstornadoioloopIOLoopcurrent
call_laterCONNECTION_TIMEOUT_check_connectedrv   r&   shutdown_kernelr   r   r   )r]   rG   rE   rel_pathrX   cwdrL   requested_kernelfnbavailable_kernelshtml
kernel_env	kernel_idkernel_futurekmargspayloadrK   sourcerd   rm   ext_dirsloopr)   s                            r*   r{   zPanelJupyterHandler.get   s     &t'7'@AA< 2 :d;;!! 	BMMMMH!4 > > @ @AAM 	#'	 !!$'''Fgoom,, @@ 	444)NOOO*---	3''' <!%%h// 	$#|599(CCAFMMgVV##H-- 	$m$$ "Yq\\" " " " " " " " " " " " " " "!vvj"5599,KKOOPVWW# 	 $T%8%L%^%^%`%` a a'888QScddd,33 (^^^--@-=@@@3 4   D!!!#
^
&#00 0" 1  
 
 
 
 
 
 
 
	 +66yAA........iikk4;55778888888884;55d5CCDDDDDDDDD .//
 
/5577
 
 

 DL0668899DL0668899
 

 #4?'JJJ"=%BB$$V,,	,0NN6,B,B&B&B&B&B&B&B#D'8 !(+++/3{GYPU.VEN4?+>(0022DOO.0EFFFKK# l+ 
	 
	 
	%55iT5JJJJJJJJJ!($).a&&+  D KK
	s+   'GGGS; ;VA+U==Vc                   K   | j         t          j        vrd S t          j        | j                  \  }}}}|s$| j                            |d           d {V  d S d S )NTr   )r|   r   r   r   r   )r]   _r   	connecteds       r*   r   z$PanelJupyterHandler._check_connected&  sz      ?%.00F%*^DO%D"1i 	K%55iT5JJJJJJJJJJJ	K 	Kr5   r7   )__name__
__module____qualname____doc__rZ   KERNEL_TIMEOUTr   r   webauthenticatedr{   r   __classcell__r_   s   @r*   rV   rV      s        	 	$ $ $ $ $
 /= / / / /: [b b b bHK K K K K K Kr5   rV   c                       e Zd ZdZd fdZd Zd Zd Zd ZddZ	e
j        j        dd            Zd ZddZddZ xZS )PanelWSProxyz
    The PanelWSProxy serves as a proxy between the frontend and the
    Jupyter kernel that is running the Panel application. It send and
    receives Bokeh protocol messages via a Jupyter Comm.
    r"   Nonec                L    d |d<    t                      j        |g|R i | d S )Napplication_context)rY   __init__)r]   tornado_appr   kwr_   s       r*   r   zPanelWSProxy.__init__5  s;    $( !2t222r22222r5   c                R    d| _         t          | j        t                    | _        d S )Nr   )_ping_countr   _keep_aliver   	_ping_job)r]   r   r^   s      r*   rZ   zPanelWSProxy.initialize:  s#    )$*:<QRRr5   c                    |                      t          | j                                      d                     | xj        dz  c_        d S )Nr   r   )pingr'   r   encoder]   s    r*   r   zPanelWSProxy._keep_alive>  sG    		#d&''..w77888Ar5   c                
   K   d S r7   r8   r   s    r*   preparezPanelWSProxy.prepareB  s      r5   c                    dS )Ndefault_userr8   r   s    r*   get_current_userzPanelWSProxy.get_current_userE  s    ~r5   originr'   boolc                    dS )NTr8   )r]   r   s     r*   check_originzPanelWSProxy.check_originH  s    tr5   c                  K   | j         }| j        dk    r#|                                  t          d          |#|                                  t          d          t	          j        t          j                                        	                                          }t          |          }d|vr#|                                  t          d          ||d         k    r#|                                  t          d          	 t                      }t          |          | _        nC# t          $ r6}t                              d|           |                                  |d}~ww xY wt!          |          | _        | j        t$          j        vr|                                  t$          j        | j                 }	|	\  | _        | _        | _        }
|	dd	         d
z   t$          j        | j        <   |                    d          }|                     |           d{V  | j                                         t7          j        |                                            dS )zR Initialize a connection to a client.

        Returns:
            None

        bokehz!Subprotocol header is not 'bokeh'Nz'No token received in subprotocol headersession_expiryz$Session expiry has not been providedzToken is expired.z/Could not create new server session, reason: %sr.   )TACK)_tokenselected_subprotocolcloser
   calendartimegmdtdatetimeutcnowutctimetupler   r	   r   receiverr}   rr   r   r|   r   r   rw   rm   r   createsend_messager   startasynciocreate_task_check_for_message)r]   rG   r   r^   rK   r   r   protocolr)   kernel_infor   r   s               r*   r   zPanelWSProxy.openK  s"      $//JJLLL CDDD]JJLLL IJJJobk0022??AABB#E**7**JJLLL FGGGG,---JJLLL 3444	zzH$X..DMM 	 	 	LLJANNNJJLLLG	
 )//?%.00JJLLLnT_57B4T\4>1*5crc*:W*Dt'ooe$$$$$$$$$$$D335566666s   "D( (
E(21E##E(c                  K   	 | j         d S 	 t          | j         j                            d                      d {V }nS# t          $ rF}t          | j                                                    d {V st          d          |Y d }~d }~ww xY w|d         d         }|dk    r9|d         d         d	k    r't                              |d         d
                    |dk    r|d         d         | j	        k    s|d         |d         }}|
                    d          }|dk    r|                     |d                   S |dk    r|                     |d                   S |
                    d          }|r!|d         d                                         }n1|d         }t          |t                    rt!          j        |          }|                     |           d {V }	|	r|                     |	           d {V  )NTra   z2Kernel died before expected shutdown of Panel app.re   rf   rn   rh   ro   rp   rq   comm_msgrm   r   statusprotocol_errorri   internal_errorbinarybuffersr   )rw   r+   rx   ry   r   rz   r&   r}   rr   rm   r{   _protocol_error_internal_errortobytes
isinstancer   r   dumps_receiver  )
r]   r   r)   rf   rh   r   r  r  fragmentmessages
             r*   r  zPanelWSProxy._check_for_messagez  sQ      	1{"()B)J)JSW)J)X)XYYYYYYYY   )$+*>*>*@*@AAAAAAAA d&'[\\bcc
 8}Z0H8##Iv(>((J(JS^F3444*,,Y	1Jdl1Z1Z #IJXG\\(++F)))++GFO<<<+++++GFO<<<\\(++F 4y>!,4466"6?h-- 4#z(33H MM(33333333G 1''000000000A 	1s   3A 
B<BBr  str | bytesc                   K   t          || j        | j                  }| j        j                            d|          }| j        j                            |           d S )N)ri   rm   rl   r  )r   rm   r|   rw   sessionr   shell_channelsend)r]   r  rh   r   s       r*   
on_messagezPanelWSProxy.on_message  sW      HdlXXXk!%%j'::!&&s+++++r5   c                   t                               d| j        | j                   | j        t
          j        v rt
          j        | j        = | j                                         t          j
        | j                            d                    t          j
        | j                            | j        d                    g| _        d| _        dS )z9
        Clean up when the connection is closed.
        z/WebSocket connection closed: code=%s, reason=%rT)replyr   N)r}   info
close_codeclose_reasonr|   r   r   r   stopr	  ensure_futurerw   shutdownr   r   r   _shutdown_futuresr   s    r*   on_closezPanelWSProxy.on_close  s     	EtX\Xijjj?en,,t/!$+"6"6T"6"B"BCC!$"5"E"EdnZ^"E"_"_``"
 r5   )r"   r   )r   r'   r"   r   )r  r  r"   r   )r   r   r   r   r   rZ   r   r   r   r   r   r   r   r   r  r"  r,  r   r   s   @r*   r   r   .  s         3 3 3 3 3 3
S S S          [,7 ,7 ,7 ,7\!1 !1 !1F, , , ,
       r5   r   c                   | j         j        d         }| j                             dt          |d          t          t          t                    ft          |d          t          ft          |d          t          ft          |d          t          i ft          |d          t          t          t          	          fg
           d S )Nr   z.*$z$panel-preview/static/extensions/(.*))rootzpanel-preview/static/(.*)zpanel-preview/render/(.*)/wszpanel-preview/render/(.*)zpanel_dist/(.*))rG   )host_patternhost_handlers)web_apprI   add_handlersr   r   r   r   r   r   rV   r   r   )notebook_appr   s     r*   _load_jupyter_server_extensionr4    s    #,Z8H %%XFGG#T~%>%>%>@X;<<X>??X;<< "&X122( 3 3 35
 &     r5   )r    r!   r"   r   )rG   r'   rK   r'   rL   r'   r"   r'   )Gr   
__future__r   r	  r   r  r  r$   r   loggingrF   r   rP   rt   queuer   typingr   r   urllib.parser   r   bokeh.embed.bundler   bokeh.protocolr	   bokeh.protocol.exceptionsr
   bokeh.protocol.receiverr   bokeh.server.tornador   ,bokeh.server.views.multi_root_static_handlerr   !bokeh.server.views.static_handlerr   bokeh.server.views.wsr   bokeh.util.tokenr   r   r   r   jupyter_server.base.handlersr   tornado.ioloopr   tornado.webr   r   	resourcesr   r   r   r   	getLoggerr   r}   r   r   get_templater   r+   rA   rJ   rO   rT   rV   r   r4  load_jupyter_server_extensionr8   r5   r*   <module>rJ     s   , # " " " " "          				          ! ! ! ! ! ! ! !              - - - - - - # # # # # # 3 3 3 3 3 3 , , , , , , 6 6 6 6 6 6 O O O O O O ; ; ; ; ; ; + + + + + +            8 7 7 7 7 7 + + + + + + ) ) ) ) ) )       5 5 5 5 5 5 5 5 5 5      		8	$	$ ))*=>>       	( 	( 	(    0XK XK XK XK XK. XK XK XKv@ @ @ @ @9n @ @ @F  , !?   r5   