Skip to content

Commit f058695

Browse files
Merge pull request #121 from dataiku/feature/dss90-jupyter-notebooks-public-api
Python wrapper for Jupyter Notebooks Public API
2 parents d3d6c3e + 745fb80 commit f058695

File tree

2 files changed

+105
-21
lines changed

2 files changed

+105
-21
lines changed

dataikuapi/dss/notebook.py

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,82 @@ class DSSNotebook(object):
44
"""
55
A Python/R/Scala notebook on the DSS instance
66
"""
7-
def __init__(self, client, project_key, notebook_name, state=None):
7+
def __init__(self, client, project_key, notebook_name, state=None, content=None):
88
self.client = client
99
self.project_key = project_key
1010
self.notebook_name = notebook_name
1111
self.state = state
12+
self.content = content
1213
self.state_is_peek = True
1314

1415
def unload(self, session_id=None):
1516
"""
16-
Stop the notebook and release its resources
17+
Stop this Jupyter notebook and release its resources
1718
"""
18-
state = self.get_state()
19-
if state is None:
19+
sessions = self.get_sessions()
20+
if sessions is None:
2021
raise Exception("Notebook isn't running")
21-
if state.get('activeSessions', None) is None:
22-
raise Exception("Notebook isn't running")
23-
if len(state['activeSessions']) == 0:
22+
if len(sessions) == 0:
2423
raise Exception("Notebook isn't running")
2524
if session_id is None:
26-
if len(state['activeSessions']) > 1:
25+
if len(sessions) > 1:
2726
raise Exception("Several sessions of the notebook are running, choose one")
2827
else:
29-
session_id = state['activeSessions'][0].get('sessionId', None)
30-
return self.client._perform_json("DELETE", "/projects/%s/notebooks/" % self.project_key, params={'notebookName' : self.notebook_name, 'sessionId' : session_id})
28+
session_id = sessions[0].get('sessionId', None)
29+
return self.client._perform_json("DELETE",
30+
"/projects/%s/jupyter-notebooks/%s/sessions/%s" % (self.project_key, self.notebook_name, session_id))
3131

32-
def get_state(self):
32+
def get_state(self, refresh=False):
3333
"""
34-
Get the status of the notebook
34+
Get the status of this Jupyter notebook
35+
36+
:param bool refresh: if True, get the status of the notebook from the backend
3537
"""
36-
if self.state is None:
37-
self.state = self.client._perform_json("GET", "/projects/%s/notebooks/" % self.project_key, params={'notebookName' : self.notebook_name})
38+
notebook_states = self.client._perform_json("GET",
39+
"/projects/%s/jupyter-notebooks/" % self.project_key,
40+
params={"active": False})
41+
if self.state is None or refresh:
42+
for notebook_state in notebook_states:
43+
if notebook_state.get("name") == self.notebook_name:
44+
self.state = notebook_state
45+
break
3846
return self.state
3947

4048
def get_sessions(self):
4149
"""
42-
Get the list of the running sessions of this notebook
50+
Get the list of running sessions of this Jupyter notebook
4351
"""
44-
state = self.get_state()
45-
if state is None:
46-
raise Exception("Notebook isn't running")
47-
if state.get('activeSessions', None) is None:
48-
raise Exception("Notebook isn't running")
49-
return state['activeSessions']
52+
53+
if self.state is None:
54+
self.state = {}
55+
sessions = self.client._perform_json("GET",
56+
"/projects/%s/jupyter-notebooks/%s/sessions" % (self.project_key, self.notebook_name))
57+
self.state["activeSessions"] = sessions
58+
return sessions
59+
60+
def get_content(self):
61+
"""
62+
Get the content of this Jupyter notebook (metadata, cells, nbformat)
63+
"""
64+
if self.content is None:
65+
self.content = self.client._perform_json("GET",
66+
"/projects/%s/jupyter-notebooks/%s" % (self.project_key, self.notebook_name))
67+
return self.content
68+
69+
def save(self):
70+
"""
71+
Save the content of this Jupyter notebook
72+
"""
73+
return self.client._perform_json("PUT",
74+
"/projects/%s/jupyter-notebooks/%s" % (self.project_key, self.notebook_name),
75+
body=self.content)
76+
77+
def delete(self):
78+
"""
79+
Delete this Jupyter notebook and stop all of its active sessions.
80+
"""
81+
return self.client._perform_json("DELETE",
82+
"/projects/%s/jupyter-notebooks/%s" % (self.project_key, self.notebook_name))
5083

5184
########################################################
5285
# Discussions

dataikuapi/dss/project.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,57 @@ def new_job_definition_builder(self, job_type='NON_RECURSIVE_FORCED_BUILD'):
825825
warnings.warn("new_job_definition_builder is deprecated, please use new_job", DeprecationWarning)
826826
return JobDefinitionBuilder(self, job_type)
827827

828+
########################################################
829+
# Jupyter Notebooks
830+
########################################################
831+
832+
def list_jupyter_notebooks(self, as_objects=True, active=False):
833+
"""
834+
List the jupyter notebooks of a project.
835+
836+
:param bool as_objects: if True, return the jupyter notebooks as a :class:`dataikuapi.dss.notebook.DSSNotebook`
837+
notebook handles instead of raw JSON
838+
:param bool active: if True, only return currently running jupyter notebooks.
839+
840+
841+
:returns: The list of the notebooks - see as_objects for more information
842+
:rtype: list
843+
"""
844+
notebooks = self.client._perform_json("GET", "/projects/%s/jupyter-notebooks/" % self.project_key,
845+
params={"active": active})
846+
if as_objects:
847+
return [DSSNotebook(self.client, notebook_state['projectKey'], notebook_state['name'], state=notebook_state) for notebook_state in notebooks]
848+
else:
849+
return notebooks
850+
851+
def get_jupyter_notebook(self, notebook_name):
852+
"""
853+
Get a handle to interact with a specific jupyter notebook
854+
855+
:param str notebook_name: The name of the jupyter notebook to retrieve
856+
:returns: A handle to interact with this jupyter notebook
857+
:rtype: :class:`~dataikuapi.dss.notebook.DSSNotebook` jupyter notebook handle
858+
"""
859+
notebook_content = self.client._perform_json("GET",
860+
"/projects/%s/jupyter-notebooks/%s" % (self.project_key, notebook_name))
861+
return DSSNotebook(self.client, self.project_key, notebook_name, content=notebook_content)
862+
863+
def create_jupyter_notebook(self, notebook_name, notebook_content):
864+
"""
865+
Create a new jupyter notebook and get a handle to interact with it
866+
867+
:param str notebook_name: the name of the notebook to create
868+
:param dict notebook_content: the data of the notebook to create, as a dict.
869+
The data will be converted to a JSON string internally.
870+
Use ``get_content()`` on a similar existing ``DSSNotebook`` object in order to get a sample definition object
871+
:returns: A handle to interact with the newly created jupyter notebook
872+
:rtype: :class:`~dataikuapi.dss.notebook.DSSNotebook` jupyter notebook handle
873+
"""
874+
created_notebook_content = self.client._perform_json("POST",
875+
"/projects/%s/jupyter-notebooks/%s" % (self.project_key, notebook_name),
876+
body=notebook_content)
877+
return DSSNotebook(self.client, self.project_key, notebook_name, content=created_notebook_content)
878+
828879
########################################################
829880
# Continuous activities
830881
########################################################

0 commit comments

Comments
 (0)