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 = s |
|
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_ |
|
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" % ( |
|
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