o
    i?M                     @   s  d Z ddlZddlZddlZddlmZmZmZmZm	Z	m
Z
 edeZedeZzddlZW n ey=   ddlmZ Y nw 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 ddlmZ ddl m!Z! G dd de"Z#eG dd dZ$G dd dZ%G dd deZ&dS )zA base class session manager.    N)AnyDictListNewTypeOptionalUnion
KernelName	ModelName)dbapi2)	dataclassfields)ensure_async)web)Instance
TraitErrorUnicodevalidate)LoggingConfigurable)InstanceFromClassesc                   @   s   e Zd ZdZdS )KernelSessionRecordConflictzgException class to use when two KernelSessionRecords cannot
    merge because of conflicting data.
    N)__name__
__module____qualname____doc__ r   r   j/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/jupyter_server/services/sessions/sessionmanager.pyr      s    r   c                   @   sN   e Zd ZU dZdZee ed< dZee ed< de	de
fddZdd	d
ZdS )KernelSessionRecordzA record object for tracking a Jupyter Server Kernel Session.

    Two records that share a session_id must also share a kernel_id, while
    kernels can have multiple session (and thereby) session_ids
    associated with them.
    N
session_id	kernel_idotherreturnc                 C   s   t |tr>| jo| j|jk}t| j|jk| jdu p|jdu g}t||gr(dS t| j| j|jk| j|jkgr>d}t|dS )z Whether a record equals another.NTzA single session_id can only have one kernel_id associated with. These two KernelSessionRecords share the same session_id but have different kernel_ids. This should not be possible and is likely an issue with the session records.F)
isinstancer   r   allr   anyr   )selfr   
condition1
condition2msgr   r   r   __eq__1   s&   



zKernelSessionRecord.__eq__c                 C   sz   t |tsd}t||jr| jr|j| jkrd}t|t| D ]}t||jr:t||jr:t	| |jt||j q!dS )zCUpdates in-place a kernel from other (only accepts positive updatesz3'other' must be an instance of KernelSessionRecord.zJCould not update the record from 'other' because the two records conflict.N)
r!   r   	TypeErrorr   r   r   hasattrnamegetattrsetattr)r$   r   r'   fieldr   r   r   updateQ   s   
zKernelSessionRecord.update)r   r   r    N)r   r   r   r   r   r   str__annotations__r   objectboolr(   r/   r   r   r   r   r   %   s   
  r   c                   @   s   e Zd ZU dZee ed< defddZdd Zde	ee
f d	efd
dZdd Zde	ee
f d	efddZded	dfddZded	dfddZdS )KernelSessionRecordLista.  An object for storing and managing a list of KernelSessionRecords.

    When adding a record to the list, the KernelSessionRecordList
    first checks if the record already exists in the list. If it does,
    the record will be updated with the new information; otherwise,
    it will be appended.
    _recordsrecordsc                 G   s   g | _ |D ]}| | qdS zInitialize a record list.N)r5   r/   )r$   r6   recordr   r   r   __init__k   s   z KernelSessionRecordList.__init__c                 C   
   t | jS )z+The string representation of a record list.)r0   r5   r$   r   r   r   __str__q      
zKernelSessionRecordList.__str__r8   r    c                 C   sH   t |tr|| jv rdS t |tr"| jD ]}||j|jfv r! dS qdS )z.Search for records by kernel_id and session_idTF)r!   r   r5   r0   r   r   )r$   r8   rr   r   r   __contains__u   s   

z$KernelSessionRecordList.__contains__c                 C   r:   )zThe length of the record list.)lenr5   r;   r   r   r   __len__   r=   zKernelSessionRecordList.__len__c                 C   sl   t |tr| jD ]}||jks||jkr|  S qnt |tr-| jD ]
}||kr,|  S q"| d}t|)zsReturn a full KernelSessionRecord from a session_id, kernel_id, or
        incomplete KernelSessionRecord.
        z& not found in KernelSessionRecordList.)r!   r0   r5   r   r   r   
ValueError)r$   r8   r>   r'   r   r   r   get   s   




zKernelSessionRecordList.getNc                 C   sD   z| j |}| j | | W dS  ty!   | j | Y dS w )z9Update a record in-place or append it if not in the list.N)r5   indexr/   rB   append)r$   r8   idxr   r   r   r/      s   zKernelSessionRecordList.updatec                 C   s   || j v r| j | dS dS )zYRemove a record if its found in the list. If it's not found,
        do nothing.
        N)r5   remove)r$   r8   r   r   r   rG      s   
zKernelSessionRecordList.remove)r   r   r   r   r   r   r1   r9   r<   r   r0   r3   r?   rA   rC   r/   rG   r   r   r   r   r4   `   s   
 r4   c                       s  e Zd ZdZedddjddZeddd	 Ze	d
Z
eddgZ fddZdZdZh dZedd Zedd Zdd Zdd Zdd ZdefddZ					d9dee dee d ee d!ee d"ee deeef fd#d$Z	d:dee dee deeef fd%d&Zd'edee dee d ee d!ee defd(d)Z d;d*d+Z!d,d- Z"d.d/ Z#d"ede$fd0d1Z%d<d3d4Z&d5d6 Z'd7d8 Z(  Z)S )=SessionManagerzA session manager.:memory:zThe filesystem path to SQLite Database file (e.g. /path/to/session_database.db). By default, the session database is stored in-memory (i.e. `:memory:` setting from sqlite3) and does not persist when the current Jupyter Server shuts down.)default_valuehelpT)configdatabase_filepathc                 C   s   |d }|dkr
|S t |}| rF| rd}t|t|d}|d}W d   n1 s2w   Y  |dsF|dkrFd	}t||S )
zValidate a database file path.valuerI   zL`database_filepath` expected a file path, but the given path is a directory.rbd   Ns   SQLite format 3    z.The given file is not an SQLite database file.)pathlibPathexistsis_dirr   openread
startswith)r$   proposalrN   pathr'   fheaderr   r   r   _validate_database_filepath   s   
z*SessionManager._validate_database_filepathzBjupyter_server.services.kernels.kernelmanager.MappingKernelManagerz8jupyter_server.services.contents.manager.ContentsManagerz2notebook.services.contents.manager.ContentsManagerc                    s   t  j|i | t | _dS r7   )superr9   r4   _pending_sessions)r$   argskwargs	__class__r   r   r9      s   zSessionManager.__init__N>   r+   rZ   typer   r   c                 C   s(   | j du r| j | _ | j d | j S )z5Start a cursor and create a database called 'session'Nz\CREATE TABLE IF NOT EXISTS session
                (session_id, path, name, type, kernel_id))_cursor
connectioncursorexecuter;   r   r   r   rg      s   
zSessionManager.cursorc                 C   s,   | j du rtj| jdd| _ tj| j _| j S )zStart a database connectionN)isolation_level)_connectionsqlite3connectrM   Rowrow_factoryr;   r   r   r   rf      s   

zSessionManager.connectionc                 C   s"   | j dur| j   d| _ dS dS )zClose the sqlite connectionN)re   closer;   r   r   r   ro      s   


zSessionManager.closec                 C   s   |    dS )z+Close connection once SessionManager closesN)ro   r;   r   r   r   __del__      zSessionManager.__del__c                    sL   d}| j d|f | j  }|dur$| j|ddI dH }|dur$d}|S )z2Check to see if the session of a given name existsFz"SELECT * FROM session WHERE path=?NT)tolerate_culled)rg   rh   fetchonerow_to_model)r$   rZ   rT   rowmodelr   r   r   session_exists   s   
zSessionManager.session_existsr    c                 C   s   t t S )zCreate a uuid for a new session)r0   uuiduuid4r;   r   r   r   new_session_id  rq   zSessionManager.new_session_idrZ   r+   rd   kernel_namer   c           	         s   |   }t|d}| j| |dur|| jv rn| |||||I dH }||_| j| | j|||||dI dH }| j| |S )zCreates a session and returns its model

        Parameters
        ----------
        name: ModelName(str)
            Usually the model name, like the filename associated with current
            kernel.
        r   N)rZ   r+   rd   r   )	rz   r   r_   r/   kernel_managerstart_kernel_for_sessionr   save_sessionrG   )	r$   rZ   r+   rd   r{   r   r   r8   resultr   r   r   create_session	  s    



zSessionManager.create_sessionc                 C   sB   |dur| j |}tj||}t|tsJ i tjd|iS )a[  Return the environment variables that need to be set in the kernel

        Parameters
        ----------
        path : str
            the url path for the given session.
        name: ModelName(str), optional
            Here the name is likely to be the name of the associated file
            with the current kernel at startup time.
        NJPY_SESSION_NAME)r}   cwd_for_pathosrZ   joinr!   r0   environ)r$   rZ   r+   cwdr   r   r   get_kernel_env*  s
   zSessionManager.get_kernel_envr   c           	         sB   t | jj|dI dH }| ||}| jj|||dI dH }|S )aQ  Start a new kernel for a given session.

        Parameters
        ----------
        session_id : str
            uuid for the session; this method must be given a session_id
        path : str
            the path for the given session - seem to be a session id sometime.
        name : str
            Usually the model name, like the filename associated with current
            kernel.
        type : str
            the type of the session
        kernel_name : str
            the name of the kernel specification to use.  The default kernel name will be used if not provided.
        )rZ   N)rZ   r{   env)r   contents_managerget_kernel_pathr   r}   start_kernel)	r$   r   rZ   r+   rd   r{   kernel_path
kernel_envr   r   r   r   r~   =  s   z'SessionManager.start_kernel_for_sessionc                    s0   | j d|||||f | j|dI dH }|S )a  Saves the items for the session with the given session_id

        Given a session_id (and any other of the arguments), this method
        creates a row in the sqlite session database that holds the information
        for a session.

        Parameters
        ----------
        session_id : str
            uuid for the session; this method must be given a session_id
        path : str
            the path for the given session
        name : str
            the name of the session
        type : str
            the type of the session
        kernel_id : str
            a uuid for the kernel associated with this session

        Returns
        -------
        model : dict
            a dictionary of the session model
        z&INSERT INTO session VALUES (?,?,?,?,?)r|   N)rg   rh   get_session)r$   r   rZ   r+   rd   r   r   r   r   r   r   `  s   zSessionManager.save_sessionc              
      s"  |s	d}t |g }|D ]}|| jvrd| }t ||d|  qdd| }| j|t|  z| j }W n t	yI   d}Y nw |du rng }|
 D ]\}}	|| d|	 qTtdd	d
| z| |I dH }
W |
S  t	y } ztdd	t| |d}~ww )a:  Returns the model for a particular session.

        Takes a keyword argument and searches for the value in the session
        database, then returns the rest of the session's info.

        Parameters
        ----------
        **kwargs : dict
            must be given one of the keywords and values from the session database
            (i.e. session_id, path, name, type, kernel_id)

        Returns
        -------
        model : dict
            returns a dictionary that includes all the information from the
            session described by the kwarg.
        zmust specify a column to queryzNo such column: %s=?zSELECT * FROM session WHERE %sz AND N=i  zSession not found: %s, )r)   _columnsrE   r   rg   rh   listvaluesrs   KeyErroritemsr   	HTTPErrorrt   r0   )r$   ra   r'   
conditionscolumnqueryru   qkeyrN   rv   er   r   r   r     s:   

zSessionManager.get_sessionc                    s~   | j |dI dH  |sdS g }|D ]}|| jvrtd| |d|  qdd| }| j|g t| | dS )a  Updates the values in the session database.

        Changes the values of the session with the given session_id
        with the values from the keyword arguments.

        Parameters
        ----------
        session_id : str
            a uuid that identifies a session in the sqlite3 database
        **kwargs : str
            the key must correspond to a column title in session database,
            and the value replaces the current value in the session
            with session_id.
        r|   NzNo such column: %rr   z(UPDATE session SET %s WHERE session_id=?r   )	r   r   r)   rE   r   rg   rh   r   r   )r$   r   ra   setsr   r   r   r   r   update_session  s   
"zSessionManager.update_sessionc                    s   || j vS )zQChecks if the kernel is still considered alive and returns true if its not found.)r}   )r$   r   r   r   r   kernel_culled  s   
zSessionManager.kernel_culledFc                    s   t | |d I dH }|r5| jd|d f dj|d |d d}|r1| j| d dS t|t | j	|d I dH }|d |d |d	 |d
 |d}|d
 dkrc|d |d	 d|d< |S )z@Takes sqlite database session row and turns it into a dictionaryr   N&DELETE FROM session WHERE session_id=?r   zKernel '{kernel_id}' appears to have been culled or died unexpectedly, invalidating session '{session_id}'. The session has been removed.)r   r   z  Continuing...rZ   r+   rd   )idrZ   r+   rd   kernelnotebook)rZ   r+   )
r   r   rg   rh   formatlogwarningr   r}   kernel_model)r$   ru   rr   r   r'   r   rv   r   r   r   rt     s.   zSessionManager.row_to_modelc              	      sT   | j d}g }| D ]}z| |I dH }|| W q ty'   Y qw |S )z_Returns a list of dictionaries containing all the information from
        the session databasezSELECT * FROM sessionN)rg   rh   fetchallrt   rE   r   )r$   cr   ru   rv   r   r   r   list_sessions  s   zSessionManager.list_sessionsc                    sh   t |d}| j| | j|dI dH }t| j|d d I dH  | jd|f | j	| dS )z=Deletes the row in the session database with given session_idr|   Nr   r   r   )
r   r_   r/   r   r   r}   shutdown_kernelrg   rh   rG   )r$   r   r8   sessionr   r   r   delete_session  s   
zSessionManager.delete_session)NNNNN)N)NNNN)F)*r   r   r   r   r   tagrM   r   r]   r   r}   r   r   r9   re   rj   r   propertyrg   rf   ro   rp   rw   r0   rz   r   r	   r   r   r   r   r   r~   r   r   r   r3   r   rt   r   r   __classcell__r   r   rb   r   rH      s    






"



# 3
$rH   )'r   r   rR   rx   typingr   r   r   r   r   r   r0   r   r	   rk   ImportError	pysqlite2r
   dataclassesr   r   jupyter_core.utilsr   tornador   	traitletsr   r   r   r   traitlets.config.configurabler   jupyter_server.traittypesr   	Exceptionr   r   r4   rH   r   r   r   r   <module>   s.     

:C