o
    ijV                     @   s<  d 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mZ dd	lmZ dd
lmZ ddlmZmZmZmZmZmZmZmZmZmZmZ ddlm Z m!Z!m"Z" ddl#m$Z$m%Z% ddl&m'Z' ddl(m)Z) zddlm*Z* W n e+y   G dd dZ*Y nw G dd deZ,G dd de,e*Z-dS )zeA MultiKernelManager for use in the notebook webserver
- raises HTTPErrors
- creates REST API models
    defaultdict)datetime	timedelta)partialN)web)Future)IOLoopPeriodicCallback)Session)MultiKernelManager)AnyBoolDictListUnicode
TraitErrorIntegerFloatInstancedefaultvalidate)maybe_future
to_os_pathexists)utcnow	isoformat)getcwd)KERNEL_CURRENTLY_RUNNING_TOTAL)AsyncMultiKernelManagerc                   @   s   e Zd ZdZdd ZdS )r   zEEmpty class to satisfy unused reference by AsyncMappingKernelManager.c                 K   s   d S N selfkwargsr!   r!   b/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/notebook/services/kernels/kernelmanager.py__init__&   s   z AsyncMultiKernelManager.__init__N)__name__
__module____qualname____doc__r&   r!   r!   r!   r%   r   $   s    r   c                   @   s  e Zd ZdZeddd Zee ZeddZ	e
 ZdZdZed	d
d Zed	dd ZeddddZdZeedddZeddddZeddddZeddddZeddddZe Zeddd ZeeddZ ee dddZ!dd  Z"d!d" Z#d#d$ Z$dCd%d&Z%d'd( Z&d)d* Z'd+d, Z(dDd-d.Z)dEd/d0Z*d1d2 Z+d3d4 Z,d5d6 Z-d7d8 Z.d9d: Z/d;d< Z0d=d> Z1d?d@ Z2dAdB Z3dS )FMappingKernelManagerzEA KernelManager that handles notebook mapping and HTTP error handlingkernel_manager_classc                 C      dS )Nz)jupyter_client.ioloop.IOLoopKernelManagerr!   r#   r!   r!   r%   _default_kernel_manager_class-      z2MappingKernelManager._default_kernel_manager_classT)configNFroot_dirc                 C   s$   z| j jW S  ty   t  Y S w r    )parentnotebook_dirAttributeErrorr   r.   r!   r!   r%   _default_root_dir;   s
   

z&MappingKernelManager._default_root_dirc                 C   sH   |d }t j|st j|}t|rt j|s"td|d|S )z'Do a bit of validation of the root dir.valuezkernel root dir z is not a directory)ospathisabsabspathr   isdirr   )r#   proposalr7   r!   r!   r%   _update_root_dirB   s   z%MappingKernelManager._update_root_dirr   zTimeout (in seconds) after which a kernel is considered idle and ready to be culled.
        Values of 0 or lower disable culling. Very short timeouts may result in kernels being culled
        for users with poor network connections.)r1   helpi,  z^The interval (in seconds) on which to check for idle kernels exceeding the cull timeout value.zxWhether to consider culling kernels which have one or more connections.
        Only effective if cull_idle_timeout > 0.zdWhether to consider culling kernels which are busy.
        Only effective if cull_idle_timeout > 0.ac  Whether messages from kernels whose frontends have disconnected should be buffered in-memory.
        When True (default), messages are buffered and replayed on reconnect,
        avoiding lost messages due to interrupted connectivity.
        Disable if long-running kernels will produce too much output while
        no frontends are connected.
        <   a  Timeout for giving up on a kernel (in seconds).
        On starting and restarting kernels, we check whether the
        kernel is running and responsive by sending kernel_info_requests.
        This sets the timeout in seconds for how long the kernel can take
        before being presumed dead.
        This affects the MappingKernelManager (which handles kernel restarts)
        and the ZMQChannelsHandler (which handles the startup).
        _kernel_buffersc                 C   s   t dd S )Nc                   S   s   g di dS )N )buffersession_keychannelsr!   r!   r!   r!   r%   <lambda>y   s    z>MappingKernelManager._default_kernel_buffers.<locals>.<lambda>r   r.   r!   r!   r%   _default_kernel_buffersw   s   z,MappingKernelManager._default_kernel_bufferszAThe last activity on any kernel, including shutting down a kernel)r?   zsWhite list of allowed kernel message types.
        When the list is empty, all message types are allowed.
        )traitr1   r?   c                 K   &   t | _| jj| fi | t | _d S r    )r   pinned_superclassr&   r   last_kernel_activityr"   r!   r!   r%   r&      s   zMappingKernelManager.__init__c                 C   s   | j d| | | dS )znotice that a kernel diedz"Kernel %s died, removing from map.N)logwarningremove_kernelr#   	kernel_idr!   r!   r%   _handle_kernel_died   s   z(MappingKernelManager._handle_kernel_diedc                 C   sH   t || j}tj|s"|| jkr"tj|}tj|s"|| jks|S )z$Turn API path into absolute OS path.)r   r2   r8   r9   r<   dirname)r#   r9   os_pathr!   r!   r%   cwd_for_path   s
   z!MappingKernelManager.cwd_for_pathc                    s    du r[|dur ||d< tjjfi |I dH  dj <   jd  dj  j	  j
d|   fddd	 tjj  j	d
  n  jd   jsp   S )ar  Start a kernel for a session and return its kernel_id.
        Parameters
        ----------
        kernel_id : uuid
            The uuid to associate the new kernel with. If this
            is not None, this kernel will be persistent whenever it is
            requested.
        path : API path
            The API path (unicode, '/' delimited) for the cwd.
            Will be transformed to an OS path relative to root_dir.
        kernel_name : str
            The name identifying which kernel spec to launch. This is ignored if
            an existing kernel is returned, but it may be checked in the future.
        Ncwdr   zKernel started: z, name: zKernel args: c                      s
     S r    )rQ   r!   rP   r#   r!   r%   rF      s   
 z3MappingKernelManager.start_kernel.<locals>.<lambda>deadtypezUsing existing kernel: )rT   r   rJ   start_kernel_kernel_connectionsstart_watching_activityrL   info_kernelskernel_namedebugadd_restart_callbackr   labelsinc_check_kernel_id_initialized_cullerinitialize_culler)r#   rP   r9   r$   r!   rV   r%   rZ      s,   

 

z!MappingKernelManager.start_kernelc                    s   j s| D ]\}}|  qdS jd|   j  | d< g  d< | d<  fdd}| D ]\}}|t	|| q@dS )a  Start buffering messages for a kernel
        Parameters
        ----------
        kernel_id : str
            The id of the kernel to start buffering.
        session_key: str
            The session_key, if any, that should get the buffer.
            If the session_key matches the current buffered session_key,
            the buffer will be returned.
        channels: dict({'channel': ZMQStream})
            The zmq channels whose messages should be buffered.
        NzStarting buffering for %srD   rC   rE   c                    s&   j d|   d | |f d S )NzBuffering msg on %s:%srC   )rL   r`   append)channel	msg_partsbuffer_inforP   r#   r!   r%   
buffer_msg   s   z8MappingKernelManager.start_buffering.<locals>.buffer_msg)
buffer_offline_messagesitemscloserL   r]   rd   stop_bufferingrA   on_recvr   )r#   rP   rD   rE   rh   streamrl   r!   rj   r%   start_buffering   s   



z$MappingKernelManager.start_bufferingc                 C   sP   | j d| || jvrdS | j| }|d |kr!| j| |S | | dS )ar  Get the buffer for a given kernel
        Parameters
        ----------
        kernel_id : str
            The id of the kernel to stop buffering.
        session_key: str, optional
            The session_key, if any, that should get the buffer.
            If the session_key matches the current buffered session_key,
            the buffer will be returned.
        zGetting buffer for %sNrD   )rL   r`   rA   poprp   )r#   rP   rD   rk   r!   r!   r%   
get_buffer   s   

zMappingKernelManager.get_bufferc                 C   s   | j d| | | || jvrdS | j|}|d  D ]}| s.|d |  q|d }|rC| j 	dt
||d  dS dS )zStop buffering kernel messages
        Parameters
        ----------
        kernel_id : str
            The id of the kernel to stop buffering.
        zClearing buffer for %sNrE   rC   z&Discarding %s buffered messages for %srD   )rL   r`   rd   rA   rt   valuesclosedrq   ro   r]   len)r#   rP   rk   rr   
msg_bufferr!   r!   r%   rp   	  s    


z#MappingKernelManager.stop_bufferingc                 C   sr   |  | | j| }|jr|j  d|_| | tj| j| jd  | j	j
| |||d | j|d dS zShutdown a kernel by kernel_idNrX   )nowrestartrd   r^   _activity_streamro   rp   r   rb   r_   decrJ   shutdown_kernelr[   rt   r#   rP   r{   r|   kernelr!   r!   r%   r   !  s   




z$MappingKernelManager.shutdown_kernelc                    s     tjj|dI dH    t  fddfdd}fdd}fd	d
d j	 d  
| t  j |S )zRestart a kernel by kernel_id)r{   Nc                      s*      s    d dS )z:Common cleanup when restart finishes/fails for any reason.rW   N)rw   ro   remove_timeoutremove_restart_callbackr!   )rh   r   loopon_restart_failedtimeoutr!   r%   finish@  s   
z3MappingKernelManager.restart_kernel.<locals>.finishc                    s.   j d     s|  d S d S )NzKernel info reply received: %s)rL   r`   done
set_result)msgr   futurerP   r#   r!   r%   on_replyG  s
   z5MappingKernelManager.restart_kernel.<locals>.on_replyc                      2   j d     std d S d S )Nz)Timeout waiting for kernel_info_reply: %szTimeout waiting for restart)rL   rM   r   set_exceptionTimeoutErrorr!   r   r!   r%   
on_timeoutM  
   z7MappingKernelManager.restart_kernel.<locals>.on_timeoutc                      r   )NzRestarting kernel failed: %szRestart failed)rL   rM   r   r   RuntimeErrorr!   r   r!   r%   r   S  r   z>MappingKernelManager.restart_kernel.<locals>.on_restart_failedrW   kernel_info_request)rd   r   rJ   restart_kernel
get_kernelconnect_shellr   ra   sessionsendrq   r	   currentadd_timeouttimekernel_info_timeout)r#   rP   r{   r   r   r!   )	rh   r   r   r   rP   r   r   r#   r   r%   r   7  s    


z#MappingKernelManager.restart_kernelc                 C   s$   || j v r| j |  d7  < dS dS )z#Notice a new connection to a kernel   Nr[   rO   r!   r!   r%   notify_connect`     
z#MappingKernelManager.notify_connectc                 C   s$   || j v r| j |  d8  < dS dS )z$Notice a disconnection from a kernelr   Nr   rO   r!   r!   r%   notify_disconnecte  r   z&MappingKernelManager.notify_disconnectc                 C   s8   |  | | j| }||jt|j|j| j| d}|S )zpReturn a JSON-safe dict representing a kernel
        For use in representing kernels in the JSON APIs.
        )idnamelast_activityexecution_stateconnections)rd   r^   r_   r   r   r   r[   )r#   rP   r   modelr!   r!   r%   kernel_modelj  s   

z!MappingKernelManager.kernel_modelc              
   C   sN   g }| j | }|D ]}z| |}|| W q
 tjtfy$   Y q
w |S )z1Returns a list of kernel_id's of kernels running.)rJ   list_kernel_idsr   rg   r   	HTTPErrorKeyError)r#   kernels
kernel_idsrP   r   r!   r!   r%   list_kernelsz  s   
z!MappingKernelManager.list_kernelsc                 C   s   || vrt dd| dS )z5Check a that a kernel_id exists and raise 404 if not.i  zKernel does not exist: N)r   r   rO   r!   r!   r%   rd     s   z%MappingKernelManager._check_kernel_idc                    sX   j   d _t  _   _t jj jj	d fdd} j
| dS )zStart watching IOPub messages on a kernel for activity.
        - update last_activity on every message
        - record execution_state from status messages
        starting)r1   keyc                    st   t   _ _| \}}|}|d d }|dkr0|d d  _jd| j dS jd| dS )	z.Record an IOPub message arriving from a kernelheadermsg_typestatuscontentr   zactivity on %s: %s (%s)zactivity on %s: %sN)r   rK   r   feed_identitiesdeserializer   rL   r`   )msg_listidentsfed_msg_listr   r   r   rP   r#   r   r!   r%   record_activity  s   
zEMappingKernelManager.start_watching_activity.<locals>.record_activityN)r^   r   r   r   connect_iopubr~   r   r   r1   r   rq   )r#   rP   r   r!   r   r%   r\     s   

z,MappingKernelManager.start_watching_activityc                 C   s   | j sO| jdkrO| jdu rOt }| jdkr$| jd| j| j | j| _t	| j
d| j | _| jd| j| j | jrA| jd | jrJ| jd | j  d| _ dS )	zStart idle culler if 'cull_idle_timeout' is greater than zero.
        Regardless of that value, set flag that we've been here.
        r   NzKInvalid value for 'cull_interval' detected (%s) - using default value (%s).i  zKCulling kernels with idle durations > %s seconds at %s second intervals ...zCulling kernels even if busyz+Culling kernels even with connected clientsT)re   cull_idle_timeout_culler_callbackr	   r   cull_intervalrL   rM   cull_interval_defaultr
   cull_kernelsr]   	cull_busycull_connectedstart)r#   r   r!   r!   r%   rf     s(   



z&MappingKernelManager.initialize_cullerc                    s|   | j d| j| j 	 t| jD ]*}z
| |I d H  W q ty; } z| j d| d|  W Y d }~qd }~ww d S )Nz9Polling every %s seconds for kernels idle > %s seconds...zSThe following exception was encountered while checking the idle duration of kernel z: )	rL   r`   r   r   listr^   cull_kernel_if_idle	Exception	exception)r#   rP   er!   r!   r%   r     s&   z!MappingKernelManager.cull_kernelsc           
         s   z| j | }W n
 ty   Y d S w t|drm| jd||j|j t }||j }|t| j	dk}| j
p:|jdk}| j|d}| jpG| }|ro|rq|rst| }	| jd|j|j|||	 t| |I d H  d S d S d S d S d S )Nr   z.kernel_id=%s, kernel_name=%s, last_activity=%s)secondsbusyr   zRCulling '%s' kernel '%s' (%s) with %d connections due to %s seconds of inactivity.)r^   r   hasattrrL   r`   r_   r   r   r   r   r   r   r[   getr   inttotal_secondsrM   r   r   )
r#   rP   r   dt_nowdt_idleis_idle_timeis_idle_executer   is_idle_connectedidle_durationr!   r!   r%   r     s0   


z(MappingKernelManager.cull_kernel_if_idle)NNFF)F)4r'   r(   r)   r*   r   r/   r   r   kernel_argvr2   r   r[   r   re   r6   r   r>   r   r   r   r   r   r   r   rm   r   r   r   rA   rG   r   r   rK   allowed_message_typesr&   rQ   rT   rZ   rs   ru   rp   r   r   r   r   r   r   rd   r\   rf   r   r   r!   r!   r!   r%   r+   *   sv    





	


	-&

)r+   c                   @   s.   e Zd Zeddd Zdd Zd
ddZd	S )AsyncMappingKernelManagerr,   c                 C   r-   )Nz.jupyter_client.ioloop.AsyncIOLoopKernelManagerr!   r.   r!   r!   r%   r/     r0   z7AsyncMappingKernelManager._default_kernel_manager_classc                 K   rI   r    )r   rJ   r&   r   rK   r"   r!   r!   r%   r&     s   z"AsyncMappingKernelManager.__init__Fc                    sz   |  | | j| }|jr|j  d|_| | tj| j| jd  | j	j
| |||dI dH  | j|d dS rz   r}   r   r!   r!   r%   r     s   




z)AsyncMappingKernelManager.shutdown_kernelNr   )r'   r(   r)   r   r/   r&   r   r!   r!   r!   r%   r     s
    
r   ).r*   collectionsr   r   r   	functoolsr   r8   tornador   tornado.concurrentr   tornado.ioloopr	   r
   jupyter_client.sessionr   !jupyter_client.multikernelmanagerr   	traitletsr   r   r   r   r   r   r   r   r   r   r   notebook.utilsr   r   r   notebook._tzr   r   ipython_genutils.py3compatr   notebook.prometheus.metricsr   r   ImportErrorr+   r   r!   r!   r!   r%   <module>   s2    4   D