o
    ^iN                     @   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	 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NewTypeOptionalUnioncast
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/home/ubuntu/hpml_nyu/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__/   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   updateO   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)r4   r.   )r#   r5   recordr   r   r   __init__i   s   z KernelSessionRecordList.__init__c                 C   
   t | jS )z+The string representation of a record list.)r/   r4   r#   r   r   r   __str__o      
zKernelSessionRecordList.__str__r7   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   r4   r/   r   r   )r#   r7   rr   r   r   __contains__s   s   

z$KernelSessionRecordList.__contains__c                 C   r9   )zThe length of the record list.)lenr4   r:   r   r   r   __len__~   r<   zKernelSessionRecordList.__len__c                 C   sh   t |tr| jD ]}||j|jfv 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    r/   r4   r   r   r   
ValueError)r#   r7   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)r4   indexr.   rA   append)r#   r7   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)r4   remove)r#   r7   r   r   r   rF      s   
zKernelSessionRecordList.remove)r   r   r   r   listr   r0   r8   r;   r   r/   r2   r>   r@   rB   r.   rF   r   r   r   r   r3   ^   s   
 r3   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 r6   )superr8   r3   _pending_sessions)r#   argskwargs	__class__r   r   r8      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)r/   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| t	t
ttf |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_sessionrF   r   dictr/   r   )	r#   rZ   r*   rd   r{   r   r   r7   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    r/   environ)r#   rZ   r*   cwdr   r   r   get_kernel_env(  s
   zSessionManager.get_kernel_envr   c           	         sH   t | jj|dI dH }| ||}| jj|||dI dH }tt|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_kernelr   r/   )	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(   _columnsrD   r   rg   rh   rG   valuesrs   KeyErroritemsr   	HTTPErrorrt   r/   )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| | t	| j
dra| jd|g | j \}}}| j
j|| ||d	 dS 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   
update_envz<SELECT path, name, kernel_id FROM session WHERE session_id=?)r   r   )r   r   r(   rD   r   rg   rh   rG   r   r)   r}   rs   r   r   )	r#   r   ra   setsr   r   rZ   r*   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   rD   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   rF   )r#   r   r7   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   r8   re   rj   r   propertyrg   rf   ro   rp   rw   r/   rz   r   r   r   r   r   r   r   r~   r   r   r   r2   r   rt   r   r   __classcell__r   r   rb   r   rH      s    

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

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

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