review pass on Sessions API

pull/37/head
MinRK 13 years ago
parent b1a0f2e8cc
commit 8b9bb04d12

@ -75,7 +75,7 @@ class SessionHandler(IPythonHandler):
def get(self, session_id):
# Returns the JSON model for a single session
sm = self.session_manager
model = sm.get_session(id=session_id)
model = sm.get_session(session_id=session_id)
self.finish(json.dumps(model, default=date_default))
@web.authenticated
@ -93,8 +93,9 @@ class SessionHandler(IPythonHandler):
changes['name'] = notebook['name']
if 'path' in notebook:
changes['path'] = notebook['path']
sm.update_session(session_id, **changes)
model = sm.get_session(id=session_id)
model = sm.get_session(session_id=session_id)
self.finish(json.dumps(model, default=date_default))
@web.authenticated
@ -103,8 +104,8 @@ class SessionHandler(IPythonHandler):
# Deletes the session with given session_id
sm = self.session_manager
km = self.kernel_manager
session = sm.get_session(id=session_id)
sm.delete_session(session_id)
session = sm.get_session(session_id=session_id)
sm.delete_session(session_id)
km.shutdown_kernel(session['kernel']['id'])
self.set_status(204)
self.finish()

@ -22,7 +22,6 @@ import sqlite3
from tornado import web
from IPython.config.configurable import LoggingConfigurable
from IPython.utils.traitlets import TraitError
#-----------------------------------------------------------------------------
# Classes
@ -33,6 +32,7 @@ class SessionManager(LoggingConfigurable):
# Session database initialized below
_cursor = None
_connection = None
_columns = {'session_id', 'name', 'path', 'kernel_id', 'ws_url'}
@property
def cursor(self):
@ -40,7 +40,7 @@ class SessionManager(LoggingConfigurable):
if self._cursor is None:
self._cursor = self.connection.cursor()
self._cursor.execute("""CREATE TABLE session
(id, name, path, kernel_id, ws_url)""")
(session_id, name, path, kernel_id, ws_url)""")
return self._cursor
@property
@ -48,7 +48,7 @@ class SessionManager(LoggingConfigurable):
"""Start a database connection"""
if self._connection is None:
self._connection = sqlite3.connect(':memory:')
self._connection.row_factory = sqlite3.Row
self._connection.row_factory = self.row_factory
return self._connection
def __del__(self):
@ -56,21 +56,21 @@ class SessionManager(LoggingConfigurable):
self.cursor.close()
def session_exists(self, name, path):
"""Check to see if the session for the given notebook exists"""
self.cursor.execute("SELECT * FROM session WHERE name=? AND path=?", (name,path))
"""Check to see if the session for a given notebook exists"""
self.cursor.execute("SELECT * FROM session WHERE name=? AND path=?", (name, path))
reply = self.cursor.fetchone()
if reply is None:
return False
else:
return True
def get_session_id(self):
def new_session_id(self):
"Create a uuid for a new session"
return unicode(uuid.uuid4())
def create_session(self, name=None, path=None, kernel_id=None, ws_url=None):
"""Creates a session and returns its model"""
session_id = self.get_session_id()
session_id = self.new_session_id()
return self.save_session(session_id, name=name, path=path, kernel_id=kernel_id, ws_url=ws_url)
def save_session(self, session_id, name=None, path=None, kernel_id=None, ws_url=None):
@ -98,10 +98,10 @@ class SessionManager(LoggingConfigurable):
model : dict
a dictionary of the session model
"""
self.cursor.execute("""INSERT INTO session VALUES
(?,?,?,?,?)""", (session_id, name, path, kernel_id, ws_url))
self.connection.commit()
return self.get_session(id=session_id)
self.cursor.execute("INSERT INTO session VALUES (?,?,?,?,?)",
(session_id, name, path, kernel_id, ws_url)
)
return self.get_session(session_id=session_id)
def get_session(self, **kwargs):
"""Returns the model for a particular session.
@ -121,17 +121,25 @@ class SessionManager(LoggingConfigurable):
returns a dictionary that includes all the information from the
session described by the kwarg.
"""
column = kwargs.keys()[0] # uses only the first kwarg that is entered
value = kwargs.values()[0]
try:
self.cursor.execute("SELECT * FROM session WHERE %s=?" %column, (value,))
except sqlite3.OperationalError:
raise TraitError("The session database has no column: %s" %column)
reply = self.cursor.fetchone()
if reply is not None:
model = self.reply_to_dictionary_model(reply)
else:
raise web.HTTPError(404, u'Session not found: %s=%r' % (column, value))
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))
self.cursor.execute(query, kwargs.values())
model = self.cursor.fetchone()
if model is None:
q = []
for key, value in kwargs.items():
q.append("%s=%r" % (key, value))
raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
return model
def update_session(self, session_id, **kwargs):
@ -149,34 +157,45 @@ class SessionManager(LoggingConfigurable):
and the value replaces the current value in the session
with session_id.
"""
for kwarg in kwargs:
try:
self.cursor.execute("UPDATE session SET %s=? WHERE id=?" %kwarg, (kwargs[kwarg], session_id))
self.connection.commit()
except sqlite3.OperationalError:
raise TraitError("No session exists with ID: %s" %session_id)
def reply_to_dictionary_model(self, reply):
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))
self.cursor.execute(query, kwargs.values() + [session_id])
@staticmethod
def row_factory(cursor, row):
"""Takes sqlite database session row and turns it into a dictionary"""
model = {'id': reply['id'],
'notebook': {'name': reply['name'], 'path': reply['path']},
'kernel': {'id': reply['kernel_id'], 'ws_url': reply['ws_url']}}
row = sqlite3.Row(cursor, row)
model = {
'id': row['session_id'],
'notebook': {
'name': row['name'],
'path': row['path']
},
'kernel': {
'id': row['kernel_id'],
'ws_url': row['ws_url']
}
}
return model
def list_sessions(self):
"""Returns a list of dictionaries containing all the information from
the session database"""
session_list=[]
self.cursor.execute("SELECT * FROM session")
sessions = self.cursor.fetchall()
for session in sessions:
model = self.reply_to_dictionary_model(session)
session_list.append(model)
return session_list
c = self.cursor.execute("SELECT * FROM session")
return list(c.fetchall())
def delete_session(self, session_id):
"""Deletes the row in the session database with given session_id"""
# Check that session exists before deleting
model = self.get_session(id=session_id)
self.cursor.execute("DELETE FROM session WHERE id=?", (session_id,))
self.connection.commit()
self.get_session(session_id=session_id)
self.cursor.execute("DELETE FROM session WHERE session_id=?", (session_id,))

@ -4,32 +4,30 @@ from unittest import TestCase
from tornado import web
from IPython.utils.traitlets import TraitError
from ..sessionmanager import SessionManager
class TestSessionManager(TestCase):
def test_get_session(self):
sm = SessionManager()
session_id = sm.get_session_id()
session_id = sm.new_session_id()
sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
model = sm.get_session(id=session_id)
model = sm.get_session(session_id=session_id)
expected = {'id':session_id, 'notebook':{'name':u'test.ipynb', 'path': u'/path/to/'}, 'kernel':{'id':u'5678', 'ws_url':u'ws_url'}}
self.assertEqual(model, expected)
def test_bad_get_session(self):
# Should raise error if a bad key is passed to the database.
sm = SessionManager()
session_id = sm.get_session_id()
session_id = sm.new_session_id()
sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
self.assertRaises(TraitError, sm.get_session, bad_id=session_id) # Bad keyword
self.assertRaises(TypeError, sm.get_session, bad_id=session_id) # Bad keyword
def test_list_sessions(self):
sm = SessionManager()
session_id1 = sm.get_session_id()
session_id2 = sm.get_session_id()
session_id3 = sm.get_session_id()
session_id1 = sm.new_session_id()
session_id2 = sm.new_session_id()
session_id3 = sm.new_session_id()
sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel_id='5678', ws_url='ws_url')
sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel_id='5678', ws_url='ws_url')
sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel_id='5678', ws_url='ws_url')
@ -44,26 +42,26 @@ class TestSessionManager(TestCase):
def test_update_session(self):
sm = SessionManager()
session_id = sm.get_session_id()
session_id = sm.new_session_id()
sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id=None, ws_url='ws_url')
sm.update_session(session_id, kernel_id='5678')
sm.update_session(session_id, name='new_name.ipynb')
model = sm.get_session(id=session_id)
model = sm.get_session(session_id=session_id)
expected = {'id':session_id, 'notebook':{'name':u'new_name.ipynb', 'path': u'/path/to/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}}
self.assertEqual(model, expected)
def test_bad_update_session(self):
# try to update a session with a bad keyword ~ raise error
sm = SessionManager()
session_id = sm.get_session_id()
session_id = sm.new_session_id()
sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
self.assertRaises(TraitError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword
self.assertRaises(TypeError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword
def test_delete_session(self):
sm = SessionManager()
session_id1 = sm.get_session_id()
session_id2 = sm.get_session_id()
session_id3 = sm.get_session_id()
session_id1 = sm.new_session_id()
session_id2 = sm.new_session_id()
session_id3 = sm.new_session_id()
sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel_id='5678', ws_url='ws_url')
sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel_id='5678', ws_url='ws_url')
sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel_id='5678', ws_url='ws_url')
@ -78,7 +76,8 @@ class TestSessionManager(TestCase):
def test_bad_delete_session(self):
# try to delete a session that doesn't exist ~ raise error
sm = SessionManager()
session_id = sm.get_session_id()
session_id = sm.new_session_id()
sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
self.assertRaises(web.HTTPError, sm.delete_session, session_id='23424') # Bad keyword
self.assertRaises(TypeError, sm.delete_session, bad_kwarg='23424') # Bad keyword
self.assertRaises(web.HTTPError, sm.delete_session, session_id='23424') # nonexistant

Loading…
Cancel
Save