##// END OF EJS Templates
Remove version
Remove version

File last commit:

r18022:7df5d75a
r18645:26a7adc7
Show More
sessionmanager.py
211 lines | 7.6 KiB | text/x-python | PythonLexer
MinRK
allow kernel_name to be undefined in requests...
r18022 """A base class session manager."""
Zachary Sailer
manual rebase - add sessions web service
r12985
MinRK
allow kernel_name to be undefined in requests...
r18022 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
Zachary Sailer
manual rebase - add sessions web service
r12985
import uuid
Zachary Sailer
session manager restructuring...
r13035 import sqlite3
Zachary Sailer
manual rebase - add sessions web service
r12985
from tornado import web
from IPython.config.configurable import LoggingConfigurable
Thomas Kluyver
Replace references to unicode and basestring
r13353 from IPython.utils.py3compat import unicode_type
Thomas Kluyver
Add kernel name to sessions REST API...
r17222 from IPython.utils.traitlets import Instance
Zachary Sailer
manual rebase - add sessions web service
r12985
class SessionManager(LoggingConfigurable):
Thomas Kluyver
Add kernel name to sessions REST API...
r17222
kernel_manager = Instance('IPython.html.services.kernels.kernelmanager.MappingKernelManager')
MinRK
rename notebooks service to contents service...
r17524 contents_manager = Instance('IPython.html.services.contents.manager.ContentsManager', args=())
Zachary Sailer
manual rebase - add sessions web service
r12985
Zachary Sailer
session manager restructuring...
r13035 # Session database initialized below
_cursor = None
_connection = None
MinRK
remove websocket url...
r15400 _columns = {'session_id', 'name', 'path', 'kernel_id'}
Zachary Sailer
manual rebase - add sessions web service
r12985
Zachary Sailer
session manager restructuring...
r13035 @property
def cursor(self):
"""Start a cursor and create a database called 'session'"""
if self._cursor is None:
self._cursor = self.connection.cursor()
self._cursor.execute("""CREATE TABLE session
MinRK
remove websocket url...
r15400 (session_id, name, path, kernel_id)""")
Zachary Sailer
session manager restructuring...
r13035 return self._cursor
@property
def connection(self):
"""Start a database connection"""
if self._connection is None:
self._connection = sqlite3.connect(':memory:')
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 self._connection.row_factory = sqlite3.Row
Zachary Sailer
session manager restructuring...
r13035 return self._connection
def __del__(self):
"""Close connection once SessionManager closes"""
self.cursor.close()
def session_exists(self, name, path):
MinRK
review pass on Sessions API
r13101 """Check to see if the session for a given notebook exists"""
self.cursor.execute("SELECT * FROM session WHERE name=? AND path=?", (name, path))
Zachary Sailer
session manager restructuring...
r13035 reply = self.cursor.fetchone()
if reply is None:
return False
Zachary Sailer
manual rebase - add sessions web service
r12985 else:
Zachary Sailer
session manager restructuring...
r13035 return True
MinRK
review pass on Sessions API
r13101 def new_session_id(self):
Zachary Sailer
session manager restructuring...
r13035 "Create a uuid for a new session"
Thomas Kluyver
Replace references to unicode and basestring
r13353 return unicode_type(uuid.uuid4())
Zachary Sailer
session manager restructuring...
r13035
MinRK
allow kernel_name to be undefined in requests...
r18022 def create_session(self, name=None, path=None, kernel_name=None):
Zachary Sailer
changes after session manager code review
r13057 """Creates a session and returns its model"""
MinRK
review pass on Sessions API
r13101 session_id = self.new_session_id()
Thomas Kluyver
Add kernel name to sessions REST API...
r17222 # allow nbm to specify kernels cwd
MinRK
rename notebooks service to contents service...
r17524 kernel_path = self.contents_manager.get_kernel_path(name=name, path=path)
Thomas Kluyver
Add kernel name to sessions REST API...
r17222 kernel_id = self.kernel_manager.start_kernel(path=kernel_path,
kernel_name=kernel_name)
return self.save_session(session_id, name=name, path=path,
kernel_id=kernel_id)
Zachary Sailer
changes after session manager code review
r13057
MinRK
remove websocket url...
r15400 def save_session(self, session_id, name=None, path=None, kernel_id=None):
Zachary Sailer
changes after session manager code review
r13057 """Saves the items for the session with the given session_id
Given a session_id (and any other of the arguments), this method
Zachary Sailer
session manager restructuring...
r13035 creates a row in the sqlite session database that holds the information
for a session.
Zachary Sailer
manual rebase - add sessions web service
r12985
Zachary Sailer
session manager restructuring...
r13035 Parameters
----------
session_id : str
uuid for the session; this method must be given a session_id
name : str
the .ipynb notebook name that started the session
path : str
the path to the named notebook
Zachary Sailer
changes after session manager code review
r13057 kernel_id : str
Zachary Sailer
session manager restructuring...
r13035 a uuid for the kernel associated with this session
MinRK
remove websocket url...
r15400
Zachary Sailer
changes after session manager code review
r13057 Returns
-------
model : dict
a dictionary of the session model
Zachary Sailer
session manager restructuring...
r13035 """
MinRK
remove websocket url...
r15400 self.cursor.execute("INSERT INTO session VALUES (?,?,?,?)",
(session_id, name, path, kernel_id)
MinRK
review pass on Sessions API
r13101 )
return self.get_session(session_id=session_id)
Zachary Sailer
session manager restructuring...
r13035
def get_session(self, **kwargs):
Zachary Sailer
changes after session manager code review
r13057 """Returns the model for a particular session.
Takes a keyword argument and searches for the value in the session
Zachary Sailer
session manager restructuring...
r13035 database, then returns the rest of the session's info.
Parameters
----------
**kwargs : keyword argument
must be given one of the keywords and values from the session database
MinRK
remove websocket url...
r15400 (i.e. session_id, name, path, kernel_id)
Zachary Sailer
session manager restructuring...
r13035
Returns
-------
model : dict
returns a dictionary that includes all the information from the
session described by the kwarg.
"""
MinRK
review pass on Sessions API
r13101 if not kwargs:
raise TypeError("must specify a column to query")
conditions = []
for column in kwargs.keys():
if column not in self._columns:
raise TypeError("No such column: %r", column)
conditions.append("%s=?" % column)
query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))
Thomas Kluyver
Fixes for notebook session manager
r13377 self.cursor.execute(query, list(kwargs.values()))
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 try:
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 row = self.cursor.fetchone()
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 except KeyError:
# The kernel is missing, so the session just got deleted.
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 row = None
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 if row is None:
MinRK
review pass on Sessions API
r13101 q = []
for key, value in kwargs.items():
q.append("%s=%r" % (key, value))
raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775
return self.row_to_model(row)
Zachary Sailer
session manager restructuring...
r13035
def update_session(self, session_id, **kwargs):
Zachary Sailer
changes after session manager code review
r13057 """Updates the values in the session database.
Changes the values of the session with the given session_id
Zachary Sailer
session manager restructuring...
r13035 with the values from the keyword arguments.
Zachary Sailer
manual rebase - add sessions web service
r12985
Zachary Sailer
session manager restructuring...
r13035 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.
"""
MinRK
review pass on Sessions API
r13101 self.get_session(session_id=session_id)
if not kwargs:
# no changes
return
sets = []
for column in kwargs.keys():
if column not in self._columns:
raise TypeError("No such column: %r" % column)
sets.append("%s=?" % column)
query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
Thomas Kluyver
Fixes for notebook session manager
r13377 self.cursor.execute(query, list(kwargs.values()) + [session_id])
MinRK
review pass on Sessions API
r13101
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 def row_to_model(self, row):
Zachary Sailer
session manager restructuring...
r13035 """Takes sqlite database session row and turns it into a dictionary"""
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 if row['kernel_id'] not in self.kernel_manager:
Thomas Kluyver
Correct comment
r17781 # The kernel was killed or died without deleting the session.
Thomas Kluyver
Add tests and fix some issues...
r17782 # We can't use delete_session here because that tries to find
# and shut down the kernel.
self.cursor.execute("DELETE FROM session WHERE session_id=?",
(row['session_id'],))
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 raise KeyError
MinRK
review pass on Sessions API
r13101 model = {
'id': row['session_id'],
'notebook': {
'name': row['name'],
'path': row['path']
},
Thomas Kluyver
Add kernel name to sessions REST API...
r17222 'kernel': self.kernel_manager.kernel_model(row['kernel_id'])
MinRK
review pass on Sessions API
r13101 }
Zachary Sailer
session manager restructuring...
r13035 return model
MinRK
review pass on Sessions API
r13101
Zachary Sailer
session manager restructuring...
r13035 def list_sessions(self):
"""Returns a list of dictionaries containing all the information from
the session database"""
MinRK
review pass on Sessions API
r13101 c = self.cursor.execute("SELECT * FROM session")
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 result = []
Thomas Kluyver
Add tests and fix some issues...
r17782 # We need to use fetchall() here, because row_to_model can delete rows,
# which messes up the cursor if we're iterating over rows.
for row in c.fetchall():
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 try:
Thomas Kluyver
Fix 404 error when accessing nonexistant session
r17775 result.append(self.row_to_model(row))
Thomas Kluyver
Handle sessions where the kernel has been killed
r17773 except KeyError:
pass
return result
Zachary Sailer
session manager restructuring...
r13035
def delete_session(self, session_id):
"""Deletes the row in the session database with given session_id"""
# Check that session exists before deleting
Thomas Kluyver
Add kernel name to sessions REST API...
r17222 session = self.get_session(session_id=session_id)
self.kernel_manager.shutdown_kernel(session['kernel']['id'])
MinRK
review pass on Sessions API
r13101 self.cursor.execute("DELETE FROM session WHERE session_id=?", (session_id,))