##// END OF EJS Templates
Merge pull request #6412 from takluyver/sessions-rest-api-fix...
Matthias Bussonnier -
r17796:6ee949eb merge
parent child Browse files
Show More
@@ -53,7 +53,7 b' class SessionManager(LoggingConfigurable):'
53 """Start a database connection"""
53 """Start a database connection"""
54 if self._connection is None:
54 if self._connection is None:
55 self._connection = sqlite3.connect(':memory:')
55 self._connection = sqlite3.connect(':memory:')
56 self._connection.row_factory = self.row_factory
56 self._connection.row_factory = sqlite3.Row
57 return self._connection
57 return self._connection
58
58
59 def __del__(self):
59 def __del__(self):
@@ -141,14 +141,20 b' class SessionManager(LoggingConfigurable):'
141 query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))
141 query = "SELECT * FROM session WHERE %s" % (' AND '.join(conditions))
142
142
143 self.cursor.execute(query, list(kwargs.values()))
143 self.cursor.execute(query, list(kwargs.values()))
144 model = self.cursor.fetchone()
144 try:
145 if model is None:
145 row = self.cursor.fetchone()
146 except KeyError:
147 # The kernel is missing, so the session just got deleted.
148 row = None
149
150 if row is None:
146 q = []
151 q = []
147 for key, value in kwargs.items():
152 for key, value in kwargs.items():
148 q.append("%s=%r" % (key, value))
153 q.append("%s=%r" % (key, value))
149
154
150 raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
155 raise web.HTTPError(404, u'Session not found: %s' % (', '.join(q)))
151 return model
156
157 return self.row_to_model(row)
152
158
153 def update_session(self, session_id, **kwargs):
159 def update_session(self, session_id, **kwargs):
154 """Updates the values in the session database.
160 """Updates the values in the session database.
@@ -179,9 +185,16 b' class SessionManager(LoggingConfigurable):'
179 query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
185 query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
180 self.cursor.execute(query, list(kwargs.values()) + [session_id])
186 self.cursor.execute(query, list(kwargs.values()) + [session_id])
181
187
182 def row_factory(self, cursor, row):
188 def row_to_model(self, row):
183 """Takes sqlite database session row and turns it into a dictionary"""
189 """Takes sqlite database session row and turns it into a dictionary"""
184 row = sqlite3.Row(cursor, row)
190 if row['kernel_id'] not in self.kernel_manager:
191 # The kernel was killed or died without deleting the session.
192 # We can't use delete_session here because that tries to find
193 # and shut down the kernel.
194 self.cursor.execute("DELETE FROM session WHERE session_id=?",
195 (row['session_id'],))
196 raise KeyError
197
185 model = {
198 model = {
186 'id': row['session_id'],
199 'id': row['session_id'],
187 'notebook': {
200 'notebook': {
@@ -196,7 +209,15 b' class SessionManager(LoggingConfigurable):'
196 """Returns a list of dictionaries containing all the information from
209 """Returns a list of dictionaries containing all the information from
197 the session database"""
210 the session database"""
198 c = self.cursor.execute("SELECT * FROM session")
211 c = self.cursor.execute("SELECT * FROM session")
199 return list(c.fetchall())
212 result = []
213 # We need to use fetchall() here, because row_to_model can delete rows,
214 # which messes up the cursor if we're iterating over rows.
215 for row in c.fetchall():
216 try:
217 result.append(self.row_to_model(row))
218 except KeyError:
219 pass
220 return result
200
221
201 def delete_session(self, session_id):
222 def delete_session(self, session_id):
202 """Deletes the row in the session database with given session_id"""
223 """Deletes the row in the session database with given session_id"""
@@ -47,6 +47,17 b' class TestSessionManager(TestCase):'
47 kernel_name='foo')['id']
47 kernel_name='foo')['id']
48 self.assertRaises(TypeError, sm.get_session, bad_id=session_id) # Bad keyword
48 self.assertRaises(TypeError, sm.get_session, bad_id=session_id) # Bad keyword
49
49
50 def test_get_session_dead_kernel(self):
51 sm = SessionManager(kernel_manager=DummyMKM())
52 session = sm.create_session(name='test1.ipynb', path='/path/to/1/', kernel_name='python')
53 # kill the kernel
54 sm.kernel_manager.shutdown_kernel(session['kernel']['id'])
55 with self.assertRaises(KeyError):
56 sm.get_session(session_id=session['id'])
57 # no sessions left
58 listed = sm.list_sessions()
59 self.assertEqual(listed, [])
60
50 def test_list_sessions(self):
61 def test_list_sessions(self):
51 sm = SessionManager(kernel_manager=DummyMKM())
62 sm = SessionManager(kernel_manager=DummyMKM())
52 sessions = [
63 sessions = [
@@ -63,6 +74,30 b' class TestSessionManager(TestCase):'
63 'path': u'/path/to/3/'}, 'kernel':{'id':u'C', 'name':'python'}}]
74 'path': u'/path/to/3/'}, 'kernel':{'id':u'C', 'name':'python'}}]
64 self.assertEqual(sessions, expected)
75 self.assertEqual(sessions, expected)
65
76
77 def test_list_sessions_dead_kernel(self):
78 sm = SessionManager(kernel_manager=DummyMKM())
79 sessions = [
80 sm.create_session(name='test1.ipynb', path='/path/to/1/', kernel_name='python'),
81 sm.create_session(name='test2.ipynb', path='/path/to/2/', kernel_name='python'),
82 ]
83 # kill one of the kernels
84 sm.kernel_manager.shutdown_kernel(sessions[0]['kernel']['id'])
85 listed = sm.list_sessions()
86 expected = [
87 {
88 'id': sessions[1]['id'],
89 'notebook': {
90 'name': u'test2.ipynb',
91 'path': u'/path/to/2/',
92 },
93 'kernel': {
94 'id': u'B',
95 'name':'python',
96 }
97 }
98 ]
99 self.assertEqual(listed, expected)
100
66 def test_update_session(self):
101 def test_update_session(self):
67 sm = SessionManager(kernel_manager=DummyMKM())
102 sm = SessionManager(kernel_manager=DummyMKM())
68 session_id = sm.create_session(name='test.ipynb', path='/path/to/',
103 session_id = sm.create_session(name='test.ipynb', path='/path/to/',
@@ -95,7 +95,7 b' def assert_http_error(status, msg=None):'
95 except requests.HTTPError as e:
95 except requests.HTTPError as e:
96 real_status = e.response.status_code
96 real_status = e.response.status_code
97 assert real_status == status, \
97 assert real_status == status, \
98 "Expected status %d, got %d" % (real_status, status)
98 "Expected status %d, got %d" % (status, real_status)
99 if msg:
99 if msg:
100 assert msg in str(e), e
100 assert msg in str(e), e
101 else:
101 else:
General Comments 0
You need to be logged in to leave comments. Login now