Skip to content

Commit b09f950

Browse files
committed
Merge branch 'release/8.0'
2 parents 412fc47 + 77647f6 commit b09f950

File tree

12 files changed

+93
-44
lines changed

12 files changed

+93
-44
lines changed

HISTORY.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Changelog
22
==========
33

4+
7.0.0 (2020-07-21)
5+
------------------
6+
7+
* Initial release for DSS 7.0
8+
49
5.1.0 (2019-03-01)
510
------------------
611

dataikuapi/dss/admin.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def remove_connection_credential(self,connection):
290290

291291
def set_basic_plugin_credential(self, plugin_id, param_set_id, preset_id, param_name, user, password):
292292
"""Sets per-user-credentials for a plugin preset that takes a user/password pair"""
293-
name = json.dumps(["PLUGIN", pluginId, paramSetId, presetId, paramName])[1:-1]
293+
name = json.dumps(["PLUGIN", plugin_id, param_set_id, preset_id, param_name])[1:-1]
294294

295295
self.settings["credentials"][name] = {
296296
"type": "BASIC",
@@ -300,7 +300,7 @@ def set_basic_plugin_credential(self, plugin_id, param_set_id, preset_id, param_
300300

301301
def set_oauth2_plugin_credential(self, plugin_id, param_set_id, preset_id, param_name, refresh_token):
302302
"""Sets per-user-credentials for a plugin preset that takes a OAuth refresh token"""
303-
name = json.dumps(["PLUGIN", pluginId, paramSetId, presetId, paramName])[1:-1]
303+
name = json.dumps(["PLUGIN", plugin_id, param_set_id, preset_id, param_name])[1:-1]
304304

305305
self.settings["credentials"][name] = {
306306
"type": "OAUTH_REFRESH_TOKEN",
@@ -309,7 +309,7 @@ def set_oauth2_plugin_credential(self, plugin_id, param_set_id, preset_id, param
309309

310310
def remove_plugin_credential(self, plugin_id, param_set_id, preset_id, param_name):
311311
"""Removes per-user-credentials for a plugin preset"""
312-
name = json.dumps(["PLUGIN", pluginId, paramSetId, presetId, paramName])[1:-1]
312+
name = json.dumps(["PLUGIN", plugin_id, param_set_id, preset_id, param_name])[1:-1]
313313

314314
if name in self.settings["credentials"]:
315315
del self.settings["credentials"][name]
@@ -732,14 +732,15 @@ def set_jupyter_support(self, active):
732732
raise Exception('Env update failed : %s' % (json.dumps(resp.get('messages', {}).get('messages', {}))))
733733
return resp
734734

735-
def update_packages(self):
735+
def update_packages(self, force_rebuild_env=False):
736736
"""
737737
Update the code env packages so that it matches its spec
738738
739739
Note: this call requires an API key with admin rights
740740
"""
741741
resp = self.client._perform_json(
742-
"POST", "/admin/code-envs/%s/%s/packages" % (self.env_lang, self.env_name))
742+
"POST", "/admin/code-envs/%s/%s/packages" % (self.env_lang, self.env_name),
743+
params={"forceRebuildEnv": force_rebuild_env})
743744
if resp is None:
744745
raise Exception('Env update returned no data')
745746
if resp.get('messages', {}).get('error', False):
@@ -797,6 +798,7 @@ def set_definition(self, definition):
797798
"PUT", "/admin/globalAPIKeys/%s" % self.key,
798799
body = definition)
799800

801+
800802
class DSSCluster(object):
801803
"""
802804
A handle to interact with a cluster on the DSS instance
@@ -873,7 +875,7 @@ def start(self):
873875
resp = self.client._perform_json(
874876
"POST", "/admin/clusters/%s/actions/start" % (self.cluster_id))
875877
if resp is None:
876-
raise Exception('Env update returned no data')
878+
raise Exception('Cluster operation returned no data')
877879
if resp.get('messages', {}).get('error', False):
878880
raise Exception('Cluster operation failed : %s' % (json.dumps(resp.get('messages', {}).get('messages', {}))))
879881
return resp
@@ -895,6 +897,9 @@ def stop(self, terminate=True):
895897
return resp
896898

897899
class DSSClusterSettings(object):
900+
"""
901+
The settings of a cluster
902+
"""
898903
def __init__(self, client, cluster_id, settings):
899904
"""Do not call directly, use :meth:`DSSCluster.get_settings`"""
900905
self.client = client
@@ -927,6 +932,9 @@ def save(self):
927932
"PUT", "/admin/clusters/%s" % (self.cluster_id), body=self.settings)
928933

929934
class DSSClusterStatus(object):
935+
"""
936+
The status of a cluster
937+
"""
930938
def __init__(self, client, cluster_id, status):
931939
"""Do not call directly, use :meth:`DSSCluster.get_Status`"""
932940
self.client = client
@@ -937,4 +945,4 @@ def get_raw(self):
937945
"""
938946
Gets the whole status as a raw dictionary.
939947
"""
940-
return self.status
948+
return self.status

dataikuapi/dss/app.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,42 @@
1-
import sys
1+
import random
22
import re
3-
import os.path as osp
3+
import string
4+
45
from .future import DSSFuture
5-
from dataikuapi.utils import DataikuException
6-
import random, string
6+
77

88
def random_string(length):
99
return ''.join(random.choice(string.ascii_letters) for _ in range(length))
1010

11+
1112
class DSSApp(object):
1213
"""
13-
A handle to interact with a app on the DSS instance.
14-
Do not create this class directly, instead use :meth:`dataikuapi.DSSClient.get_app``
14+
A handle to interact with an application on the DSS instance.
15+
Do not create this class directly, instead use :meth:`dataikuapi.DSSClient.get_app`
1516
"""
1617
def __init__(self, client, app_id):
17-
self.client = client
18-
self.app_id = app_id
18+
self.client = client
19+
self.app_id = app_id
1920

2021
########################################################
2122
# Instances
2223
########################################################
2324

2425
def create_instance(self, instance_key, instance_name, wait=True):
2526
"""
26-
Creates a new instance of this app. Each instance. must have a globally unique
27+
Creates a new instance of this application. Each instance. must have a globally unique
2728
instance key, separate from any project key across the whole DSS instance
2829
2930
:return:
3031
"""
3132
future_resp = self.client._perform_json(
3233
"POST", "/apps/%s/instances" % self.app_id, body={
33-
"targetProjectKey" : instance_key,
34-
"targetProjectName" : instance_name
35-
})
34+
"targetProjectKey": instance_key,
35+
"targetProjectName": instance_name
36+
})
3637
future = DSSFuture(self.client, future_resp.get("jobId", None), future_resp)
3738
if wait:
38-
result = future.wait_for_result()
39+
future.wait_for_result()
3940
return DSSAppInstance(self.client, instance_key)
4041
else:
4142
return future
@@ -46,13 +47,13 @@ def make_random_project_key(self):
4647

4748
def create_temporary_instance(self):
4849
"""
49-
Creates a new temporary instance of this app.
50+
Creates a new temporary instance of this application.
5051
The return value should be used as a Python context manager. Upon exit, the temporary app
5152
instance is deleted
5253
:return a :class:`TemporaryDSSAppInstance`
5354
"""
5455
key = self.make_random_project_key()
55-
instance = self.create_instance(key, key, True)
56+
self.create_instance(key, key, True)
5657
return TemporaryDSSAppInstance(self.client, key)
5758

5859
def list_instance_keys(self):
@@ -85,7 +86,7 @@ def get_manifest(self):
8586
class DSSAppManifest(object):
8687

8788
def __init__(self, client, raw_data, project_key=None):
88-
"""The manifest for an app. Do not create this class directly"""
89+
"""The manifest for an application. Do not create this class directly"""
8990
self.client = client
9091
self.raw_data = raw_data
9192
self.project_key = project_key
@@ -110,34 +111,34 @@ def save(self):
110111
class DSSAppInstance(object):
111112

112113
def __init__(self, client, project_key):
113-
self.client = client
114-
self.project_key = project_key
114+
self.client = client
115+
self.project_key = project_key
115116

116117
def get_as_project(self):
117118
"""
118-
Get the :class:`dataikuapi.dss.project DSSProject` corresponding to this app instance
119+
Get the :class:`dataikuapi.dss.project DSSProject` corresponding to this application instance
119120
"""
120121
return self.client.get_project(self.project_key)
121122

122123
def get_manifest(self):
123124
"""
124-
Get the app manifest for this instance, as a :class:`DSSAppManifest`
125+
Get the application manifest for this instance, as a :class:`DSSAppManifest`
125126
"""
126127
raw_data = self.client._perform_json("GET", "/projects/%s/app-manifest" % self.project_key)
127128
return DSSAppManifest(self.client, raw_data)
128129

130+
129131
class TemporaryDSSAppInstance(DSSAppInstance):
130132
"""internal class"""
131133

132134
def __init__(self, client, project_key):
133135
DSSAppInstance.__init__(self, client,project_key)
134136

135-
136137
def close(self):
137138
self.get_as_project().delete(drop_data=True)
138139

139140
def __enter__(self,):
140141
return self
141142

142143
def __exit__(self, type, value, traceback):
143-
self.close()
144+
self.close()

dataikuapi/dss/continuousactivity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import time
22
import sys
3-
from dataikuapi.utils import DataikuException
3+
from ..utils import DataikuException
44

55
class DSSContinuousActivity(object):
66
"""
@@ -40,4 +40,4 @@ def get_recipe(self):
4040
Return a handle on the associated recipe
4141
"""
4242
from .recipe import DSSRecipe
43-
return DSSRecipe(self.client, self.project_key, self.recipe_id)
43+
return DSSRecipe(self.client, self.project_key, self.recipe_id)

dataikuapi/dss/flow.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,9 @@ def get_successor_computables(self, node, as_type="dict"):
515515
return self._convert_nodes_list(computables, as_type)
516516

517517
def _convert_nodes_list(self, nodes, as_type):
518+
actual_nodes = [node for node in nodes if node['type'] != 'RUNNABLE_IMPLICIT_RECIPE']
518519
if as_type == "object" or as_type == "objects":
519-
return [self._get_object_from_graph_node(node) for node in nodes]
520+
return [self._get_object_from_graph_node(node) for node in actual_nodes]
520521
else:
521522
return nodes
522523

@@ -529,6 +530,8 @@ def _get_object_from_graph_node(self, node):
529530
return DSSManagedFolder(self.flow.client, self.flow.project.project_key, node["ref"])
530531
elif node["type"] == "COMPUTABLE_SAVED_MODEL":
531532
return DSSSavedModel(self.flow.client, self.flow.project.project_key, node["ref"])
533+
elif node["type"] == "COMPUTABLE_STREAMING_ENDPOINT":
534+
return DSSStreamingEndpoint(self.flow.client, self.flow.project.project_key, node["ref"])
532535
else:
533536
# TODO add streaming elements
534537
raise Exception("unsupported node type: %s" % node["type"])

dataikuapi/dss/ml.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ def disable_all_algorithms(self):
275275
custom_mllib["enabled"] = False
276276
for custom_python in self.mltask_settings["modeling"]["custom_python"]:
277277
custom_python["enabled"] = False
278-
for plugin in self.mltask_settings["modeling"]["plugin"].values():
278+
for plugin in self.mltask_settings["modeling"]["plugin_python"].values():
279279
plugin["enabled"] = False
280280

281281
def get_all_possible_algorithm_names(self):
@@ -1447,7 +1447,7 @@ class DSSMLTask(object):
14471447

14481448
@staticmethod
14491449
def from_full_model_id(client, fmi, project_key=None):
1450-
match = re.match("^A-(\w+)-(\w+)-(\w+)-(s[0-9]+)-(pp[0-9]+(-part-(\w+)|-base)?)-(m[0-9]+)$", fmi)
1450+
match = re.match(r"^A-(\w+)-(\w+)-(\w+)-(s[0-9]+)-(pp[0-9]+(-part-(\w+)|-base)?)-(m[0-9]+)$", fmi)
14511451
if match is None:
14521452
return DataikuException("Invalid model id: {}".format(fmi))
14531453
else:

dataikuapi/dss/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from dataikuapi.utils import DataikuException
1+
from ..utils import DataikuException
22

33

44
class DSSPluginSettings(object):

dataikuapi/dss/project.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,9 +1384,11 @@ def set_python_code_env(self, code_env_name):
13841384
"""
13851385
if code_env_name is None:
13861386
self.settings["settings"]["codeEnvs"]["python"]["useBuiltinEnv"] = True
1387+
self.settings["settings"]["codeEnvs"]["python"]["mode"] = "USE_BUILTIN_MODE"
13871388
else:
13881389
self.settings["settings"]["codeEnvs"]["python"]["useBuiltinEnv"] = False
13891390
self.settings["settings"]["codeEnvs"]["python"]["envName"] = code_env_name
1391+
self.settings["settings"]["codeEnvs"]["python"]["mode"] = "EXPLICIT_ENV"
13901392

13911393
def set_r_code_env(self, code_env_name):
13921394
"""Sets the default R code env used by this project
@@ -1395,9 +1397,11 @@ def set_r_code_env(self, code_env_name):
13951397
"""
13961398
if code_env_name is None:
13971399
self.settings["settings"]["codeEnvs"]["r"]["useBuiltinEnv"] = True
1400+
self.settings["settings"]["codeEnvs"]["r"]["mode"] = "USE_BUILTIN_MODE"
13981401
else:
13991402
self.settings["settings"]["codeEnvs"]["r"]["useBuiltinEnv"] = False
14001403
self.settings["settings"]["codeEnvs"]["r"]["envName"] = code_env_name
1404+
self.settings["settings"]["codeEnvs"]["r"]["mode"] = "EXPLICIT_ENV"
14011405

14021406
def set_container_exec_config(self, config_name):
14031407
"""Sets the default containerized execution config used by this project

dataikuapi/dss/savedmodel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from dataikuapi.dss.ml import DSSMLTask
21
from .metrics import ComputedMetrics
2+
from .ml import DSSMLTask
33
from .ml import DSSTrainedClusteringModelDetails
44
from .ml import DSSTrainedPredictionModelDetails
55

dataikuapi/dss/tools/codegen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __exit__(self, b, c, d):
1414

1515

1616
def slugify(name):
17-
return re.sub("[^A-Za-z0-9_]", "_", name)
17+
return re.sub("r[^A-Za-z0-9_]", "_", name)
1818

1919
class FlowCodeGenerator(object):
2020
def __init__(self):

0 commit comments

Comments
 (0)