Skip to content

Commit 2ee3d75

Browse files
authored
Merge pull request #22 from dataiku/feature/collaboration
public api for collaboration features
2 parents cc60cb2 + 76b6733 commit 2ee3d75

File tree

10 files changed

+609
-0
lines changed

10 files changed

+609
-0
lines changed

dataikuapi/dss/dataset.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ..utils import DataikuStreamedHttpUTF8CSVReader
44
import json
55
from .metrics import ComputedMetrics
6+
from .discussion import DSSObjectDiscussions
67

78
class DSSDataset(object):
89
"""
@@ -234,3 +235,15 @@ def get_usages(self):
234235
a list of usages
235236
"""
236237
return self.client._perform_json("GET", "/projects/%s/datasets/%s/usages" % (self.project_key, self.dataset_name))
238+
239+
########################################################
240+
# Discussions
241+
########################################################
242+
def get_object_discussions(self):
243+
"""
244+
Get a handle to manage discussions on the dataset
245+
246+
:returns: the handle to manage discussions
247+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
248+
"""
249+
return DSSObjectDiscussions(self.client, self.project_key, "DATASET", self.dataset_name)

dataikuapi/dss/discussion.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import json
2+
import sys
3+
4+
if sys.version_info >= (3,0):
5+
import urllib.parse
6+
dku_quote_fn = urllib.parse.quote
7+
else:
8+
import urllib
9+
dku_quote_fn = urllib.quote
10+
11+
class DSSObjectDiscussions(object):
12+
"""
13+
A handle to manage discussions on a DSS object
14+
"""
15+
def __init__(self, client, project_key, object_type, object_id):
16+
"""Do not call directly, use :meth:`dataikuapi.dssclient.DSSClient.get_object_discussions` or on any commentable DSS object"""
17+
self.client = client
18+
self.project_key = project_key
19+
self.object_type = object_type
20+
self.object_id = object_id
21+
# encode in UTF-8 if its python2 and unicode
22+
if sys.version_info < (3,0) and isinstance(self.object_id, unicode):
23+
self.object_id = self.object_id.encode('utf-8')
24+
25+
def list_discussions(self):
26+
"""
27+
Get the list of discussions on the object
28+
29+
:returns: list of discussions on the object
30+
:rtype: list of :class:`dataikuapi.dss.discussion.DSSDiscussion`
31+
"""
32+
data = self.client._perform_json("GET", "/projects/%s/discussions/%s/%s/" % (self.project_key, self.object_type, self.object_id))
33+
return [DSSDiscussion(self.client, self.project_key, self.object_type, self.object_id, discu_data['id'], discu_data, False) for discu_data in data]
34+
35+
def create_discussion(self, topic, message):
36+
"""
37+
Create a new discussion
38+
39+
:param str topic: the discussion topic
40+
:param str message: the markdown formatted first message
41+
:returns: the newly created discussion
42+
:rtype: :class:`dataikuapi.dss.discussion.DSSDiscussion`
43+
"""
44+
creation_data = {
45+
"topic" : topic,
46+
"reply" : message
47+
}
48+
discu_data = self.client._perform_json("POST", "/projects/%s/discussions/%s/%s/" % (self.project_key, self.object_type, self.object_id), body=creation_data)
49+
return DSSDiscussion(self.client, self.project_key, self.object_type, self.object_id, discu_data['id'], discu_data, True)
50+
51+
def get_discussion(self, discussion_id):
52+
"""
53+
Get a specific discussion
54+
55+
:param str discussion_id: the discussion ID
56+
:returns: the discussion
57+
:rtype: :class:`dataikuapi.dss.discussion.DSSDiscussion`
58+
"""
59+
discu_data = self.client._perform_json("GET", "/projects/%s/discussions/%s/%s/%s" % (self.project_key, self.object_type, self.object_id, discussion_id))
60+
return DSSDiscussion(self.client, self.project_key, self.object_type, self.object_id, discussion_id, discu_data, True)
61+
62+
class DSSDiscussion(object):
63+
"""Do not call directly, use :meth:`dataikuapi.dss.discussion.DSSObjectDiscussions.get_discussion`"""
64+
def __init__(self, client, project_key, object_type, object_id, discussion_id, discussion_data, discussion_data_has_replies):
65+
"""
66+
:param DSSClient client: an api client to connect to the DSS backend
67+
:param str project_key: identifier of the project to access
68+
:param str object_type: DSS object type
69+
:param str object_id: DSS object ID
70+
:param str discussion_id: identified of the discussion
71+
:param dict discussion_data: the discussion data
72+
:param bool discussion_data_has_replies: a flag that indicates if the replies has been loaded
73+
"""
74+
self.client = client
75+
self.project_key = project_key
76+
self.object_type = object_type
77+
self.object_id = object_id
78+
self.discussion_id = discussion_id
79+
self.discussion_data = discussion_data
80+
self.discussion_data_has_replies = discussion_data_has_replies
81+
82+
def _get_with_replies(self):
83+
"""
84+
Reload the discussion data from the backend including the replies
85+
"""
86+
self.discussion_data = self.client._perform_json("GET", "/projects/%s/discussions/%s/%s/%s" % (self.project_key, self.object_type, self.object_id, self.discussion_id))
87+
self.discussion_data_has_replies = True
88+
89+
def get_metadata(self):
90+
"""
91+
Get the discussion metadata
92+
93+
:returns: the discussion metadata
94+
:rtype: dict
95+
"""
96+
metadata = dict(self.discussion_data)
97+
if "replies" in metadata:
98+
del metadata["replies"]
99+
return metadata
100+
101+
def set_metadata(self, discussion_metadata):
102+
"""
103+
Update the discussion metadata
104+
105+
:param dict discussion_metadata: the discussion metadata
106+
"""
107+
if not self.discussion_data_has_replies:
108+
self._get_with_replies()
109+
110+
edited_metadata = dict(discussion_metadata)
111+
edited_metadata["replies"] = self.discussion_data["replies"]
112+
113+
self.discussion_data = self.client._perform_json("PUT", "/projects/%s/discussions/%s/%s/%s" % (self.project_key, self.object_type, self.object_id, self.discussion_id), body=edited_metadata)
114+
self.discussion_data_has_replies = True
115+
116+
def get_replies(self):
117+
"""
118+
Get the list of replies in this discussion
119+
120+
:returns: a list of replies
121+
:rtype: list of :class:`dataikuapi.dss.discussion.DSSDiscussionReply`
122+
"""
123+
if not self.discussion_data_has_replies:
124+
self._get_with_replies()
125+
126+
return [DSSDiscussionReply(reply_data) for reply_data in self.discussion_data["replies"]]
127+
128+
def add_reply(self, text):
129+
"""
130+
Add a reply to a discussion
131+
132+
:param str text: the markdown formatted text to reply
133+
"""
134+
reply_data = {
135+
"reply": text
136+
}
137+
self.discussion_data = self.client._perform_json("POST", "/projects/%s/discussions/%s/%s/%s/replies/" % (self.project_key, self.object_type, self.object_id, self.discussion_id), body=reply_data)
138+
self.discussion_data_has_replies = True
139+
140+
class DSSDiscussionReply(object):
141+
"""
142+
A read-only handle to access a discussion reply
143+
"""
144+
def __init__(self, reply_data):
145+
"""Do not call directly, use :meth:`dataikuapi.dss.discussion.DSSDiscussion.get_replies`"""
146+
self.reply_data = reply_data
147+
148+
def get_raw_data(self):
149+
"""
150+
Get the reply raw data
151+
152+
:returns: the reply data
153+
:rtype: dict
154+
"""
155+
return self.reply_data
156+
157+
def get_text(self):
158+
"""
159+
Get the reply text
160+
161+
:returns: the reply text
162+
:rtype: str
163+
"""
164+
return self.reply_data["text"]
165+
166+
def get_author(self):
167+
"""
168+
Get the reply author
169+
170+
:returns: the author ID
171+
:rtype: str
172+
"""
173+
return self.reply_data["author"]
174+
175+
def get_timestamp(self):
176+
"""
177+
Get the reply timestamp
178+
179+
:returns: the reply timestamp
180+
:rtype: long
181+
"""
182+
return self.reply_data["time"]
183+
184+
def get_edited_timestamp(self):
185+
"""
186+
Get the last edition timestamp
187+
188+
:returns: the last edition timestamp
189+
:rtype: long
190+
"""
191+
return self.reply_data["editedOn"]

dataikuapi/dss/managedfolder.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ..utils import DataikuStreamedHttpUTF8CSVReader
44
import json
55
from .metrics import ComputedMetrics
6+
from .discussion import DSSObjectDiscussions
67

78
class DSSManagedFolder(object):
89
"""
@@ -161,4 +162,14 @@ def get_usages(self):
161162
"""
162163
return self.client._perform_json("GET", "/projects/%s/managedfolders/%s/usages" % (self.project_key, self.odb_id))
163164

165+
########################################################
166+
# Discussions
167+
########################################################
168+
def get_object_discussions(self):
169+
"""
170+
Get a handle to manage discussions on the managed folder
164171
172+
:returns: the handle to manage discussions
173+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
174+
"""
175+
return DSSObjectDiscussions(self.client, self.project_key, "MANAGED_FOLDER", self.odb_id)

dataikuapi/dss/notebook.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from .discussion import DSSObjectDiscussions
2+
13
class DSSNotebook(object):
24
"""
35
A Python/R/Scala notebook on the DSS instance
@@ -45,3 +47,15 @@ def get_sessions(self):
4547
if state.get('activeSessions', None) is None:
4648
raise Exception("Notebook isn't running")
4749
return state['activeSessions']
50+
51+
########################################################
52+
# Discussions
53+
########################################################
54+
def get_object_discussions(self):
55+
"""
56+
Get a handle to manage discussions on the notebook
57+
58+
:returns: the handle to manage discussions
59+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
60+
"""
61+
return DSSObjectDiscussions(self.client, self.project_key, "JUPYTER_NOTEBOOK", self.notebook_name)

dataikuapi/dss/project.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from .future import DSSFuture
1212
from .notebook import DSSNotebook
1313
from .macro import DSSMacro
14+
from .wiki import DSSWiki
15+
from .discussion import DSSObjectDiscussions
1416
from .ml import DSSMLTask
1517
from .analysis import DSSAnalysis
1618
from dataikuapi.utils import DataikuException
@@ -745,6 +747,29 @@ def get_macro(self, runnable_type):
745747
"""
746748
return DSSMacro(self.client, self.project_key, runnable_type)
747749

750+
########################################################
751+
# Wiki
752+
########################################################
753+
def get_wiki(self):
754+
"""
755+
Get the wiki
756+
757+
:returns: the wiki associated to the project
758+
:rtype: :class:`dataikuapi.dss.wiki.DSSWiki`
759+
"""
760+
return DSSWiki(self.client, self.project_key)
761+
762+
########################################################
763+
# Discussions
764+
########################################################
765+
def get_object_discussions(self):
766+
"""
767+
Get a handle to manage discussions on the project
768+
769+
:returns: the handle to manage discussions
770+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
771+
"""
772+
return DSSObjectDiscussions(self.client, self.project_key, "PROJECT", self.project_key)
748773

749774
class DSSProjectSettings(object):
750775
"""Settings of a DSS project"""

dataikuapi/dss/recipe.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ..utils import DataikuException
2+
from .discussion import DSSObjectDiscussions
23
import json
34

45
class DSSRecipe(object):
@@ -76,6 +77,18 @@ def set_metadata(self, metadata):
7677
"PUT", "/projects/%s/recipes/%s/metadata" % (self.project_key, self.recipe_name),
7778
body=metadata)
7879

80+
########################################################
81+
# Discussions
82+
########################################################
83+
def get_object_discussions(self):
84+
"""
85+
Get a handle to manage discussions on the recipe
86+
87+
:returns: the handle to manage discussions
88+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
89+
"""
90+
return DSSObjectDiscussions(self.client, self.project_key, "RECIPE", self.recipe_name)
91+
7992

8093
class DSSRecipeDefinitionAndPayload(object):
8194
"""

dataikuapi/dss/savedmodel.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import json
55
from .ml import DSSTrainedPredictionModelDetails, DSSTrainedClusteringModelDetails
66
from .metrics import ComputedMetrics
7+
from .discussion import DSSObjectDiscussions
78

89
class DSSSavedModel(object):
910
"""
@@ -97,3 +98,14 @@ def get_usages(self):
9798
return self.client._perform_json("GET", "/projects/%s/savedmodels/%s/usages" % (self.project_key, self.sm_id))
9899

99100

101+
########################################################
102+
# Discussions
103+
########################################################
104+
def get_object_discussions(self):
105+
"""
106+
Get a handle to manage discussions on the saved model
107+
108+
:returns: the handle to manage discussions
109+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
110+
"""
111+
return DSSObjectDiscussions(self.client, self.project_key, "SAVED_MODEL", self.sm_id)

dataikuapi/dss/scenario.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import datetime
22
import time
33
from dataikuapi.utils import DataikuException
4+
from .discussion import DSSObjectDiscussions
45

56

67
class DSSScenario(object):
@@ -155,6 +156,18 @@ def get_average_duration(self, limit=3):
155156
return None
156157
return sum([run.get_duration() for run in last_runs]) / len(last_runs)
157158

159+
########################################################
160+
# Discussions
161+
########################################################
162+
def get_object_discussions(self):
163+
"""
164+
Get a handle to manage discussions on the scenario
165+
166+
:returns: the handle to manage discussions
167+
:rtype: :class:`dataikuapi.discussion.DSSObjectDiscussions`
168+
"""
169+
return DSSObjectDiscussions(self.client, self.project_key, "SCENARIO", self.id)
170+
158171

159172
class DSSScenarioRun(object):
160173
"""

0 commit comments

Comments
 (0)