##// END OF EJS Templates
changes after session manager code review
Zachary Sailer -
Show More
@@ -28,6 +28,7 b' import os'
28 import stat
28 import stat
29 import sys
29 import sys
30 import threading
30 import threading
31 import traceback
31
32
32 from tornado import web
33 from tornado import web
33 from tornado import websocket
34 from tornado import websocket
@@ -248,6 +249,17 b' class IPythonHandler(AuthenticatedHandler):'
248 use_less=self.use_less,
249 use_less=self.use_less,
249 )
250 )
250
251
252 def get_json_body(self):
253 """Return the body of the request as JSON data."""
254 if not self.request.body:
255 return None
256 # Do we need to call body.decode('utf-8') here?
257 body = self.request.body.strip().decode(u'utf-8')
258 try:
259 model = json.loads(body)
260 except:
261 raise web.HTTPError(400, u'Invalid JSON in body of request')
262 return model
251
263
252 class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler):
264 class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler):
253 """static files should only be accessible when logged in"""
265 """static files should only be accessible when logged in"""
@@ -282,7 +294,8 b' def json_errors(method):'
282 status = 400
294 status = 400
283 message = u"Unknown server error"
295 message = u"Unknown server error"
284 self.set_status(status)
296 self.set_status(status)
285 reply = dict(message=message)
297 tb_text = ''.join(traceback.format_exception(t, value, tb))
298 reply = dict(message=message, traceback=tb_text)
286 self.finish(json.dumps(reply, default=date_default))
299 self.finish(json.dumps(reply, default=date_default))
287 else:
300 else:
288 return result
301 return result
@@ -381,6 +394,12 b' class FileFindHandler(web.StaticFileHandler):'
381 if if_since >= modified:
394 if if_since >= modified:
382 self.set_status(304)
395 self.set_status(304)
383 return
396 return
397
398 if os.path.splitext(path)[1] == '.ipynb':
399 raise HTTPError(404, 'HAHA')
400 name = os.path.splitext(os.path.split(path))[0]
401 self.set_header('Content-Type', 'application/json')
402 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
384
403
385 with open(abspath, "rb") as file:
404 with open(abspath, "rb") as file:
386 data = file.read()
405 data = file.read()
@@ -16,12 +16,11 b' Authors:'
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from tornado import web
19 import json
20
21 from zmq.utils import jsonapi
22
20
21 from tornado import web
23 from IPython.utils.jsonutil import date_default
22 from IPython.utils.jsonutil import date_default
24 from ...base.handlers import IPythonHandler
23 from ...base.handlers import IPythonHandler, json_errors
25
24
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
27 # Session web service handlers
26 # Session web service handlers
@@ -31,63 +30,76 b' from ...base.handlers import IPythonHandler'
31 class SessionRootHandler(IPythonHandler):
30 class SessionRootHandler(IPythonHandler):
32
31
33 @web.authenticated
32 @web.authenticated
33 @json_errors
34 def get(self):
34 def get(self):
35 # Return a list of running sessions
35 # Return a list of running sessions
36 sm = self.session_manager
36 sm = self.session_manager
37 nbm = self.notebook_manager
38 km = self.kernel_manager
39 sessions = sm.list_sessions()
37 sessions = sm.list_sessions()
40 self.finish(jsonapi.dumps(sessions))
38 self.finish(json.dumps(sessions, default=date_default))
41
39
42 @web.authenticated
40 @web.authenticated
41 @json_errors
43 def post(self):
42 def post(self):
44 # Creates a new session
43 # Creates a new session
45 #(unless a session already exists for the named nb)
44 #(unless a session already exists for the named nb)
46 sm = self.session_manager
45 sm = self.session_manager
47 nbm = self.notebook_manager
46 nbm = self.notebook_manager
48 km = self.kernel_manager
47 km = self.kernel_manager
49 notebook_path = self.get_argument('notebook_path', default=None)
48 model = self.get_json_body()
50 name, path = nbm.named_notebook_path(notebook_path)
49 if model is None:
50 raise HTTPError(400, "No JSON data provided")
51 try:
52 name = model['notebook']['name']
53 except KeyError:
54 raise HTTPError(400, "Missing field in JSON data: name")
55 try:
56 path = model['notebook']['path']
57 except KeyError:
58 raise HTTPError(400, "Missing field in JSON data: path")
51 # Check to see if session exists
59 # Check to see if session exists
52 if sm.session_exists(name=name, path=path):
60 if sm.session_exists(name=name, path=path):
53 model = sm.get_session(name=name, path=path)
61 model = sm.get_session(name=name, path=path)
54 kernel_id = model['kernel']['id']
55 km.start_kernel(kernel_id, cwd=nbm.notebook_dir)
56 else:
62 else:
57 session_id = sm.get_session_id()
58 sm.save_session(session_id=session_id, name=name, path=path)
59 kernel_id = km.start_kernel(cwd=nbm.notebook_dir)
63 kernel_id = km.start_kernel(cwd=nbm.notebook_dir)
60 kernel = km.kernel_model(kernel_id, self.ws_url)
64 model = sm.create_session(name=name, path=path, kernel_id=kernel_id, ws_url=self.ws_url)
61 sm.update_session(session_id, kernel=kernel_id)
65 self.set_header('Location', '{0}/api/sessions/{1}'.format(self.base_project_url, model['id']))
62 model = sm.get_session(id=session_id)
66 self.finish(json.dumps(model, default=date_default))
63 self.set_header('Location', '{0}kernels/{1}'.format(self.base_kernel_url, kernel_id))
64 self.finish(jsonapi.dumps(model))
65
67
66 class SessionHandler(IPythonHandler):
68 class SessionHandler(IPythonHandler):
67
69
68 SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE')
70 SUPPORTED_METHODS = ('GET', 'PATCH', 'DELETE')
69
71
70 @web.authenticated
72 @web.authenticated
73 @json_errors
71 def get(self, session_id):
74 def get(self, session_id):
72 # Returns the JSON model for a single session
75 # Returns the JSON model for a single session
73 sm = self.session_manager
76 sm = self.session_manager
74 model = sm.get_session(id=session_id)
77 model = sm.get_session(id=session_id)
75 self.finish(jsonapi.dumps(model))
78 self.finish(json.dumps(model, default=date_default))
76
79
77 @web.authenticated
80 @web.authenticated
81 @json_errors
78 def patch(self, session_id):
82 def patch(self, session_id):
79 # Currently, this handler is strictly for renaming notebooks
83 # Currently, this handler is strictly for renaming notebooks
80 sm = self.session_manager
84 sm = self.session_manager
81 nbm = self.notebook_manager
85 nbm = self.notebook_manager
82 km = self.kernel_manager
86 km = self.kernel_manager
83 data = self.request.body
87 model = self.get_json_body()
84 data = jsonapi.loads(self.request.body)
88 if model is None:
85 name, path = nbm.named_notebook_path(data['notebook_path'])
89 raise HTTPError(400, "No JSON data provided")
86 sm.update_session(session_id, name=name)
90 changes = {}
91 if 'notebook' in model:
92 notebook = model['notebook']
93 if 'name' in notebook:
94 changes['name'] = notebook['name']
95 if 'path' in notebook:
96 changes['path'] = notebook['path']
97 sm.update_session(session_id, **changes)
87 model = sm.get_session(id=session_id)
98 model = sm.get_session(id=session_id)
88 self.finish(jsonapi.dumps(model))
99 self.finish(json.dumps(model, default=date_default))
89
100
90 @web.authenticated
101 @web.authenticated
102 @json_errors
91 def delete(self, session_id):
103 def delete(self, session_id):
92 # Deletes the session with given session_id
104 # Deletes the session with given session_id
93 sm = self.session_manager
105 sm = self.session_manager
@@ -107,9 +119,7 b' class SessionHandler(IPythonHandler):'
107 _session_id_regex = r"(?P<session_id>\w+-\w+-\w+-\w+-\w+)"
119 _session_id_regex = r"(?P<session_id>\w+-\w+-\w+-\w+-\w+)"
108
120
109 default_handlers = [
121 default_handlers = [
110 (r"api/sessions/%s/" % _session_id_regex, SessionHandler),
111 (r"api/sessions/%s" % _session_id_regex, SessionHandler),
122 (r"api/sessions/%s" % _session_id_regex, SessionHandler),
112 (r"api/sessions/", SessionRootHandler),
113 (r"api/sessions", SessionRootHandler)
123 (r"api/sessions", SessionRootHandler)
114 ]
124 ]
115
125
@@ -42,7 +42,7 b' class SessionManager(LoggingConfigurable):'
42 if self._cursor is None:
42 if self._cursor is None:
43 self._cursor = self.connection.cursor()
43 self._cursor = self.connection.cursor()
44 self._cursor.execute("""CREATE TABLE session
44 self._cursor.execute("""CREATE TABLE session
45 (id, name, path, kernel)""")
45 (id, name, path, kernel_id, ws_url)""")
46 return self._cursor
46 return self._cursor
47
47
48 @property
48 @property
@@ -70,8 +70,15 b' class SessionManager(LoggingConfigurable):'
70 "Create a uuid for a new session"
70 "Create a uuid for a new session"
71 return unicode(uuid.uuid4())
71 return unicode(uuid.uuid4())
72
72
73 def save_session(self, session_id, name=None, path=None, kernel=None):
73 def create_session(self, name=None, path=None, kernel_id=None, ws_url=None):
74 """ Given a session_id (and any other of the arguments), this method
74 """Creates a session and returns its model"""
75 session_id = self.get_session_id()
76 return self.save_session(session_id, name=name, path=path, kernel_id=kernel_id, ws_url=ws_url)
77
78 def save_session(self, session_id, name=None, path=None, kernel_id=None, ws_url=None):
79 """Saves the items for the session with the given session_id
80
81 Given a session_id (and any other of the arguments), this method
75 creates a row in the sqlite session database that holds the information
82 creates a row in the sqlite session database that holds the information
76 for a session.
83 for a session.
77
84
@@ -83,22 +90,32 b' class SessionManager(LoggingConfigurable):'
83 the .ipynb notebook name that started the session
90 the .ipynb notebook name that started the session
84 path : str
91 path : str
85 the path to the named notebook
92 the path to the named notebook
86 kernel : str
93 kernel_id : str
87 a uuid for the kernel associated with this session
94 a uuid for the kernel associated with this session
95 ws_url : str
96 the websocket url
97
98 Returns
99 -------
100 model : dict
101 a dictionary of the session model
88 """
102 """
89 self.cursor.execute("""INSERT INTO session VALUES
103 self.cursor.execute("""INSERT INTO session VALUES
90 (?,?,?,?)""", (session_id, name, path, kernel))
104 (?,?,?,?,?)""", (session_id, name, path, kernel_id, ws_url))
91 self.connection.commit()
105 self.connection.commit()
106 return self.get_session(id=session_id)
92
107
93 def get_session(self, **kwargs):
108 def get_session(self, **kwargs):
94 """ Takes a keyword argument and searches for the value in the session
109 """Returns the model for a particular session.
110
111 Takes a keyword argument and searches for the value in the session
95 database, then returns the rest of the session's info.
112 database, then returns the rest of the session's info.
96
113
97 Parameters
114 Parameters
98 ----------
115 ----------
99 **kwargs : keyword argument
116 **kwargs : keyword argument
100 must be given one of the keywords and values from the session database
117 must be given one of the keywords and values from the session database
101 (i.e. session_id, name, path, kernel)
118 (i.e. session_id, name, path, kernel_id, ws_url)
102
119
103 Returns
120 Returns
104 -------
121 -------
@@ -120,7 +137,9 b' class SessionManager(LoggingConfigurable):'
120 return model
137 return model
121
138
122 def update_session(self, session_id, **kwargs):
139 def update_session(self, session_id, **kwargs):
123 """Updates the values in the session with the given session_id
140 """Updates the values in the session database.
141
142 Changes the values of the session with the given session_id
124 with the values from the keyword arguments.
143 with the values from the keyword arguments.
125
144
126 Parameters
145 Parameters
@@ -132,20 +151,20 b' class SessionManager(LoggingConfigurable):'
132 and the value replaces the current value in the session
151 and the value replaces the current value in the session
133 with session_id.
152 with session_id.
134 """
153 """
135 column = kwargs.keys()[0] # uses only the first kwarg that is entered
154 column = kwargs.keys() # uses only the first kwarg that is entered
136 value = kwargs.values()[0]
155 value = kwargs.values()
137 try:
156 for kwarg in kwargs:
138 self.cursor.execute("UPDATE session SET %s=? WHERE id=?" %column, (value, session_id))
157 try:
139 self.connection.commit()
158 self.cursor.execute("UPDATE session SET %s=? WHERE id=?" %kwarg, (kwargs[kwarg], session_id))
140 except sqlite3.OperationalError:
159 self.connection.commit()
141 raise TraitError("No session exists with ID: %s" %session_id)
160 except sqlite3.OperationalError:
161 raise TraitError("No session exists with ID: %s" %session_id)
142
162
143 def reply_to_dictionary_model(self, reply):
163 def reply_to_dictionary_model(self, reply):
144 """Takes sqlite database session row and turns it into a dictionary"""
164 """Takes sqlite database session row and turns it into a dictionary"""
145 model = {'id': reply['id'],
165 model = {'id': reply['id'],
146 'name' : reply['name'],
166 'notebook': {'name': reply['name'], 'path': reply['path']},
147 'path' : reply['path'],
167 'kernel': {'id': reply['kernel_id'], 'ws_url': reply['ws_url']}}
148 'kernel' : {'id':reply['kernel'], 'ws_url': ''}}
149 return model
168 return model
150
169
151 def list_sessions(self):
170 def list_sessions(self):
@@ -15,16 +15,16 b' class TestSessionManager(TestCase):'
15 def test_get_session(self):
15 def test_get_session(self):
16 sm = SessionManager()
16 sm = SessionManager()
17 session_id = sm.get_session_id()
17 session_id = sm.get_session_id()
18 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel='5678')
18 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
19 model = sm.get_session(id=session_id)
19 model = sm.get_session(id=session_id)
20 expected = {'id':session_id, 'name':u'test.ipynb', 'path': u'/path/to/', 'kernel':{'id':u'5678', 'ws_url': u''}}
20 expected = {'id':session_id, 'notebook':{'name':u'test.ipynb', 'path': u'/path/to/'}, 'kernel':{'id':u'5678', 'ws_url':u'ws_url'}}
21 self.assertEqual(model, expected)
21 self.assertEqual(model, expected)
22
22
23 def test_bad_get_session(self):
23 def test_bad_get_session(self):
24 # Should raise error if a bad key is passed to the database.
24 # Should raise error if a bad key is passed to the database.
25 sm = SessionManager()
25 sm = SessionManager()
26 session_id = sm.get_session_id()
26 session_id = sm.get_session_id()
27 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel='5678')
27 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
28 self.assertRaises(TraitError, sm.get_session, bad_id=session_id) # Bad keyword
28 self.assertRaises(TraitError, sm.get_session, bad_id=session_id) # Bad keyword
29
29
30 def test_list_sessions(self):
30 def test_list_sessions(self):
@@ -32,33 +32,33 b' class TestSessionManager(TestCase):'
32 session_id1 = sm.get_session_id()
32 session_id1 = sm.get_session_id()
33 session_id2 = sm.get_session_id()
33 session_id2 = sm.get_session_id()
34 session_id3 = sm.get_session_id()
34 session_id3 = sm.get_session_id()
35 sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel='5678')
35 sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel_id='5678', ws_url='ws_url')
36 sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel='5678')
36 sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel_id='5678', ws_url='ws_url')
37 sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel='5678')
37 sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel_id='5678', ws_url='ws_url')
38 sessions = sm.list_sessions()
38 sessions = sm.list_sessions()
39 expected = [{'id':session_id1, 'name':u'test1.ipynb',
39 expected = [{'id':session_id1, 'notebook':{'name':u'test1.ipynb',
40 'path': u'/path/to/1/', 'kernel':{'id':u'5678', 'ws_url': u''}},
40 'path': u'/path/to/1/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}},
41 {'id':session_id2, 'name':u'test2.ipynb',
41 {'id':session_id2, 'notebook': {'name':u'test2.ipynb',
42 'path': u'/path/to/2/', 'kernel':{'id':u'5678', 'ws_url': u''}},
42 'path': u'/path/to/2/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}},
43 {'id':session_id3, 'name':u'test3.ipynb',
43 {'id':session_id3, 'notebook':{'name':u'test3.ipynb',
44 'path': u'/path/to/3/', 'kernel':{'id':u'5678', 'ws_url': u''}}]
44 'path': u'/path/to/3/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}}]
45 self.assertEqual(sessions, expected)
45 self.assertEqual(sessions, expected)
46
46
47 def test_update_session(self):
47 def test_update_session(self):
48 sm = SessionManager()
48 sm = SessionManager()
49 session_id = sm.get_session_id()
49 session_id = sm.get_session_id()
50 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel=None)
50 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id=None, ws_url='ws_url')
51 sm.update_session(session_id, kernel='5678')
51 sm.update_session(session_id, kernel_id='5678')
52 sm.update_session(session_id, name='new_name.ipynb')
52 sm.update_session(session_id, name='new_name.ipynb')
53 model = sm.get_session(id=session_id)
53 model = sm.get_session(id=session_id)
54 expected = {'id':session_id, 'name':u'new_name.ipynb', 'path': u'/path/to/', 'kernel':{'id':u'5678', 'ws_url': u''}}
54 expected = {'id':session_id, 'notebook':{'name':u'new_name.ipynb', 'path': u'/path/to/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}}
55 self.assertEqual(model, expected)
55 self.assertEqual(model, expected)
56
56
57 def test_bad_update_session(self):
57 def test_bad_update_session(self):
58 # try to update a session with a bad keyword ~ raise error
58 # try to update a session with a bad keyword ~ raise error
59 sm = SessionManager()
59 sm = SessionManager()
60 session_id = sm.get_session_id()
60 session_id = sm.get_session_id()
61 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel='5678')
61 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
62 self.assertRaises(TraitError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword
62 self.assertRaises(TraitError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword
63
63
64 def test_delete_session(self):
64 def test_delete_session(self):
@@ -66,21 +66,21 b' class TestSessionManager(TestCase):'
66 session_id1 = sm.get_session_id()
66 session_id1 = sm.get_session_id()
67 session_id2 = sm.get_session_id()
67 session_id2 = sm.get_session_id()
68 session_id3 = sm.get_session_id()
68 session_id3 = sm.get_session_id()
69 sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel='5678')
69 sm.save_session(session_id=session_id1, name='test1.ipynb', path='/path/to/1/', kernel_id='5678', ws_url='ws_url')
70 sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel='5678')
70 sm.save_session(session_id=session_id2, name='test2.ipynb', path='/path/to/2/', kernel_id='5678', ws_url='ws_url')
71 sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel='5678')
71 sm.save_session(session_id=session_id3, name='test3.ipynb', path='/path/to/3/', kernel_id='5678', ws_url='ws_url')
72 sm.delete_session(session_id2)
72 sm.delete_session(session_id2)
73 sessions = sm.list_sessions()
73 sessions = sm.list_sessions()
74 expected = [{'id':session_id1, 'name':u'test1.ipynb',
74 expected = [{'id':session_id1, 'notebook':{'name':u'test1.ipynb',
75 'path': u'/path/to/1/', 'kernel':{'id':u'5678', 'ws_url': u''}},
75 'path': u'/path/to/1/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}},
76 {'id':session_id3, 'name':u'test3.ipynb',
76 {'id':session_id3, 'notebook':{'name':u'test3.ipynb',
77 'path': u'/path/to/3/', 'kernel':{'id':u'5678', 'ws_url': u''}}]
77 'path': u'/path/to/3/'}, 'kernel':{'id':u'5678', 'ws_url': 'ws_url'}}]
78 self.assertEqual(sessions, expected)
78 self.assertEqual(sessions, expected)
79
79
80 def test_bad_delete_session(self):
80 def test_bad_delete_session(self):
81 # try to delete a session that doesn't exist ~ raise error
81 # try to delete a session that doesn't exist ~ raise error
82 sm = SessionManager()
82 sm = SessionManager()
83 session_id = sm.get_session_id()
83 session_id = sm.get_session_id()
84 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel='5678')
84 sm.save_session(session_id=session_id, name='test.ipynb', path='/path/to/', kernel_id='5678', ws_url='ws_url')
85 self.assertRaises(TraitError, sm.delete_session, session_id='23424') # Bad keyword
85 self.assertRaises(TraitError, sm.delete_session, session_id='23424') # Bad keyword
86
86
@@ -4,10 +4,9 b''
4 import os
4 import os
5 import sys
5 import sys
6 import json
6 import json
7 from zmq.utils import jsonapi
8
9 import requests
7 import requests
10
8
9 from IPython.utils.jsonutil import date_default
11 from IPython.html.utils import url_path_join
10 from IPython.html.utils import url_path_join
12 from IPython.html.tests.launchnotebook import NotebookTestBase
11 from IPython.html.tests.launchnotebook import NotebookTestBase
13
12
@@ -39,12 +38,12 b' class SessionAPITest(NotebookTestBase):'
39 # POST a session
38 # POST a session
40 url, nb = self.mknb()
39 url, nb = self.mknb()
41 notebook = nb.json()
40 notebook = nb.json()
42 param = {'notebook_path': notebook['path'] + notebook['name']}
41 model = {'notebook': {'name':notebook['name'], 'path': notebook['path']}}
43 r = requests.post(self.session_url(), params=param)
42 r = requests.post(self.session_url(), data=json.dumps(model, default=date_default))
44 data = r.json()
43 data = r.json()
45 assert isinstance(data, dict)
44 assert isinstance(data, dict)
46 self.assertIn('name', data)
45 self.assertIn('name', data['notebook'])
47 self.assertEqual(data['name'], notebook['name'])
46 self.assertEqual(data['notebook']['name'], notebook['name'])
48
47
49 # GET sessions
48 # GET sessions
50 r = requests.get(self.session_url())
49 r = requests.get(self.session_url())
@@ -62,8 +61,8 b' class SessionAPITest(NotebookTestBase):'
62 # Create a session
61 # Create a session
63 url, nb = self.mknb()
62 url, nb = self.mknb()
64 notebook = nb.json()
63 notebook = nb.json()
65 param = {'notebook_path': notebook['path'] + notebook['name']}
64 model = {'notebook': {'name':notebook['name'], 'path': notebook['path']}}
66 r = requests.post(self.session_url(), params=param)
65 r = requests.post(self.session_url(), data=json.dumps(model, default=date_default))
67 session = r.json()
66 session = r.json()
68
67
69 # GET a session
68 # GET a session
@@ -73,15 +72,17 b' class SessionAPITest(NotebookTestBase):'
73 self.assertEqual(r.json(), session)
72 self.assertEqual(r.json(), session)
74
73
75 # PATCH a session
74 # PATCH a session
76 data = {'notebook_path': 'test.ipynb'}
75 model = {'notebook': {'name':'test.ipynb', 'path': '/'}}
77 r = requests.patch(sess_url, data=jsonapi.dumps(data))
76 r = requests.patch(sess_url, data=json.dumps(model, default=date_default))
77
78 # Patching the notebook webservice too (just for consistency)
78 # Patching the notebook webservice too (just for consistency)
79 requests.patch(self.notebook_url() + '/Untitled0.ipynb',
79 requests.patch(self.notebook_url() + '/Untitled0.ipynb',
80 data=jsonapi.dumps({'name':'test.ipynb'}))
80 data=json.dumps({'name':'test.ipynb'}))
81 print r.json()
81 assert isinstance(r.json(), dict)
82 assert isinstance(r.json(), dict)
82 self.assertIn('name', r.json())
83 self.assertIn('name', r.json()['notebook'])
83 self.assertIn('id', r.json())
84 self.assertIn('id', r.json())
84 self.assertEqual(r.json()['name'], 'test.ipynb')
85 self.assertEqual(r.json()['notebook']['name'], 'test.ipynb')
85 self.assertEqual(r.json()['id'], session['id'])
86 self.assertEqual(r.json()['id'], session['id'])
86
87
87 # DELETE a session
88 # DELETE a session
@@ -11,33 +11,39 b''
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13
13
14 var Session = function(notebook_path, Notebook){
14 var Session = function(notebook_name, notebook_path, Notebook){
15 this.kernel = null;
15 this.kernel = null;
16 this.kernel_id = null;
16 this.kernel_id = null;
17 this.session_id = null;
17 this.session_id = null;
18 this.notebook_name = notebook_name;
18 this.notebook_path = notebook_path;
19 this.notebook_path = notebook_path;
19 this.notebook = Notebook;
20 this.notebook = Notebook;
20 this._baseProjectUrl = Notebook.baseProjectUrl()
21 this._baseProjectUrl = Notebook.baseProjectUrl()
21 };
22 };
22
23
23 Session.prototype.start = function(){
24 Session.prototype.start = function() {
24 var that = this
25 var that = this
25 var qs = $.param({notebook_path:this.notebook_path});
26 var notebook = {'notebook':{'name': this.notebook_name, 'path': this.notebook_path}}
26 var url = '/api/sessions' + '?' + qs;
27 var settings = {
27 $.post(url,
28 processData : false,
28 $.proxy(this.start_kernel, that),
29 cache : false,
29 'json'
30 type : "POST",
30 );
31 data: JSON.stringify(notebook),
32 dataType : "json",
33 };
34 var url = this._baseProjectUrl + 'api/sessions';
35 $.ajax(url, settings);
31 };
36 };
32
37
33 Session.prototype.notebook_rename = function (notebook_path) {
38 Session.prototype.notebook_rename = function (name, path) {
34 this.notebook_path = notebook_path;
39 this.notebook_name = name;
35 var name = {'notebook_path': notebook_path}
40 this.notebook_path = path;
41 var notebook = {'notebook':{'name':name, 'path': path}};
36 var settings = {
42 var settings = {
37 processData : false,
43 processData : false,
38 cache : false,
44 cache : false,
39 type : "PATCH",
45 type : "PATCH",
40 data: JSON.stringify(name),
46 data: JSON.stringify(notebook),
41 dataType : "json",
47 dataType : "json",
42 };
48 };
43 var url = this._baseProjectUrl + 'api/sessions/' + this.session_id;
49 var url = this._baseProjectUrl + 'api/sessions/' + this.session_id;
General Comments 0
You need to be logged in to leave comments. Login now