nextmv 0.40.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nextmv/__about__.py +1 -1
- nextmv/__entrypoint__.py +1 -2
- nextmv/__init__.py +2 -4
- nextmv/cli/CONTRIBUTING.md +583 -0
- nextmv/cli/cloud/__init__.py +49 -0
- nextmv/cli/cloud/acceptance/__init__.py +27 -0
- nextmv/cli/cloud/acceptance/create.py +391 -0
- nextmv/cli/cloud/acceptance/delete.py +64 -0
- nextmv/cli/cloud/acceptance/get.py +103 -0
- nextmv/cli/cloud/acceptance/list.py +62 -0
- nextmv/cli/cloud/acceptance/update.py +95 -0
- nextmv/cli/cloud/account/__init__.py +28 -0
- nextmv/cli/cloud/account/create.py +83 -0
- nextmv/cli/cloud/account/delete.py +59 -0
- nextmv/cli/cloud/account/get.py +66 -0
- nextmv/cli/cloud/account/update.py +70 -0
- nextmv/cli/cloud/app/__init__.py +35 -0
- nextmv/cli/cloud/app/create.py +140 -0
- nextmv/cli/cloud/app/delete.py +57 -0
- nextmv/cli/cloud/app/exists.py +44 -0
- nextmv/cli/cloud/app/get.py +66 -0
- nextmv/cli/cloud/app/list.py +61 -0
- nextmv/cli/cloud/app/push.py +432 -0
- nextmv/cli/cloud/app/update.py +124 -0
- nextmv/cli/cloud/batch/__init__.py +29 -0
- nextmv/cli/cloud/batch/create.py +452 -0
- nextmv/cli/cloud/batch/delete.py +64 -0
- nextmv/cli/cloud/batch/get.py +104 -0
- nextmv/cli/cloud/batch/list.py +63 -0
- nextmv/cli/cloud/batch/metadata.py +66 -0
- nextmv/cli/cloud/batch/update.py +95 -0
- nextmv/cli/cloud/data/__init__.py +26 -0
- nextmv/cli/cloud/data/upload.py +162 -0
- nextmv/cli/cloud/ensemble/__init__.py +33 -0
- nextmv/cli/cloud/ensemble/create.py +413 -0
- nextmv/cli/cloud/ensemble/delete.py +63 -0
- nextmv/cli/cloud/ensemble/get.py +65 -0
- nextmv/cli/cloud/ensemble/list.py +63 -0
- nextmv/cli/cloud/ensemble/update.py +103 -0
- nextmv/cli/cloud/input_set/__init__.py +32 -0
- nextmv/cli/cloud/input_set/create.py +168 -0
- nextmv/cli/cloud/input_set/delete.py +64 -0
- nextmv/cli/cloud/input_set/get.py +63 -0
- nextmv/cli/cloud/input_set/list.py +63 -0
- nextmv/cli/cloud/input_set/update.py +123 -0
- nextmv/cli/cloud/instance/__init__.py +35 -0
- nextmv/cli/cloud/instance/create.py +289 -0
- nextmv/cli/cloud/instance/delete.py +61 -0
- nextmv/cli/cloud/instance/exists.py +39 -0
- nextmv/cli/cloud/instance/get.py +62 -0
- nextmv/cli/cloud/instance/list.py +60 -0
- nextmv/cli/cloud/instance/update.py +216 -0
- nextmv/cli/cloud/managed_input/__init__.py +31 -0
- nextmv/cli/cloud/managed_input/create.py +144 -0
- nextmv/cli/cloud/managed_input/delete.py +64 -0
- nextmv/cli/cloud/managed_input/get.py +63 -0
- nextmv/cli/cloud/managed_input/list.py +60 -0
- nextmv/cli/cloud/managed_input/update.py +97 -0
- nextmv/cli/cloud/run/__init__.py +37 -0
- nextmv/cli/cloud/run/cancel.py +37 -0
- nextmv/cli/cloud/run/create.py +524 -0
- nextmv/cli/cloud/run/get.py +199 -0
- nextmv/cli/cloud/run/input.py +86 -0
- nextmv/cli/cloud/run/list.py +80 -0
- nextmv/cli/cloud/run/logs.py +166 -0
- nextmv/cli/cloud/run/metadata.py +67 -0
- nextmv/cli/cloud/run/track.py +500 -0
- nextmv/cli/cloud/scenario/__init__.py +29 -0
- nextmv/cli/cloud/scenario/create.py +451 -0
- nextmv/cli/cloud/scenario/delete.py +61 -0
- nextmv/cli/cloud/scenario/get.py +102 -0
- nextmv/cli/cloud/scenario/list.py +63 -0
- nextmv/cli/cloud/scenario/metadata.py +67 -0
- nextmv/cli/cloud/scenario/update.py +93 -0
- nextmv/cli/cloud/secrets/__init__.py +33 -0
- nextmv/cli/cloud/secrets/create.py +206 -0
- nextmv/cli/cloud/secrets/delete.py +63 -0
- nextmv/cli/cloud/secrets/get.py +66 -0
- nextmv/cli/cloud/secrets/list.py +60 -0
- nextmv/cli/cloud/secrets/update.py +144 -0
- nextmv/cli/cloud/shadow/__init__.py +33 -0
- nextmv/cli/cloud/shadow/create.py +184 -0
- nextmv/cli/cloud/shadow/delete.py +64 -0
- nextmv/cli/cloud/shadow/get.py +61 -0
- nextmv/cli/cloud/shadow/list.py +63 -0
- nextmv/cli/cloud/shadow/metadata.py +66 -0
- nextmv/cli/cloud/shadow/start.py +43 -0
- nextmv/cli/cloud/shadow/stop.py +53 -0
- nextmv/cli/cloud/shadow/update.py +96 -0
- nextmv/cli/cloud/switchback/__init__.py +33 -0
- nextmv/cli/cloud/switchback/create.py +151 -0
- nextmv/cli/cloud/switchback/delete.py +64 -0
- nextmv/cli/cloud/switchback/get.py +62 -0
- nextmv/cli/cloud/switchback/list.py +63 -0
- nextmv/cli/cloud/switchback/metadata.py +68 -0
- nextmv/cli/cloud/switchback/start.py +43 -0
- nextmv/cli/cloud/switchback/stop.py +53 -0
- nextmv/cli/cloud/switchback/update.py +96 -0
- nextmv/cli/cloud/upload/__init__.py +22 -0
- nextmv/cli/cloud/upload/create.py +39 -0
- nextmv/cli/cloud/version/__init__.py +33 -0
- nextmv/cli/cloud/version/create.py +96 -0
- nextmv/cli/cloud/version/delete.py +61 -0
- nextmv/cli/cloud/version/exists.py +39 -0
- nextmv/cli/cloud/version/get.py +62 -0
- nextmv/cli/cloud/version/list.py +60 -0
- nextmv/cli/cloud/version/update.py +92 -0
- nextmv/cli/community/__init__.py +24 -0
- nextmv/cli/community/clone.py +20 -204
- nextmv/cli/community/list.py +61 -126
- nextmv/cli/configuration/__init__.py +23 -0
- nextmv/cli/configuration/config.py +103 -6
- nextmv/cli/configuration/create.py +17 -18
- nextmv/cli/configuration/delete.py +25 -13
- nextmv/cli/configuration/list.py +4 -4
- nextmv/cli/confirm.py +34 -0
- nextmv/cli/main.py +68 -36
- nextmv/cli/message.py +170 -0
- nextmv/cli/options.py +196 -0
- nextmv/cli/version.py +20 -1
- nextmv/cloud/__init__.py +17 -38
- nextmv/cloud/acceptance_test.py +20 -83
- nextmv/cloud/account.py +269 -30
- nextmv/cloud/application/__init__.py +898 -0
- nextmv/cloud/application/_acceptance.py +424 -0
- nextmv/cloud/application/_batch_scenario.py +845 -0
- nextmv/cloud/application/_ensemble.py +251 -0
- nextmv/cloud/application/_input_set.py +263 -0
- nextmv/cloud/application/_instance.py +289 -0
- nextmv/cloud/application/_managed_input.py +227 -0
- nextmv/cloud/application/_run.py +1393 -0
- nextmv/cloud/application/_secrets.py +294 -0
- nextmv/cloud/application/_shadow.py +320 -0
- nextmv/cloud/application/_switchback.py +332 -0
- nextmv/cloud/application/_utils.py +54 -0
- nextmv/cloud/application/_version.py +304 -0
- nextmv/cloud/batch_experiment.py +6 -2
- nextmv/cloud/community.py +446 -0
- nextmv/cloud/instance.py +11 -1
- nextmv/cloud/integration.py +8 -5
- nextmv/cloud/package.py +50 -9
- nextmv/cloud/shadow.py +254 -0
- nextmv/cloud/switchback.py +228 -0
- nextmv/deprecated.py +5 -3
- nextmv/input.py +20 -88
- nextmv/local/application.py +3 -15
- nextmv/local/runner.py +1 -1
- nextmv/model.py +50 -11
- nextmv/options.py +11 -256
- nextmv/output.py +0 -62
- nextmv/polling.py +54 -16
- nextmv/run.py +84 -37
- nextmv/status.py +1 -51
- {nextmv-0.40.0.dist-info → nextmv-1.0.0.dist-info}/METADATA +37 -11
- nextmv-1.0.0.dist-info/RECORD +185 -0
- nextmv-1.0.0.dist-info/entry_points.txt +2 -0
- nextmv/cli/community/community.py +0 -24
- nextmv/cli/configuration/configuration.py +0 -23
- nextmv/cli/error.py +0 -22
- nextmv/cloud/application.py +0 -4204
- nextmv-0.40.0.dist-info/RECORD +0 -66
- {nextmv-0.40.0.dist-info → nextmv-1.0.0.dist-info}/WHEEL +0 -0
- {nextmv-0.40.0.dist-info → nextmv-1.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application mixin for managing app ensembles.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from nextmv.cloud.ensemble import EnsembleDefinition, EvaluationRule, RunGroup
|
|
8
|
+
from nextmv.deprecated import deprecated
|
|
9
|
+
from nextmv.safe import safe_id
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from . import Application
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ApplicationEnsembleMixin:
|
|
16
|
+
"""
|
|
17
|
+
Mixin class for managing app ensembles within an application.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def delete_ensemble_definition(self: "Application", ensemble_definition_id: str) -> None:
|
|
21
|
+
"""
|
|
22
|
+
Delete an ensemble definition.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
ensemble_definition_id : str
|
|
27
|
+
ID of the ensemble definition to delete.
|
|
28
|
+
|
|
29
|
+
Raises
|
|
30
|
+
------
|
|
31
|
+
requests.HTTPError
|
|
32
|
+
If the response status code is not 2xx.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> app.delete_ensemble_definition("development-ensemble-definition")
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
_ = self.client.request(
|
|
40
|
+
method="DELETE",
|
|
41
|
+
endpoint=f"{self.ensembles_endpoint}/{ensemble_definition_id}",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def ensemble_definition(self: "Application", ensemble_definition_id: str) -> EnsembleDefinition:
|
|
45
|
+
"""
|
|
46
|
+
Get an ensemble definition.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
ensemble_definition_id : str
|
|
51
|
+
ID of the ensemble definition to retrieve.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
EnsembleDefintion
|
|
56
|
+
The requested ensemble definition details.
|
|
57
|
+
|
|
58
|
+
Raises
|
|
59
|
+
------
|
|
60
|
+
requests.HTTPError
|
|
61
|
+
If the response status code is not 2xx.
|
|
62
|
+
|
|
63
|
+
Examples
|
|
64
|
+
--------
|
|
65
|
+
>>> ensemble_definition = app.ensemble_definition("instance-123")
|
|
66
|
+
>>> print(ensemble_definition.name)
|
|
67
|
+
'Production Ensemble Definition'
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
response = self.client.request(
|
|
71
|
+
method="GET",
|
|
72
|
+
endpoint=f"{self.ensembles_endpoint}/{ensemble_definition_id}",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
76
|
+
|
|
77
|
+
def list_ensemble_definitions(self: "Application") -> list[EnsembleDefinition]:
|
|
78
|
+
"""
|
|
79
|
+
List all ensemble_definitions.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
list[EnsembleDefinition]
|
|
84
|
+
List of all ensemble definitions associated with this application.
|
|
85
|
+
|
|
86
|
+
Raises
|
|
87
|
+
------
|
|
88
|
+
requests.HTTPError
|
|
89
|
+
If the response status code is not 2xx.
|
|
90
|
+
|
|
91
|
+
Examples
|
|
92
|
+
--------
|
|
93
|
+
>>> ensemble_definitions = app.list_ensemble_definitions()
|
|
94
|
+
>>> for ensemble_definition in ensemble_definitions:
|
|
95
|
+
... print(ensemble_definition.name)
|
|
96
|
+
'Development Ensemble Definition'
|
|
97
|
+
'Production Ensemble Definition'
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
response = self.client.request(
|
|
101
|
+
method="GET",
|
|
102
|
+
endpoint=f"{self.ensembles_endpoint}",
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
return [EnsembleDefinition.from_dict(ensemble_definition) for ensemble_definition in response.json()["items"]]
|
|
106
|
+
|
|
107
|
+
def new_ensemble_defintion(
|
|
108
|
+
self: "Application",
|
|
109
|
+
id: str,
|
|
110
|
+
run_groups: list[RunGroup],
|
|
111
|
+
rules: list[EvaluationRule],
|
|
112
|
+
name: str | None = None,
|
|
113
|
+
description: str | None = None,
|
|
114
|
+
) -> EnsembleDefinition:
|
|
115
|
+
"""
|
|
116
|
+
!!! warning
|
|
117
|
+
`new_ensemble_defintion` is deprecated, use `new_ensemble_definition` instead.
|
|
118
|
+
|
|
119
|
+
Create a new ensemble definition.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
id: str
|
|
124
|
+
ID of the ensemble defintion.
|
|
125
|
+
run_groups: list[RunGroup]
|
|
126
|
+
Information to facilitate the execution of child runs.
|
|
127
|
+
rules: list[EvaluationRule]
|
|
128
|
+
Information to facilitate the selection of
|
|
129
|
+
a result for the ensemble run from child runs.
|
|
130
|
+
name: Optional[str]
|
|
131
|
+
Name of the ensemble definition.
|
|
132
|
+
description: Optional[str]
|
|
133
|
+
Description of the ensemble definition.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
deprecated(
|
|
137
|
+
name="new_ensemble_defintion",
|
|
138
|
+
reason="`Application.new_ensemble_defintion` is deprecated, use `new_ensemble_definition` instead",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return self.new_ensemble_definition(
|
|
142
|
+
run_groups=run_groups,
|
|
143
|
+
rules=rules,
|
|
144
|
+
id=id,
|
|
145
|
+
name=name,
|
|
146
|
+
description=description,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def new_ensemble_definition(
|
|
150
|
+
self: "Application",
|
|
151
|
+
run_groups: list[RunGroup],
|
|
152
|
+
rules: list[EvaluationRule],
|
|
153
|
+
id: str | None = None,
|
|
154
|
+
name: str | None = None,
|
|
155
|
+
description: str | None = None,
|
|
156
|
+
) -> EnsembleDefinition:
|
|
157
|
+
"""
|
|
158
|
+
Create a new ensemble definition.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
run_groups: list[RunGroup]
|
|
163
|
+
Information to facilitate the execution of child runs.
|
|
164
|
+
rules: list[EvaluationRule]
|
|
165
|
+
Information to facilitate the selection of
|
|
166
|
+
a result for the ensemble run from child runs.
|
|
167
|
+
id: str | None, default=None
|
|
168
|
+
ID of the ensemble definition. If not provided, a unique ID will be
|
|
169
|
+
generated with the prefix 'ensemble-'.
|
|
170
|
+
name: Optional[str]
|
|
171
|
+
Name of the ensemble definition. If not provided, the ID will be used.
|
|
172
|
+
description: Optional[str]
|
|
173
|
+
Description of the ensemble definition. If not provided, the name will be used.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
if len(run_groups) == 0:
|
|
177
|
+
raise ValueError("at least one run group must be defined to create an ensemble definition")
|
|
178
|
+
|
|
179
|
+
if len(rules) == 0:
|
|
180
|
+
raise ValueError("at least one evaluation rule must be defined to create an ensemble definition")
|
|
181
|
+
|
|
182
|
+
if id is None or id == "":
|
|
183
|
+
id = safe_id(prefix="ensemble")
|
|
184
|
+
if name is None or name == "":
|
|
185
|
+
name = id
|
|
186
|
+
if description is None or description == "":
|
|
187
|
+
description = name
|
|
188
|
+
|
|
189
|
+
payload = {
|
|
190
|
+
"id": id,
|
|
191
|
+
"run_groups": [run_group.to_dict() for run_group in run_groups],
|
|
192
|
+
"rules": [rule.to_dict() for rule in rules],
|
|
193
|
+
"name": name,
|
|
194
|
+
"description": description,
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
response = self.client.request(
|
|
198
|
+
method="POST",
|
|
199
|
+
endpoint=f"{self.ensembles_endpoint}",
|
|
200
|
+
payload=payload,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
204
|
+
|
|
205
|
+
def update_ensemble_definition(
|
|
206
|
+
self: "Application",
|
|
207
|
+
id: str,
|
|
208
|
+
name: str | None = None,
|
|
209
|
+
description: str | None = None,
|
|
210
|
+
) -> EnsembleDefinition:
|
|
211
|
+
"""
|
|
212
|
+
Update an ensemble definition.
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
id : str
|
|
217
|
+
ID of the ensemble definition to update.
|
|
218
|
+
name : Optional[str], default=None
|
|
219
|
+
Optional name of the ensemble definition.
|
|
220
|
+
description : Optional[str], default=None
|
|
221
|
+
Optional description of the ensemble definition.
|
|
222
|
+
|
|
223
|
+
Returns
|
|
224
|
+
-------
|
|
225
|
+
EnsembleDefinition
|
|
226
|
+
The updated ensemble definition.
|
|
227
|
+
|
|
228
|
+
Raises
|
|
229
|
+
------
|
|
230
|
+
ValueError
|
|
231
|
+
If neither name nor description is updated
|
|
232
|
+
requests.HTTPError
|
|
233
|
+
If the response status code is not 2xx.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
payload = {}
|
|
237
|
+
|
|
238
|
+
if name is None and description is None:
|
|
239
|
+
raise ValueError("Must define at least one value among name and description to modify")
|
|
240
|
+
if name is not None:
|
|
241
|
+
payload["name"] = name
|
|
242
|
+
if description is not None:
|
|
243
|
+
payload["description"] = description
|
|
244
|
+
|
|
245
|
+
response = self.client.request(
|
|
246
|
+
method="PATCH",
|
|
247
|
+
endpoint=f"{self.ensembles_endpoint}/{id}",
|
|
248
|
+
payload=payload,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application mixin for managing app input sets.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from nextmv.cloud.input_set import InputSet, ManagedInput
|
|
9
|
+
from nextmv.safe import safe_id
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from . import Application
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ApplicationInputSetMixin:
|
|
16
|
+
"""
|
|
17
|
+
Mixin class for managing app input sets within an application.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def delete_input_set(self: "Application", input_set_id: str) -> None:
|
|
21
|
+
"""
|
|
22
|
+
Delete an input set.
|
|
23
|
+
|
|
24
|
+
Deletes an input set along with all the associated information.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
input_set_id : str
|
|
29
|
+
ID of the input set to delete.
|
|
30
|
+
|
|
31
|
+
Raises
|
|
32
|
+
------
|
|
33
|
+
requests.HTTPError
|
|
34
|
+
If the response status code is not 2xx.
|
|
35
|
+
|
|
36
|
+
Examples
|
|
37
|
+
--------
|
|
38
|
+
>>> app.delete_input_set("input-set-123")
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
_ = self.client.request(
|
|
42
|
+
method="DELETE",
|
|
43
|
+
endpoint=f"{self.experiments_endpoint}/inputsets/{input_set_id}",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def input_set(self: "Application", input_set_id: str) -> InputSet:
|
|
47
|
+
"""
|
|
48
|
+
Get an input set.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
input_set_id : str
|
|
53
|
+
ID of the input set to retrieve.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
InputSet
|
|
58
|
+
The requested input set.
|
|
59
|
+
|
|
60
|
+
Raises
|
|
61
|
+
------
|
|
62
|
+
requests.HTTPError
|
|
63
|
+
If the response status code is not 2xx.
|
|
64
|
+
|
|
65
|
+
Examples
|
|
66
|
+
--------
|
|
67
|
+
>>> input_set = app.input_set("input-set-123")
|
|
68
|
+
>>> print(input_set.name)
|
|
69
|
+
'My Input Set'
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
response = self.client.request(
|
|
73
|
+
method="GET",
|
|
74
|
+
endpoint=f"{self.experiments_endpoint}/inputsets/{input_set_id}",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return InputSet.from_dict(response.json())
|
|
78
|
+
|
|
79
|
+
def list_input_sets(self: "Application") -> list[InputSet]:
|
|
80
|
+
"""
|
|
81
|
+
List all input sets.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
list[InputSet]
|
|
86
|
+
List of all input sets associated with this application.
|
|
87
|
+
|
|
88
|
+
Raises
|
|
89
|
+
------
|
|
90
|
+
requests.HTTPError
|
|
91
|
+
If the response status code is not 2xx.
|
|
92
|
+
|
|
93
|
+
Examples
|
|
94
|
+
--------
|
|
95
|
+
>>> input_sets = app.list_input_sets()
|
|
96
|
+
>>> for input_set in input_sets:
|
|
97
|
+
... print(input_set.name)
|
|
98
|
+
'Input Set 1'
|
|
99
|
+
'Input Set 2'
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
response = self.client.request(
|
|
103
|
+
method="GET",
|
|
104
|
+
endpoint=f"{self.experiments_endpoint}/inputsets",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return [InputSet.from_dict(input_set) for input_set in response.json()]
|
|
108
|
+
|
|
109
|
+
def new_input_set(
|
|
110
|
+
self: "Application",
|
|
111
|
+
id: str | None = None,
|
|
112
|
+
name: str | None = None,
|
|
113
|
+
description: str | None = None,
|
|
114
|
+
end_time: datetime | None = None,
|
|
115
|
+
instance_id: str | None = None,
|
|
116
|
+
maximum_runs: int | None = None,
|
|
117
|
+
run_ids: list[str] | None = None,
|
|
118
|
+
start_time: datetime | None = None,
|
|
119
|
+
inputs: list[ManagedInput] | None = None,
|
|
120
|
+
) -> InputSet:
|
|
121
|
+
"""
|
|
122
|
+
Create a new input set. You can create an input set from three
|
|
123
|
+
different methodologies:
|
|
124
|
+
|
|
125
|
+
1. Using `instance_id`, `start_time`, `end_time` and `maximum_runs`.
|
|
126
|
+
Instance runs will be obtained from the application matching the
|
|
127
|
+
criteria of dates and maximum number of runs.
|
|
128
|
+
2. Using `run_ids`. The input set will be created using the list of
|
|
129
|
+
runs specified by the user.
|
|
130
|
+
3. Using `inputs`. The input set will be created using the list of
|
|
131
|
+
inputs specified by the user. This is useful for creating an input
|
|
132
|
+
set from a list of inputs that are already available in the
|
|
133
|
+
application.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
id: str | None = None
|
|
138
|
+
ID of the input set, will be generated if not provided.
|
|
139
|
+
name: str | None = None
|
|
140
|
+
Name of the input set. If not provided, the ID will be used as
|
|
141
|
+
the name.
|
|
142
|
+
description: Optional[str]
|
|
143
|
+
Optional description of the input set.
|
|
144
|
+
end_time: Optional[datetime]
|
|
145
|
+
End time of the input set. This is used to filter the runs
|
|
146
|
+
associated with the input set.
|
|
147
|
+
instance_id: Optional[str]
|
|
148
|
+
ID of the instance to use for the input set. This is used to
|
|
149
|
+
filter the runs associated with the input set. If not provided,
|
|
150
|
+
the application's `default_instance_id` is used.
|
|
151
|
+
maximum_runs: Optional[int]
|
|
152
|
+
Maximum number of runs to use for the input set. This is used to
|
|
153
|
+
filter the runs associated with the input set. If not provided,
|
|
154
|
+
all runs are used.
|
|
155
|
+
run_ids: Optional[list[str]]
|
|
156
|
+
List of run IDs to use for the input set.
|
|
157
|
+
start_time: Optional[datetime]
|
|
158
|
+
Start time of the input set. This is used to filter the runs
|
|
159
|
+
associated with the input set.
|
|
160
|
+
inputs: Optional[list[ManagedInput]]
|
|
161
|
+
List of inputs to use for the input set. This is used to create
|
|
162
|
+
the input set from a list of inputs that are already available in
|
|
163
|
+
the application.
|
|
164
|
+
|
|
165
|
+
Returns
|
|
166
|
+
-------
|
|
167
|
+
InputSet
|
|
168
|
+
The new input set.
|
|
169
|
+
|
|
170
|
+
Raises
|
|
171
|
+
------
|
|
172
|
+
requests.HTTPError
|
|
173
|
+
If the response status code is not 2xx.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
# Generate ID if not provided
|
|
177
|
+
if id is None or id == "":
|
|
178
|
+
id = safe_id("input-set")
|
|
179
|
+
|
|
180
|
+
# Use ID as name if name not provided
|
|
181
|
+
if name is None or name == "":
|
|
182
|
+
name = id
|
|
183
|
+
|
|
184
|
+
payload = {
|
|
185
|
+
"id": id,
|
|
186
|
+
"name": name,
|
|
187
|
+
}
|
|
188
|
+
if description is not None:
|
|
189
|
+
payload["description"] = description
|
|
190
|
+
if end_time is not None:
|
|
191
|
+
payload["end_time"] = end_time.isoformat()
|
|
192
|
+
if instance_id is not None:
|
|
193
|
+
payload["instance_id"] = instance_id
|
|
194
|
+
if maximum_runs is not None:
|
|
195
|
+
payload["maximum_runs"] = maximum_runs
|
|
196
|
+
if run_ids is not None:
|
|
197
|
+
payload["run_ids"] = run_ids
|
|
198
|
+
if start_time is not None:
|
|
199
|
+
payload["start_time"] = start_time.isoformat()
|
|
200
|
+
if inputs is not None:
|
|
201
|
+
payload["inputs"] = [input.to_dict() for input in inputs]
|
|
202
|
+
|
|
203
|
+
response = self.client.request(
|
|
204
|
+
method="POST",
|
|
205
|
+
endpoint=f"{self.experiments_endpoint}/inputsets",
|
|
206
|
+
payload=payload,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
return InputSet.from_dict(response.json())
|
|
210
|
+
|
|
211
|
+
def update_input_set(
|
|
212
|
+
self: "Application",
|
|
213
|
+
id: str,
|
|
214
|
+
name: str | None = None,
|
|
215
|
+
description: str | None = None,
|
|
216
|
+
inputs: list[ManagedInput] | None = None,
|
|
217
|
+
) -> InputSet:
|
|
218
|
+
"""
|
|
219
|
+
Update an input set.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
id : str
|
|
224
|
+
ID of the input set to update.
|
|
225
|
+
name : Optional[str], default=None
|
|
226
|
+
Optional name of the input set.
|
|
227
|
+
description : Optional[str], default=None
|
|
228
|
+
Optional description of the input set.
|
|
229
|
+
inputs: Optional[list[ManagedInput]]
|
|
230
|
+
List of inputs to use for the input set. This is used to create
|
|
231
|
+
the input set from a list of inputs that are already available in
|
|
232
|
+
the application.
|
|
233
|
+
|
|
234
|
+
Returns
|
|
235
|
+
-------
|
|
236
|
+
Instance
|
|
237
|
+
The updated instance.
|
|
238
|
+
|
|
239
|
+
Raises
|
|
240
|
+
------
|
|
241
|
+
requests.HTTPError
|
|
242
|
+
If the response status code is not 2xx.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
# Get the input set as it currently exsits.
|
|
246
|
+
input_set = self.input_set(id)
|
|
247
|
+
input_set_dict = input_set.to_dict()
|
|
248
|
+
payload = input_set_dict.copy()
|
|
249
|
+
|
|
250
|
+
if name is not None:
|
|
251
|
+
payload["name"] = name
|
|
252
|
+
if description is not None:
|
|
253
|
+
payload["description"] = description
|
|
254
|
+
if inputs is not None:
|
|
255
|
+
payload["inputs"] = [input.to_dict() for input in inputs]
|
|
256
|
+
|
|
257
|
+
response = self.client.request(
|
|
258
|
+
method="PUT",
|
|
259
|
+
endpoint=f"{self.experiments_endpoint}/inputsets/{id}",
|
|
260
|
+
payload=payload,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return InputSet.from_dict(response.json())
|