diff --git a/notebook/services/sessions/handlers.py b/notebook/services/sessions/handlers.py index 987255d9c0..79c274c57a 100644 --- a/notebook/services/sessions/handlers.py +++ b/notebook/services/sessions/handlers.py @@ -42,10 +42,13 @@ def post(self): path = model['notebook']['path'] except KeyError: raise web.HTTPError(400, "Missing field in JSON data: notebook.path") - try: - kernel_name = model['kernel']['name'] - except KeyError: - self.log.debug("No kernel name specified, using default kernel") + + kernel = model.get('kernel', {}) + kernel_name = kernel.get('name') or None + kernel_id = kernel.get('id') or None + + if not kernel_id and not kernel_name: + self.log.debug("No kernel specified, using default kernel") kernel_name = None # Check to see if session exists @@ -55,7 +58,8 @@ def post(self): else: try: model = yield gen.maybe_future( - sm.create_session(path=path, kernel_name=kernel_name)) + sm.create_session(path=path, kernel_name=kernel_name, + kernel_id=kernel_id)) except NoSuchKernel: msg = ("The '%s' kernel is not available. Please pick another " "suitable kernel instead, or install that kernel." % kernel_name) diff --git a/notebook/services/sessions/sessionmanager.py b/notebook/services/sessions/sessionmanager.py index 11c810f3d0..8f5a6845c1 100644 --- a/notebook/services/sessions/sessionmanager.py +++ b/notebook/services/sessions/sessionmanager.py @@ -64,10 +64,14 @@ def new_session_id(self): return unicode_type(uuid.uuid4()) @gen.coroutine - def create_session(self, path=None, kernel_name=None): + def create_session(self, path=None, kernel_name=None, kernel_id=None): """Creates a session and returns its model""" session_id = self.new_session_id() - kernel_id = yield self.start_kernel_for_session(session_id, path, kernel_name) + if kernel_id is not None and kernel_id in self.kernel_manager: + pass + else: + kernel_id = yield self.start_kernel_for_session(session_id, path, + kernel_name) result = yield gen.maybe_future( self.save_session(session_id, path=path, kernel_id=kernel_id) ) diff --git a/notebook/services/sessions/tests/test_sessions_api.py b/notebook/services/sessions/tests/test_sessions_api.py index e824522810..ef3f4c4489 100644 --- a/notebook/services/sessions/tests/test_sessions_api.py +++ b/notebook/services/sessions/tests/test_sessions_api.py @@ -39,9 +39,10 @@ def list(self): def get(self, id): return self._req('GET', id) - def create(self, path, kernel_name='python'): + def create(self, path, kernel_name='python', kernel_id=None): body = json.dumps({'notebook': {'path':path}, - 'kernel': {'name': kernel_name}}) + 'kernel': {'name': kernel_name, + 'id': kernel_id}}) return self._req('POST', '', body) def modify_path(self, id, path): @@ -110,6 +111,28 @@ def test_create(self): got = self.sess_api.get(sid).json() self.assertEqual(got, newsession) + def test_create_with_kernel_id(self): + # create a new kernel + r = requests.post(url_path_join(self.base_url(), 'api/kernels')) + r.raise_for_status() + kernel = r.json() + + resp = self.sess_api.create('foo/nb1.ipynb', kernel_id=kernel['id']) + self.assertEqual(resp.status_code, 201) + newsession = resp.json() + self.assertIn('id', newsession) + self.assertEqual(newsession['notebook']['path'], 'foo/nb1.ipynb') + self.assertEqual(newsession['kernel']['id'], kernel['id']) + self.assertEqual(resp.headers['Location'], self.url_prefix + 'api/sessions/{0}'.format(newsession['id'])) + + sessions = self.sess_api.list().json() + self.assertEqual(sessions, [newsession]) + + # Retrieve it + sid = newsession['id'] + got = self.sess_api.get(sid).json() + self.assertEqual(got, newsession) + def test_delete(self): newsession = self.sess_api.create('foo/nb1.ipynb').json() sid = newsession['id']