Show More
@@ -36,10 +36,6 b' class SessionRootHandler(IPythonHandler):' | |||||
36 | if model is None: |
|
36 | if model is None: | |
37 | raise web.HTTPError(400, "No JSON data provided") |
|
37 | raise web.HTTPError(400, "No JSON data provided") | |
38 | try: |
|
38 | try: | |
39 | name = model['notebook']['name'] |
|
|||
40 | except KeyError: |
|
|||
41 | raise web.HTTPError(400, "Missing field in JSON data: notebook.name") |
|
|||
42 | try: |
|
|||
43 | path = model['notebook']['path'] |
|
39 | path = model['notebook']['path'] | |
44 | except KeyError: |
|
40 | except KeyError: | |
45 | raise web.HTTPError(400, "Missing field in JSON data: notebook.path") |
|
41 | raise web.HTTPError(400, "Missing field in JSON data: notebook.path") | |
@@ -50,11 +46,11 b' class SessionRootHandler(IPythonHandler):' | |||||
50 | kernel_name = None |
|
46 | kernel_name = None | |
51 |
|
47 | |||
52 | # Check to see if session exists |
|
48 | # Check to see if session exists | |
53 |
if sm.session_exists( |
|
49 | if sm.session_exists(path=path): | |
54 |
model = sm.get_session( |
|
50 | model = sm.get_session(path=path) | |
55 | else: |
|
51 | else: | |
56 | try: |
|
52 | try: | |
57 |
model = sm.create_session( |
|
53 | model = sm.create_session(path=path, kernel_name=kernel_name) | |
58 | except NoSuchKernel: |
|
54 | except NoSuchKernel: | |
59 | msg = ("The '%s' kernel is not available. Please pick another " |
|
55 | msg = ("The '%s' kernel is not available. Please pick another " | |
60 | "suitable kernel instead, or install that kernel." % kernel_name) |
|
56 | "suitable kernel instead, or install that kernel." % kernel_name) | |
@@ -92,8 +88,6 b' class SessionHandler(IPythonHandler):' | |||||
92 | changes = {} |
|
88 | changes = {} | |
93 | if 'notebook' in model: |
|
89 | if 'notebook' in model: | |
94 | notebook = model['notebook'] |
|
90 | notebook = model['notebook'] | |
95 | if 'name' in notebook: |
|
|||
96 | changes['name'] = notebook['name'] |
|
|||
97 | if 'path' in notebook: |
|
91 | if 'path' in notebook: | |
98 | changes['path'] = notebook['path'] |
|
92 | changes['path'] = notebook['path'] | |
99 |
|
93 |
@@ -21,7 +21,7 b' class SessionManager(LoggingConfigurable):' | |||||
21 | # Session database initialized below |
|
21 | # Session database initialized below | |
22 | _cursor = None |
|
22 | _cursor = None | |
23 | _connection = None |
|
23 | _connection = None | |
24 |
_columns = {'session_id', ' |
|
24 | _columns = {'session_id', 'path', 'kernel_id'} | |
25 |
|
25 | |||
26 | @property |
|
26 | @property | |
27 | def cursor(self): |
|
27 | def cursor(self): | |
@@ -29,7 +29,7 b' class SessionManager(LoggingConfigurable):' | |||||
29 | if self._cursor is None: |
|
29 | if self._cursor is None: | |
30 | self._cursor = self.connection.cursor() |
|
30 | self._cursor = self.connection.cursor() | |
31 | self._cursor.execute("""CREATE TABLE session |
|
31 | self._cursor.execute("""CREATE TABLE session | |
32 |
(session_id, |
|
32 | (session_id, path, kernel_id)""") | |
33 | return self._cursor |
|
33 | return self._cursor | |
34 |
|
34 | |||
35 | @property |
|
35 | @property | |
@@ -44,9 +44,9 b' class SessionManager(LoggingConfigurable):' | |||||
44 | """Close connection once SessionManager closes""" |
|
44 | """Close connection once SessionManager closes""" | |
45 | self.cursor.close() |
|
45 | self.cursor.close() | |
46 |
|
46 | |||
47 |
def session_exists(self, |
|
47 | def session_exists(self, path): | |
48 | """Check to see if the session for a given notebook exists""" |
|
48 | """Check to see if the session for a given notebook exists""" | |
49 |
self.cursor.execute("SELECT * FROM session WHERE |
|
49 | self.cursor.execute("SELECT * FROM session WHERE path=?", (path,)) | |
50 | reply = self.cursor.fetchone() |
|
50 | reply = self.cursor.fetchone() | |
51 | if reply is None: |
|
51 | if reply is None: | |
52 | return False |
|
52 | return False | |
@@ -57,17 +57,17 b' class SessionManager(LoggingConfigurable):' | |||||
57 | "Create a uuid for a new session" |
|
57 | "Create a uuid for a new session" | |
58 | return unicode_type(uuid.uuid4()) |
|
58 | return unicode_type(uuid.uuid4()) | |
59 |
|
59 | |||
60 |
def create_session(self |
|
60 | def create_session(self, path=None, kernel_name=None): | |
61 | """Creates a session and returns its model""" |
|
61 | """Creates a session and returns its model""" | |
62 | session_id = self.new_session_id() |
|
62 | session_id = self.new_session_id() | |
63 | # allow nbm to specify kernels cwd |
|
63 | # allow nbm to specify kernels cwd | |
64 |
kernel_path = self.contents_manager.get_kernel_path( |
|
64 | kernel_path = self.contents_manager.get_kernel_path(path=path) | |
65 | kernel_id = self.kernel_manager.start_kernel(path=kernel_path, |
|
65 | kernel_id = self.kernel_manager.start_kernel(path=kernel_path, | |
66 | kernel_name=kernel_name) |
|
66 | kernel_name=kernel_name) | |
67 |
return self.save_session(session_id, |
|
67 | return self.save_session(session_id, path=path, | |
68 | kernel_id=kernel_id) |
|
68 | kernel_id=kernel_id) | |
69 |
|
69 | |||
70 |
def save_session(self, session_id |
|
70 | def save_session(self, session_id, path=None, kernel_id=None): | |
71 | """Saves the items for the session with the given session_id |
|
71 | """Saves the items for the session with the given session_id | |
72 |
|
72 | |||
73 | Given a session_id (and any other of the arguments), this method |
|
73 | Given a session_id (and any other of the arguments), this method | |
@@ -78,10 +78,8 b' class SessionManager(LoggingConfigurable):' | |||||
78 | ---------- |
|
78 | ---------- | |
79 | session_id : str |
|
79 | session_id : str | |
80 | uuid for the session; this method must be given a session_id |
|
80 | uuid for the session; this method must be given a session_id | |
81 | name : str |
|
|||
82 | the .ipynb notebook name that started the session |
|
|||
83 | path : str |
|
81 | path : str | |
84 |
the path |
|
82 | the path for the given notebook | |
85 | kernel_id : str |
|
83 | kernel_id : str | |
86 | a uuid for the kernel associated with this session |
|
84 | a uuid for the kernel associated with this session | |
87 |
|
85 | |||
@@ -90,8 +88,8 b' class SessionManager(LoggingConfigurable):' | |||||
90 | model : dict |
|
88 | model : dict | |
91 | a dictionary of the session model |
|
89 | a dictionary of the session model | |
92 | """ |
|
90 | """ | |
93 |
self.cursor.execute("INSERT INTO session VALUES (?,?,? |
|
91 | self.cursor.execute("INSERT INTO session VALUES (?,?,?)", | |
94 |
(session_id |
|
92 | (session_id, path, kernel_id) | |
95 | ) |
|
93 | ) | |
96 | return self.get_session(session_id=session_id) |
|
94 | return self.get_session(session_id=session_id) | |
97 |
|
95 | |||
@@ -105,7 +103,7 b' class SessionManager(LoggingConfigurable):' | |||||
105 | ---------- |
|
103 | ---------- | |
106 | **kwargs : keyword argument |
|
104 | **kwargs : keyword argument | |
107 | must be given one of the keywords and values from the session database |
|
105 | must be given one of the keywords and values from the session database | |
108 |
(i.e. session_id, |
|
106 | (i.e. session_id, path, kernel_id) | |
109 |
|
107 | |||
110 | Returns |
|
108 | Returns | |
111 | ------- |
|
109 | ------- | |
@@ -182,7 +180,6 b' class SessionManager(LoggingConfigurable):' | |||||
182 | model = { |
|
180 | model = { | |
183 | 'id': row['session_id'], |
|
181 | 'id': row['session_id'], | |
184 | 'notebook': { |
|
182 | 'notebook': { | |
185 | 'name': row['name'], |
|
|||
186 | 'path': row['path'] |
|
183 | 'path': row['path'] | |
187 | }, |
|
184 | }, | |
188 | 'kernel': self.kernel_manager.kernel_model(row['kernel_id']) |
|
185 | 'kernel': self.kernel_manager.kernel_model(row['kernel_id']) |
@@ -32,24 +32,24 b' class TestSessionManager(TestCase):' | |||||
32 |
|
32 | |||
33 | def test_get_session(self): |
|
33 | def test_get_session(self): | |
34 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
34 | sm = SessionManager(kernel_manager=DummyMKM()) | |
35 |
session_id = sm.create_session( |
|
35 | session_id = sm.create_session(path='/path/to/test.ipynb', | |
36 | kernel_name='bar')['id'] |
|
36 | kernel_name='bar')['id'] | |
37 | model = sm.get_session(session_id=session_id) |
|
37 | model = sm.get_session(session_id=session_id) | |
38 | expected = {'id':session_id, |
|
38 | expected = {'id':session_id, | |
39 |
'notebook':{' |
|
39 | 'notebook':{'path': u'/path/to/test.ipynb'}, | |
40 | 'kernel': {'id':u'A', 'name': 'bar'}} |
|
40 | 'kernel': {'id':u'A', 'name': 'bar'}} | |
41 | self.assertEqual(model, expected) |
|
41 | self.assertEqual(model, expected) | |
42 |
|
42 | |||
43 | def test_bad_get_session(self): |
|
43 | def test_bad_get_session(self): | |
44 | # Should raise error if a bad key is passed to the database. |
|
44 | # Should raise error if a bad key is passed to the database. | |
45 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
45 | sm = SessionManager(kernel_manager=DummyMKM()) | |
46 |
session_id = sm.create_session( |
|
46 | session_id = sm.create_session(path='/path/to/test.ipynb', | |
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): |
|
50 | def test_get_session_dead_kernel(self): | |
51 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
51 | sm = SessionManager(kernel_manager=DummyMKM()) | |
52 |
session = sm.create_session( |
|
52 | session = sm.create_session(path='/path/to/1/test1.ipynb', kernel_name='python') | |
53 | # kill the kernel |
|
53 | # kill the kernel | |
54 | sm.kernel_manager.shutdown_kernel(session['kernel']['id']) |
|
54 | sm.kernel_manager.shutdown_kernel(session['kernel']['id']) | |
55 | with self.assertRaises(KeyError): |
|
55 | with self.assertRaises(KeyError): | |
@@ -61,24 +61,33 b' class TestSessionManager(TestCase):' | |||||
61 | def test_list_sessions(self): |
|
61 | def test_list_sessions(self): | |
62 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
62 | sm = SessionManager(kernel_manager=DummyMKM()) | |
63 | sessions = [ |
|
63 | sessions = [ | |
64 |
sm.create_session( |
|
64 | sm.create_session(path='/path/to/1/test1.ipynb', kernel_name='python'), | |
65 |
sm.create_session( |
|
65 | sm.create_session(path='/path/to/2/test2.ipynb', kernel_name='python'), | |
66 |
sm.create_session( |
|
66 | sm.create_session(path='/path/to/3/test3.ipynb', kernel_name='python'), | |
67 | ] |
|
67 | ] | |
68 | sessions = sm.list_sessions() |
|
68 | sessions = sm.list_sessions() | |
69 | expected = [{'id':sessions[0]['id'], 'notebook':{'name':u'test1.ipynb', |
|
69 | expected = [ | |
70 | 'path': u'/path/to/1/'}, 'kernel':{'id':u'A', 'name':'python'}}, |
|
70 | { | |
71 |
|
|
71 | 'id':sessions[0]['id'], | |
72 | 'path': u'/path/to/2/'}, 'kernel':{'id':u'B', 'name':'python'}}, |
|
72 | 'notebook':{'path': u'/path/to/1/test1.ipynb'}, | |
73 | {'id':sessions[2]['id'], 'notebook':{'name':u'test3.ipynb', |
|
73 | 'kernel':{'id':u'A', 'name':'python'} | |
74 | 'path': u'/path/to/3/'}, 'kernel':{'id':u'C', 'name':'python'}}] |
|
74 | }, { | |
|
75 | 'id':sessions[1]['id'], | |||
|
76 | 'notebook': {'path': u'/path/to/2/test2.ipynb'}, | |||
|
77 | 'kernel':{'id':u'B', 'name':'python'} | |||
|
78 | }, { | |||
|
79 | 'id':sessions[2]['id'], | |||
|
80 | 'notebook':{'path': u'/path/to/3/test3.ipynb'}, | |||
|
81 | 'kernel':{'id':u'C', 'name':'python'} | |||
|
82 | } | |||
|
83 | ] | |||
75 | self.assertEqual(sessions, expected) |
|
84 | self.assertEqual(sessions, expected) | |
76 |
|
85 | |||
77 | def test_list_sessions_dead_kernel(self): |
|
86 | def test_list_sessions_dead_kernel(self): | |
78 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
87 | sm = SessionManager(kernel_manager=DummyMKM()) | |
79 | sessions = [ |
|
88 | sessions = [ | |
80 |
sm.create_session( |
|
89 | sm.create_session(path='/path/to/1/test1.ipynb', kernel_name='python'), | |
81 |
sm.create_session( |
|
90 | sm.create_session(path='/path/to/2/test2.ipynb', kernel_name='python'), | |
82 | ] |
|
91 | ] | |
83 | # kill one of the kernels |
|
92 | # kill one of the kernels | |
84 | sm.kernel_manager.shutdown_kernel(sessions[0]['kernel']['id']) |
|
93 | sm.kernel_manager.shutdown_kernel(sessions[0]['kernel']['id']) | |
@@ -87,8 +96,7 b' class TestSessionManager(TestCase):' | |||||
87 | { |
|
96 | { | |
88 | 'id': sessions[1]['id'], |
|
97 | 'id': sessions[1]['id'], | |
89 | 'notebook': { |
|
98 | 'notebook': { | |
90 |
' |
|
99 | 'path': u'/path/to/2/test2.ipynb', | |
91 | 'path': u'/path/to/2/', |
|
|||
92 | }, |
|
100 | }, | |
93 | 'kernel': { |
|
101 | 'kernel': { | |
94 | 'id': u'B', |
|
102 | 'id': u'B', | |
@@ -100,41 +108,47 b' class TestSessionManager(TestCase):' | |||||
100 |
|
108 | |||
101 | def test_update_session(self): |
|
109 | def test_update_session(self): | |
102 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
110 | sm = SessionManager(kernel_manager=DummyMKM()) | |
103 |
session_id = sm.create_session( |
|
111 | session_id = sm.create_session(path='/path/to/test.ipynb', | |
104 | kernel_name='julia')['id'] |
|
112 | kernel_name='julia')['id'] | |
105 |
sm.update_session(session_id, |
|
113 | sm.update_session(session_id, path='/path/to/new_name.ipynb') | |
106 | model = sm.get_session(session_id=session_id) |
|
114 | model = sm.get_session(session_id=session_id) | |
107 | expected = {'id':session_id, |
|
115 | expected = {'id':session_id, | |
108 |
'notebook':{' |
|
116 | 'notebook':{'path': u'/path/to/new_name.ipynb'}, | |
109 | 'kernel':{'id':u'A', 'name':'julia'}} |
|
117 | 'kernel':{'id':u'A', 'name':'julia'}} | |
110 | self.assertEqual(model, expected) |
|
118 | self.assertEqual(model, expected) | |
111 |
|
119 | |||
112 | def test_bad_update_session(self): |
|
120 | def test_bad_update_session(self): | |
113 | # try to update a session with a bad keyword ~ raise error |
|
121 | # try to update a session with a bad keyword ~ raise error | |
114 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
122 | sm = SessionManager(kernel_manager=DummyMKM()) | |
115 |
session_id = sm.create_session( |
|
123 | session_id = sm.create_session(path='/path/to/test.ipynb', | |
116 | kernel_name='ir')['id'] |
|
124 | kernel_name='ir')['id'] | |
117 | self.assertRaises(TypeError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword |
|
125 | self.assertRaises(TypeError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword | |
118 |
|
126 | |||
119 | def test_delete_session(self): |
|
127 | def test_delete_session(self): | |
120 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
128 | sm = SessionManager(kernel_manager=DummyMKM()) | |
121 | sessions = [ |
|
129 | sessions = [ | |
122 |
sm.create_session( |
|
130 | sm.create_session(path='/path/to/1/test1.ipynb', kernel_name='python'), | |
123 |
sm.create_session( |
|
131 | sm.create_session(path='/path/to/2/test2.ipynb', kernel_name='python'), | |
124 |
sm.create_session( |
|
132 | sm.create_session(path='/path/to/3/test3.ipynb', kernel_name='python'), | |
125 | ] |
|
133 | ] | |
126 | sm.delete_session(sessions[1]['id']) |
|
134 | sm.delete_session(sessions[1]['id']) | |
127 | new_sessions = sm.list_sessions() |
|
135 | new_sessions = sm.list_sessions() | |
128 | expected = [{'id':sessions[0]['id'], 'notebook':{'name':u'test1.ipynb', |
|
136 | expected = [{ | |
129 | 'path': u'/path/to/1/'}, 'kernel':{'id':u'A', 'name':'python'}}, |
|
137 | 'id': sessions[0]['id'], | |
130 |
|
|
138 | 'notebook': {'path': u'/path/to/1/test1.ipynb'}, | |
131 |
|
|
139 | 'kernel': {'id':u'A', 'name':'python'} | |
|
140 | }, { | |||
|
141 | 'id': sessions[2]['id'], | |||
|
142 | 'notebook': {'path': u'/path/to/3/test3.ipynb'}, | |||
|
143 | 'kernel': {'id':u'C', 'name':'python'} | |||
|
144 | } | |||
|
145 | ] | |||
132 | self.assertEqual(new_sessions, expected) |
|
146 | self.assertEqual(new_sessions, expected) | |
133 |
|
147 | |||
134 | def test_bad_delete_session(self): |
|
148 | def test_bad_delete_session(self): | |
135 | # try to delete a session that doesn't exist ~ raise error |
|
149 | # try to delete a session that doesn't exist ~ raise error | |
136 | sm = SessionManager(kernel_manager=DummyMKM()) |
|
150 | sm = SessionManager(kernel_manager=DummyMKM()) | |
137 |
sm.create_session( |
|
151 | sm.create_session(path='/path/to/test.ipynb', kernel_name='python') | |
138 | self.assertRaises(TypeError, sm.delete_session, bad_kwarg='23424') # Bad keyword |
|
152 | self.assertRaises(TypeError, sm.delete_session, bad_kwarg='23424') # Bad keyword | |
139 | self.assertRaises(web.HTTPError, sm.delete_session, session_id='23424') # nonexistant |
|
153 | self.assertRaises(web.HTTPError, sm.delete_session, session_id='23424') # nonexistant | |
140 |
|
154 |
@@ -38,13 +38,13 b' class SessionAPI(object):' | |||||
38 | def get(self, id): |
|
38 | def get(self, id): | |
39 | return self._req('GET', id) |
|
39 | return self._req('GET', id) | |
40 |
|
40 | |||
41 |
def create(self |
|
41 | def create(self, path, kernel_name='python'): | |
42 |
body = json.dumps({'notebook': {' |
|
42 | body = json.dumps({'notebook': {'path':path}, | |
43 | 'kernel': {'name': kernel_name}}) |
|
43 | 'kernel': {'name': kernel_name}}) | |
44 | return self._req('POST', '', body) |
|
44 | return self._req('POST', '', body) | |
45 |
|
45 | |||
46 |
def modify(self, id, |
|
46 | def modify(self, id, path): | |
47 |
body = json.dumps({'notebook': {' |
|
47 | body = json.dumps({'notebook': {'path':path}}) | |
48 | return self._req('PATCH', id, body) |
|
48 | return self._req('PATCH', id, body) | |
49 |
|
49 | |||
50 | def delete(self, id): |
|
50 | def delete(self, id): | |
@@ -78,12 +78,11 b' class SessionAPITest(NotebookTestBase):' | |||||
78 | sessions = self.sess_api.list().json() |
|
78 | sessions = self.sess_api.list().json() | |
79 | self.assertEqual(len(sessions), 0) |
|
79 | self.assertEqual(len(sessions), 0) | |
80 |
|
80 | |||
81 |
resp = self.sess_api.create('nb1.ipynb |
|
81 | resp = self.sess_api.create('foo/nb1.ipynb') | |
82 | self.assertEqual(resp.status_code, 201) |
|
82 | self.assertEqual(resp.status_code, 201) | |
83 | newsession = resp.json() |
|
83 | newsession = resp.json() | |
84 | self.assertIn('id', newsession) |
|
84 | self.assertIn('id', newsession) | |
85 |
self.assertEqual(newsession['notebook'][' |
|
85 | self.assertEqual(newsession['notebook']['path'], 'foo/nb1.ipynb') | |
86 | self.assertEqual(newsession['notebook']['path'], 'foo') |
|
|||
87 | self.assertEqual(resp.headers['Location'], '/api/sessions/{0}'.format(newsession['id'])) |
|
86 | self.assertEqual(resp.headers['Location'], '/api/sessions/{0}'.format(newsession['id'])) | |
88 |
|
87 | |||
89 | sessions = self.sess_api.list().json() |
|
88 | sessions = self.sess_api.list().json() | |
@@ -95,7 +94,7 b' class SessionAPITest(NotebookTestBase):' | |||||
95 | self.assertEqual(got, newsession) |
|
94 | self.assertEqual(got, newsession) | |
96 |
|
95 | |||
97 | def test_delete(self): |
|
96 | def test_delete(self): | |
98 |
newsession = self.sess_api.create('nb1.ipynb |
|
97 | newsession = self.sess_api.create('foo/nb1.ipynb').json() | |
99 | sid = newsession['id'] |
|
98 | sid = newsession['id'] | |
100 |
|
99 | |||
101 | resp = self.sess_api.delete(sid) |
|
100 | resp = self.sess_api.delete(sid) | |
@@ -108,10 +107,9 b' class SessionAPITest(NotebookTestBase):' | |||||
108 | self.sess_api.get(sid) |
|
107 | self.sess_api.get(sid) | |
109 |
|
108 | |||
110 | def test_modify(self): |
|
109 | def test_modify(self): | |
111 |
newsession = self.sess_api.create('nb1.ipynb |
|
110 | newsession = self.sess_api.create('foo/nb1.ipynb').json() | |
112 | sid = newsession['id'] |
|
111 | sid = newsession['id'] | |
113 |
|
112 | |||
114 |
changed = self.sess_api.modify(sid, 'nb2.ipynb' |
|
113 | changed = self.sess_api.modify(sid, 'nb2.ipynb').json() | |
115 | self.assertEqual(changed['id'], sid) |
|
114 | self.assertEqual(changed['id'], sid) | |
116 |
self.assertEqual(changed['notebook'][' |
|
115 | self.assertEqual(changed['notebook']['path'], 'nb2.ipynb') | |
117 | self.assertEqual(changed['notebook']['path'], '') |
|
General Comments 0
You need to be logged in to leave comments.
Login now