nextmv 0.31.0__tar.gz → 0.33.0.dev0__tar.gz
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-0.31.0 → nextmv-0.33.0.dev0}/PKG-INFO +1 -1
- nextmv-0.33.0.dev0/nextmv/__about__.py +1 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/__init__.py +4 -9
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/__init__.py +7 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/acceptance_test.py +60 -6
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/application.py +274 -49
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/batch_experiment.py +7 -1
- nextmv-0.33.0.dev0/nextmv/cloud/ensemble.py +248 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/README.md +17 -2
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/app.yaml +1 -2
- nextmv-0.33.0.dev0/nextmv/default_app/input.json +5 -0
- nextmv-0.33.0.dev0/nextmv/default_app/main.py +37 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/input.py +2 -8
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/application.py +250 -224
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/executor.py +9 -13
- nextmv-0.33.0.dev0/nextmv/local/local.py +97 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/runner.py +3 -41
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/output.py +6 -26
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/run.py +476 -108
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/local/test_application.py +2 -1
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/local/test_executor.py +1 -5
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/local/test_runner.py +3 -2
- nextmv-0.33.0.dev0/tests/test_run.py +208 -0
- nextmv-0.31.0/nextmv/__about__.py +0 -1
- nextmv-0.31.0/tests/test_run.py +0 -18
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/.gitignore +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/LICENSE +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/README.md +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/__entrypoint__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/_serialization.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/base_model.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/account.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/client.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/input_set.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/instance.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/package.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/scenario.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/secrets.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/url.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/cloud/version.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/.gitignore +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/requirements.txt +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/src/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/src/main.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/default_app/src/visuals.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/deprecated.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/geojson_handler.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/local/plotly_handler.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/logger.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/manifest.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/model.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/options.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/polling.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/safe.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/nextmv/status.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/pyproject.toml +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/cloud/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/cloud/app.yaml +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/cloud/test_client.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/cloud/test_package.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/cloud/test_scenario.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/local/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options1.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options2.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options3.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options4.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options5.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options6.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options7.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/scripts/options_deprecated.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_base_model.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_entrypoint/__init__.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_entrypoint/test_entrypoint.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_input.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_inputs/test_data.csv +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_inputs/test_data.json +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_inputs/test_data.txt +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_logger.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_manifest.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_model.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_options.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_output.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_polling.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_safe.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_serialization.py +0 -0
- {nextmv-0.31.0 → nextmv-0.33.0.dev0}/tests/test_version.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "v0.33.0.dev0"
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
from .__about__ import __version__
|
|
4
4
|
from .base_model import BaseModel as BaseModel
|
|
5
5
|
from .base_model import from_dict as from_dict
|
|
6
|
-
from .input import DEFAULT_INPUT_JSON_FILE as DEFAULT_INPUT_JSON_FILE
|
|
7
|
-
from .input import INPUTS_KEY as INPUTS_KEY
|
|
8
6
|
from .input import DataFile as DataFile
|
|
9
7
|
from .input import Input as Input
|
|
10
8
|
from .input import InputFormat as InputFormat
|
|
@@ -31,13 +29,6 @@ from .model import ModelConfiguration as ModelConfiguration
|
|
|
31
29
|
from .options import Option as Option
|
|
32
30
|
from .options import Options as Options
|
|
33
31
|
from .options import Parameter as Parameter
|
|
34
|
-
from .output import ASSETS_KEY as ASSETS_KEY
|
|
35
|
-
from .output import DEFAULT_OUTPUT_JSON_FILE as DEFAULT_OUTPUT_JSON_FILE
|
|
36
|
-
from .output import LOGS_FILE as LOGS_FILE
|
|
37
|
-
from .output import LOGS_KEY as LOGS_KEY
|
|
38
|
-
from .output import OUTPUTS_KEY as OUTPUTS_KEY
|
|
39
|
-
from .output import SOLUTIONS_KEY as SOLUTIONS_KEY
|
|
40
|
-
from .output import STATISTICS_KEY as STATISTICS_KEY
|
|
41
32
|
from .output import Asset as Asset
|
|
42
33
|
from .output import DataPoint as DataPoint
|
|
43
34
|
from .output import LocalOutputWriter as LocalOutputWriter
|
|
@@ -66,13 +57,17 @@ from .run import Format as Format
|
|
|
66
57
|
from .run import FormatInput as FormatInput
|
|
67
58
|
from .run import FormatOutput as FormatOutput
|
|
68
59
|
from .run import Metadata as Metadata
|
|
60
|
+
from .run import OptionsSummaryItem as OptionsSummaryItem
|
|
61
|
+
from .run import Run as Run
|
|
69
62
|
from .run import RunConfiguration as RunConfiguration
|
|
70
63
|
from .run import RunInformation as RunInformation
|
|
64
|
+
from .run import RunInfoStatistics as RunInfoStatistics
|
|
71
65
|
from .run import RunLog as RunLog
|
|
72
66
|
from .run import RunQueuing as RunQueuing
|
|
73
67
|
from .run import RunResult as RunResult
|
|
74
68
|
from .run import RunType as RunType
|
|
75
69
|
from .run import RunTypeConfiguration as RunTypeConfiguration
|
|
70
|
+
from .run import StatisticsIndicator as StatisticsIndicator
|
|
76
71
|
from .run import TrackedRun as TrackedRun
|
|
77
72
|
from .run import TrackedRunStatus as TrackedRunStatus
|
|
78
73
|
from .run import run_duration as run_duration
|
|
@@ -47,6 +47,7 @@ from .acceptance_test import MetricParams as MetricParams
|
|
|
47
47
|
from .acceptance_test import MetricResult as MetricResult
|
|
48
48
|
from .acceptance_test import MetricStatistics as MetricStatistics
|
|
49
49
|
from .acceptance_test import MetricTolerance as MetricTolerance
|
|
50
|
+
from .acceptance_test import MetricToleranceType as MetricToleranceType
|
|
50
51
|
from .acceptance_test import MetricType as MetricType
|
|
51
52
|
from .acceptance_test import ResultStatistics as ResultStatistics
|
|
52
53
|
from .acceptance_test import StatisticType as StatisticType
|
|
@@ -63,6 +64,12 @@ from .batch_experiment import BatchExperimentRun as BatchExperimentRun
|
|
|
63
64
|
from .batch_experiment import ExperimentStatus as ExperimentStatus
|
|
64
65
|
from .client import Client as Client
|
|
65
66
|
from .client import get_size as get_size
|
|
67
|
+
from .ensemble import EnsembleDefinition as EnsembleDefinition
|
|
68
|
+
from .ensemble import EvaluationRule as EvaluationRule
|
|
69
|
+
from .ensemble import RuleObjective as RuleObjective
|
|
70
|
+
from .ensemble import RuleTolerance as RuleTolerance
|
|
71
|
+
from .ensemble import RuleToleranceType as RuleToleranceType
|
|
72
|
+
from .ensemble import RunGroup as RunGroup
|
|
66
73
|
from .input_set import InputSet as InputSet
|
|
67
74
|
from .input_set import ManagedInput as ManagedInput
|
|
68
75
|
from .instance import Instance as Instance
|
|
@@ -47,6 +47,7 @@ from typing import Optional
|
|
|
47
47
|
|
|
48
48
|
from nextmv.base_model import BaseModel
|
|
49
49
|
from nextmv.cloud.batch_experiment import ExperimentStatus
|
|
50
|
+
from nextmv.deprecated import deprecated
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
class MetricType(str, Enum):
|
|
@@ -214,6 +215,9 @@ class Comparison(str, Enum):
|
|
|
214
215
|
|
|
215
216
|
class ToleranceType(str, Enum):
|
|
216
217
|
"""
|
|
218
|
+
!!! warning
|
|
219
|
+
`ToleranceType` is deprecated, use `MetricToleranceType` instead.
|
|
220
|
+
|
|
217
221
|
Type of tolerance used for a metric.
|
|
218
222
|
|
|
219
223
|
You can import the `ToleranceType` class directly from `cloud`:
|
|
@@ -242,6 +246,57 @@ class ToleranceType(str, Enum):
|
|
|
242
246
|
<ToleranceType.absolute: 'absolute'>
|
|
243
247
|
"""
|
|
244
248
|
|
|
249
|
+
undefined = ""
|
|
250
|
+
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
251
|
+
Undefined tolerance type."""
|
|
252
|
+
absolute = "absolute"
|
|
253
|
+
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
254
|
+
Absolute tolerance type."""
|
|
255
|
+
relative = "relative"
|
|
256
|
+
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
257
|
+
Relative tolerance type."""
|
|
258
|
+
|
|
259
|
+
def __new__(cls, value: str):
|
|
260
|
+
"""Create a new ToleranceType instance and emit deprecation warning."""
|
|
261
|
+
deprecated(
|
|
262
|
+
"ToleranceType",
|
|
263
|
+
"ToleranceType is deprecated and will be removed in a future version. "
|
|
264
|
+
"Please use MetricToleranceType instead",
|
|
265
|
+
)
|
|
266
|
+
obj = str.__new__(cls, value)
|
|
267
|
+
obj._value_ = value
|
|
268
|
+
return obj
|
|
269
|
+
|
|
270
|
+
class MetricToleranceType(str, Enum):
|
|
271
|
+
"""
|
|
272
|
+
Type of tolerance used for a metric.
|
|
273
|
+
|
|
274
|
+
You can import the `MetricToleranceType` class directly from `cloud`:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from nextmv.cloud import MetricToleranceType
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
This enumeration defines the different types of tolerances that can be used
|
|
281
|
+
when comparing metrics in acceptance tests.
|
|
282
|
+
|
|
283
|
+
Attributes
|
|
284
|
+
----------
|
|
285
|
+
undefined : str
|
|
286
|
+
Undefined tolerance type (empty string).
|
|
287
|
+
absolute : str
|
|
288
|
+
Absolute tolerance type, using a fixed value.
|
|
289
|
+
relative : str
|
|
290
|
+
Relative tolerance type, using a percentage.
|
|
291
|
+
|
|
292
|
+
Examples
|
|
293
|
+
--------
|
|
294
|
+
>>> from nextmv.cloud import MetricToleranceType
|
|
295
|
+
>>> tol_type = MetricToleranceType.absolute
|
|
296
|
+
>>> tol_type
|
|
297
|
+
<MetricToleranceType.absolute: 'absolute'>
|
|
298
|
+
"""
|
|
299
|
+
|
|
245
300
|
undefined = ""
|
|
246
301
|
"""Undefined tolerance type."""
|
|
247
302
|
absolute = "absolute"
|
|
@@ -249,7 +304,6 @@ class ToleranceType(str, Enum):
|
|
|
249
304
|
relative = "relative"
|
|
250
305
|
"""Relative tolerance type."""
|
|
251
306
|
|
|
252
|
-
|
|
253
307
|
class MetricTolerance(BaseModel):
|
|
254
308
|
"""
|
|
255
309
|
Tolerance used for a metric in an acceptance test.
|
|
@@ -265,22 +319,22 @@ class MetricTolerance(BaseModel):
|
|
|
265
319
|
|
|
266
320
|
Attributes
|
|
267
321
|
----------
|
|
268
|
-
type :
|
|
322
|
+
type : MetricToleranceType
|
|
269
323
|
Type of tolerance (absolute or relative).
|
|
270
324
|
value : float
|
|
271
325
|
Value of the tolerance.
|
|
272
326
|
|
|
273
327
|
Examples
|
|
274
328
|
--------
|
|
275
|
-
>>> from nextmv.cloud import MetricTolerance,
|
|
276
|
-
>>> tolerance = MetricTolerance(type=
|
|
329
|
+
>>> from nextmv.cloud import MetricTolerance, MetricToleranceType
|
|
330
|
+
>>> tolerance = MetricTolerance(type=MetricToleranceType.absolute, value=0.1)
|
|
277
331
|
>>> tolerance.type
|
|
278
|
-
<
|
|
332
|
+
<MetricToleranceType.absolute: 'absolute'>
|
|
279
333
|
>>> tolerance.value
|
|
280
334
|
0.1
|
|
281
335
|
"""
|
|
282
336
|
|
|
283
|
-
type:
|
|
337
|
+
type: MetricToleranceType
|
|
284
338
|
"""Type of tolerance."""
|
|
285
339
|
value: float
|
|
286
340
|
"""Value of the tolerance."""
|
|
@@ -46,6 +46,11 @@ from nextmv.cloud.batch_experiment import (
|
|
|
46
46
|
to_runs,
|
|
47
47
|
)
|
|
48
48
|
from nextmv.cloud.client import Client, get_size
|
|
49
|
+
from nextmv.cloud.ensemble import (
|
|
50
|
+
EnsembleDefinition,
|
|
51
|
+
EvaluationRule,
|
|
52
|
+
RunGroup,
|
|
53
|
+
)
|
|
49
54
|
from nextmv.cloud.input_set import InputSet, ManagedInput
|
|
50
55
|
from nextmv.cloud.instance import Instance, InstanceConfiguration
|
|
51
56
|
from nextmv.cloud.scenario import Scenario, ScenarioInputType, _option_sets, _scenarios_by_id
|
|
@@ -64,6 +69,7 @@ from nextmv.run import (
|
|
|
64
69
|
Format,
|
|
65
70
|
FormatInput,
|
|
66
71
|
FormatOutput,
|
|
72
|
+
Run,
|
|
67
73
|
RunConfiguration,
|
|
68
74
|
RunInformation,
|
|
69
75
|
RunLog,
|
|
@@ -128,6 +134,8 @@ class Application:
|
|
|
128
134
|
"""Base endpoint for the application."""
|
|
129
135
|
experiments_endpoint: str = "{base}/experiments"
|
|
130
136
|
"""Base endpoint for the experiments in the application."""
|
|
137
|
+
ensembles_endpoint: str = "{base}/ensembles"
|
|
138
|
+
"""Base endpoint for managing the ensemble definitions in the application"""
|
|
131
139
|
|
|
132
140
|
def __post_init__(self):
|
|
133
141
|
"""Initialize the endpoint and experiments_endpoint attributes.
|
|
@@ -137,6 +145,7 @@ class Application:
|
|
|
137
145
|
"""
|
|
138
146
|
self.endpoint = self.endpoint.format(id=self.id)
|
|
139
147
|
self.experiments_endpoint = self.experiments_endpoint.format(base=self.endpoint)
|
|
148
|
+
self.ensembles_endpoint = self.ensembles_endpoint.format(base=self.endpoint)
|
|
140
149
|
|
|
141
150
|
@classmethod
|
|
142
151
|
def new(
|
|
@@ -289,7 +298,8 @@ class Application:
|
|
|
289
298
|
|
|
290
299
|
def batch_experiment(self, batch_id: str) -> BatchExperiment:
|
|
291
300
|
"""
|
|
292
|
-
Get a batch experiment.
|
|
301
|
+
Get a batch experiment. This method also returns the runs of the batch
|
|
302
|
+
experiment under the `.runs` attribute.
|
|
293
303
|
|
|
294
304
|
Parameters
|
|
295
305
|
----------
|
|
@@ -318,7 +328,17 @@ class Application:
|
|
|
318
328
|
endpoint=f"{self.experiments_endpoint}/batch/{batch_id}",
|
|
319
329
|
)
|
|
320
330
|
|
|
321
|
-
|
|
331
|
+
exp = BatchExperiment.from_dict(response.json())
|
|
332
|
+
|
|
333
|
+
runs_response = self.client.request(
|
|
334
|
+
method="GET",
|
|
335
|
+
endpoint=f"{self.experiments_endpoint}/batch/{batch_id}/runs",
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
runs = [Run.from_dict(run) for run in runs_response.json().get("runs", [])]
|
|
339
|
+
exp.runs = runs
|
|
340
|
+
|
|
341
|
+
return exp
|
|
322
342
|
|
|
323
343
|
def batch_experiment_metadata(self, batch_id: str) -> BatchExperimentMetadata:
|
|
324
344
|
"""
|
|
@@ -503,6 +523,30 @@ class Application:
|
|
|
503
523
|
endpoint=f"{self.experiments_endpoint}/batch/{batch_id}",
|
|
504
524
|
)
|
|
505
525
|
|
|
526
|
+
def delete_ensemble_definition(self, ensemble_definition_id: str) -> None:
|
|
527
|
+
"""
|
|
528
|
+
Delete an ensemble definition.
|
|
529
|
+
|
|
530
|
+
Parameters
|
|
531
|
+
----------
|
|
532
|
+
ensemble_definition_id : str
|
|
533
|
+
ID of the ensemble definition to delete.
|
|
534
|
+
|
|
535
|
+
Raises
|
|
536
|
+
------
|
|
537
|
+
requests.HTTPError
|
|
538
|
+
If the response status code is not 2xx.
|
|
539
|
+
|
|
540
|
+
Examples
|
|
541
|
+
--------
|
|
542
|
+
>>> app.delete_ensemble_definition("development-ensemble-definition")
|
|
543
|
+
"""
|
|
544
|
+
|
|
545
|
+
_ = self.client.request(
|
|
546
|
+
method="DELETE",
|
|
547
|
+
endpoint=f"{self.ensembles_endpoint}/{ensemble_definition_id}",
|
|
548
|
+
)
|
|
549
|
+
|
|
506
550
|
def delete_scenario_test(self, scenario_test_id: str) -> None:
|
|
507
551
|
"""
|
|
508
552
|
Delete a scenario test.
|
|
@@ -551,6 +595,39 @@ class Application:
|
|
|
551
595
|
endpoint=f"{self.endpoint}/secrets/{secrets_collection_id}",
|
|
552
596
|
)
|
|
553
597
|
|
|
598
|
+
def ensemble_definition(self, ensemble_definition_id: str) -> EnsembleDefinition:
|
|
599
|
+
"""
|
|
600
|
+
Get an ensemble definition.
|
|
601
|
+
|
|
602
|
+
Parameters
|
|
603
|
+
----------
|
|
604
|
+
ensemble_definition_id : str
|
|
605
|
+
ID of the ensemble definition to retrieve.
|
|
606
|
+
|
|
607
|
+
Returns
|
|
608
|
+
-------
|
|
609
|
+
EnsembleDefintion
|
|
610
|
+
The requested ensemble definition details.
|
|
611
|
+
|
|
612
|
+
Raises
|
|
613
|
+
------
|
|
614
|
+
requests.HTTPError
|
|
615
|
+
If the response status code is not 2xx.
|
|
616
|
+
|
|
617
|
+
Examples
|
|
618
|
+
--------
|
|
619
|
+
>>> ensemble_definition = app.ensemble_definition("instance-123")
|
|
620
|
+
>>> print(ensemble_definition.name)
|
|
621
|
+
'Production Ensemble Definition'
|
|
622
|
+
"""
|
|
623
|
+
|
|
624
|
+
response = self.client.request(
|
|
625
|
+
method="GET",
|
|
626
|
+
endpoint=f"{self.ensembles_endpoint}/{ensemble_definition_id}",
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
630
|
+
|
|
554
631
|
@staticmethod
|
|
555
632
|
def exists(client: Client, id: str) -> bool:
|
|
556
633
|
"""
|
|
@@ -736,6 +813,36 @@ class Application:
|
|
|
736
813
|
|
|
737
814
|
return [BatchExperimentMetadata.from_dict(batch_experiment) for batch_experiment in response.json()]
|
|
738
815
|
|
|
816
|
+
def list_ensemble_definitions(self) -> list[EnsembleDefinition]:
|
|
817
|
+
"""
|
|
818
|
+
List all ensemble_definitions.
|
|
819
|
+
|
|
820
|
+
Returns
|
|
821
|
+
-------
|
|
822
|
+
list[EnsembleDefinition]
|
|
823
|
+
List of all ensemble definitions associated with this application.
|
|
824
|
+
|
|
825
|
+
Raises
|
|
826
|
+
------
|
|
827
|
+
requests.HTTPError
|
|
828
|
+
If the response status code is not 2xx.
|
|
829
|
+
|
|
830
|
+
Examples
|
|
831
|
+
--------
|
|
832
|
+
>>> ensemble_definitions = app.list_ensemble_definitions()
|
|
833
|
+
>>> for ensemble_definition in ensemble_definitions:
|
|
834
|
+
... print(ensemble_definition.name)
|
|
835
|
+
'Development Ensemble Definition'
|
|
836
|
+
'Production Ensemble Definition'
|
|
837
|
+
"""
|
|
838
|
+
|
|
839
|
+
response = self.client.request(
|
|
840
|
+
method="GET",
|
|
841
|
+
endpoint=f"{self.ensembles_endpoint}",
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
return [EnsembleDefinition.from_dict(ensemble_definition) for ensemble_definition in response.json()["items"]]
|
|
845
|
+
|
|
739
846
|
def list_input_sets(self) -> list[InputSet]:
|
|
740
847
|
"""
|
|
741
848
|
List all input sets.
|
|
@@ -818,6 +925,28 @@ class Application:
|
|
|
818
925
|
|
|
819
926
|
return [ManagedInput.from_dict(managed_input) for managed_input in response.json()]
|
|
820
927
|
|
|
928
|
+
def list_runs(self) -> list[Run]:
|
|
929
|
+
"""
|
|
930
|
+
List all runs.
|
|
931
|
+
|
|
932
|
+
Returns
|
|
933
|
+
-------
|
|
934
|
+
list[Run]
|
|
935
|
+
List of runs.
|
|
936
|
+
|
|
937
|
+
Raises
|
|
938
|
+
------
|
|
939
|
+
requests.HTTPError
|
|
940
|
+
If the response status code is not 2xx.
|
|
941
|
+
"""
|
|
942
|
+
|
|
943
|
+
response = self.client.request(
|
|
944
|
+
method="GET",
|
|
945
|
+
endpoint=f"{self.endpoint}/runs",
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
return [Run.from_dict(run) for run in response.json().get("runs", [])]
|
|
949
|
+
|
|
821
950
|
def list_scenario_tests(self) -> list[BatchExperimentMetadata]:
|
|
822
951
|
"""
|
|
823
952
|
List all batch scenario tests. Scenario tests are based on the batch
|
|
@@ -1280,6 +1409,53 @@ class Application:
|
|
|
1280
1409
|
|
|
1281
1410
|
return self.batch_experiment_with_polling(batch_id=batch_id, polling_options=polling_options)
|
|
1282
1411
|
|
|
1412
|
+
def new_ensemble_defintion(
|
|
1413
|
+
self,
|
|
1414
|
+
id: str,
|
|
1415
|
+
run_groups: list[RunGroup],
|
|
1416
|
+
rules: list[EvaluationRule],
|
|
1417
|
+
name: Optional[str] = None,
|
|
1418
|
+
description: Optional[str] = None,
|
|
1419
|
+
) -> EnsembleDefinition:
|
|
1420
|
+
"""
|
|
1421
|
+
Create a new ensemble definition.
|
|
1422
|
+
|
|
1423
|
+
Parameters
|
|
1424
|
+
----------
|
|
1425
|
+
id: str
|
|
1426
|
+
ID of the ensemble defintion.
|
|
1427
|
+
run_groups: list[RunGroup]
|
|
1428
|
+
Information to facilitate the execution of child runs.
|
|
1429
|
+
rules: list[EvaluationRule]
|
|
1430
|
+
Information to facilitate the selection of
|
|
1431
|
+
a result for the ensemble run from child runs.
|
|
1432
|
+
name: Optional[str]
|
|
1433
|
+
Name of the ensemble definition.
|
|
1434
|
+
description: Optional[str]
|
|
1435
|
+
Description of the ensemble definition.
|
|
1436
|
+
"""
|
|
1437
|
+
|
|
1438
|
+
if name is None:
|
|
1439
|
+
name = id
|
|
1440
|
+
if description is None:
|
|
1441
|
+
description = name
|
|
1442
|
+
|
|
1443
|
+
payload = {
|
|
1444
|
+
"id": id,
|
|
1445
|
+
"run_groups": [run_group.to_dict() for run_group in run_groups],
|
|
1446
|
+
"rules": [rule.to_dict() for rule in rules],
|
|
1447
|
+
"name": name,
|
|
1448
|
+
"description": description,
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
response = self.client.request(
|
|
1452
|
+
method="POST",
|
|
1453
|
+
endpoint=f"{self.ensembles_endpoint}",
|
|
1454
|
+
payload=payload,
|
|
1455
|
+
)
|
|
1456
|
+
|
|
1457
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
1458
|
+
|
|
1283
1459
|
def new_input_set(
|
|
1284
1460
|
self,
|
|
1285
1461
|
id: str,
|
|
@@ -2202,13 +2378,14 @@ class Application:
|
|
|
2202
2378
|
|
|
2203
2379
|
if id is None:
|
|
2204
2380
|
id = safe_id(prefix="version")
|
|
2381
|
+
if name is None:
|
|
2382
|
+
name = id
|
|
2205
2383
|
|
|
2206
2384
|
payload = {
|
|
2207
2385
|
"id": id,
|
|
2386
|
+
"name": name,
|
|
2208
2387
|
}
|
|
2209
2388
|
|
|
2210
|
-
if name is not None:
|
|
2211
|
-
payload["name"] = name
|
|
2212
2389
|
if description is not None:
|
|
2213
2390
|
payload["description"] = description
|
|
2214
2391
|
|
|
@@ -2759,7 +2936,7 @@ class Application:
|
|
|
2759
2936
|
Examples
|
|
2760
2937
|
--------
|
|
2761
2938
|
>>> from nextmv.cloud import Application
|
|
2762
|
-
>>> from nextmv
|
|
2939
|
+
>>> from nextmv import TrackedRun
|
|
2763
2940
|
>>> app = Application(id="app_123")
|
|
2764
2941
|
>>> tracked_run = TrackedRun(input={"data": [...]}, output={"solution": [...]})
|
|
2765
2942
|
>>> run_id = app.track_run(tracked_run)
|
|
@@ -2900,6 +3077,98 @@ class Application:
|
|
|
2900
3077
|
output_dir_path=output_dir_path,
|
|
2901
3078
|
)
|
|
2902
3079
|
|
|
3080
|
+
def update_batch_experiment(
|
|
3081
|
+
self,
|
|
3082
|
+
batch_experiment_id: str,
|
|
3083
|
+
name: Optional[str] = None,
|
|
3084
|
+
description: Optional[str] = None,
|
|
3085
|
+
) -> BatchExperimentInformation:
|
|
3086
|
+
"""
|
|
3087
|
+
Update a batch experiment.
|
|
3088
|
+
|
|
3089
|
+
Parameters
|
|
3090
|
+
----------
|
|
3091
|
+
batch_experiment_id : str
|
|
3092
|
+
ID of the batch experiment to update.
|
|
3093
|
+
name : Optional[str], default=None
|
|
3094
|
+
Optional name of the batch experiment.
|
|
3095
|
+
description : Optional[str], default=None
|
|
3096
|
+
Optional description of the batch experiment.
|
|
3097
|
+
|
|
3098
|
+
Returns
|
|
3099
|
+
-------
|
|
3100
|
+
BatchExperimentInformation
|
|
3101
|
+
The information with the updated batch experiment.
|
|
3102
|
+
|
|
3103
|
+
Raises
|
|
3104
|
+
------
|
|
3105
|
+
requests.HTTPError
|
|
3106
|
+
If the response status code is not 2xx.
|
|
3107
|
+
"""
|
|
3108
|
+
|
|
3109
|
+
payload = {}
|
|
3110
|
+
|
|
3111
|
+
if name is not None:
|
|
3112
|
+
payload["name"] = name
|
|
3113
|
+
if description is not None:
|
|
3114
|
+
payload["description"] = description
|
|
3115
|
+
|
|
3116
|
+
response = self.client.request(
|
|
3117
|
+
method="PATCH",
|
|
3118
|
+
endpoint=f"{self.experiments_endpoint}/batch/{batch_experiment_id}",
|
|
3119
|
+
payload=payload,
|
|
3120
|
+
)
|
|
3121
|
+
|
|
3122
|
+
return BatchExperimentInformation.from_dict(response.json())
|
|
3123
|
+
|
|
3124
|
+
def update_ensemble_definition(
|
|
3125
|
+
self,
|
|
3126
|
+
id: str,
|
|
3127
|
+
name: Optional[str] = None,
|
|
3128
|
+
description: Optional[str] = None,
|
|
3129
|
+
) -> EnsembleDefinition:
|
|
3130
|
+
"""
|
|
3131
|
+
Update an ensemble definition.
|
|
3132
|
+
|
|
3133
|
+
Parameters
|
|
3134
|
+
----------
|
|
3135
|
+
id : str
|
|
3136
|
+
ID of the ensemble definition to update.
|
|
3137
|
+
name : Optional[str], default=None
|
|
3138
|
+
Optional name of the ensemble definition.
|
|
3139
|
+
description : Optional[str], default=None
|
|
3140
|
+
Optional description of the ensemble definition.
|
|
3141
|
+
|
|
3142
|
+
Returns
|
|
3143
|
+
-------
|
|
3144
|
+
EnsembleDefinition
|
|
3145
|
+
The updated ensemble definition.
|
|
3146
|
+
|
|
3147
|
+
Raises
|
|
3148
|
+
------
|
|
3149
|
+
ValueError
|
|
3150
|
+
If neither name nor description is updated
|
|
3151
|
+
requests.HTTPError
|
|
3152
|
+
If the response status code is not 2xx.
|
|
3153
|
+
"""
|
|
3154
|
+
|
|
3155
|
+
payload = {}
|
|
3156
|
+
|
|
3157
|
+
if name is None and description is None:
|
|
3158
|
+
raise ValueError("Must define at least one value among name and description to modify")
|
|
3159
|
+
if name is not None:
|
|
3160
|
+
payload["name"] = name
|
|
3161
|
+
if description is not None:
|
|
3162
|
+
payload["description"] = description
|
|
3163
|
+
|
|
3164
|
+
response = self.client.request(
|
|
3165
|
+
method="PATCH",
|
|
3166
|
+
endpoint=f"{self.ensembles_endpoint}/{id}",
|
|
3167
|
+
payload=payload,
|
|
3168
|
+
)
|
|
3169
|
+
|
|
3170
|
+
return EnsembleDefinition.from_dict(response.json())
|
|
3171
|
+
|
|
2903
3172
|
def update_instance(
|
|
2904
3173
|
self,
|
|
2905
3174
|
id: str,
|
|
@@ -2963,50 +3232,6 @@ class Application:
|
|
|
2963
3232
|
|
|
2964
3233
|
return Instance.from_dict(response.json())
|
|
2965
3234
|
|
|
2966
|
-
def update_batch_experiment(
|
|
2967
|
-
self,
|
|
2968
|
-
batch_experiment_id: str,
|
|
2969
|
-
name: Optional[str] = None,
|
|
2970
|
-
description: Optional[str] = None,
|
|
2971
|
-
) -> BatchExperimentInformation:
|
|
2972
|
-
"""
|
|
2973
|
-
Update a batch experiment.
|
|
2974
|
-
|
|
2975
|
-
Parameters
|
|
2976
|
-
----------
|
|
2977
|
-
batch_experiment_id : str
|
|
2978
|
-
ID of the batch experiment to update.
|
|
2979
|
-
name : Optional[str], default=None
|
|
2980
|
-
Optional name of the batch experiment.
|
|
2981
|
-
description : Optional[str], default=None
|
|
2982
|
-
Optional description of the batch experiment.
|
|
2983
|
-
|
|
2984
|
-
Returns
|
|
2985
|
-
-------
|
|
2986
|
-
BatchExperimentInformation
|
|
2987
|
-
The information with the updated batch experiment.
|
|
2988
|
-
|
|
2989
|
-
Raises
|
|
2990
|
-
------
|
|
2991
|
-
requests.HTTPError
|
|
2992
|
-
If the response status code is not 2xx.
|
|
2993
|
-
"""
|
|
2994
|
-
|
|
2995
|
-
payload = {}
|
|
2996
|
-
|
|
2997
|
-
if name is not None:
|
|
2998
|
-
payload["name"] = name
|
|
2999
|
-
if description is not None:
|
|
3000
|
-
payload["description"] = description
|
|
3001
|
-
|
|
3002
|
-
response = self.client.request(
|
|
3003
|
-
method="PATCH",
|
|
3004
|
-
endpoint=f"{self.experiments_endpoint}/batch/{batch_experiment_id}",
|
|
3005
|
-
payload=payload,
|
|
3006
|
-
)
|
|
3007
|
-
|
|
3008
|
-
return BatchExperimentInformation.from_dict(response.json())
|
|
3009
|
-
|
|
3010
3235
|
def update_managed_input(
|
|
3011
3236
|
self,
|
|
3012
3237
|
managed_input_id: str,
|
|
@@ -21,6 +21,7 @@ from typing import Any, Optional
|
|
|
21
21
|
|
|
22
22
|
from nextmv.base_model import BaseModel
|
|
23
23
|
from nextmv.cloud.input_set import InputSet
|
|
24
|
+
from nextmv.run import Run
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class ExperimentStatus(str, Enum):
|
|
@@ -191,7 +192,10 @@ class BatchExperiment(BatchExperimentInformation):
|
|
|
191
192
|
instance_ids : list[str]
|
|
192
193
|
List of instance IDs used for the experiment.
|
|
193
194
|
grouped_distributional_summaries : list[dict[str, Any]], optional
|
|
194
|
-
Grouped distributional summaries of the batch experiment. Defaults to
|
|
195
|
+
Grouped distributional summaries of the batch experiment. Defaults to
|
|
196
|
+
None.
|
|
197
|
+
runs : list[Run], optional
|
|
198
|
+
List of runs in the batch experiment. Defaults to None.
|
|
195
199
|
"""
|
|
196
200
|
|
|
197
201
|
input_set_id: str
|
|
@@ -200,6 +204,8 @@ class BatchExperiment(BatchExperimentInformation):
|
|
|
200
204
|
"""List of instance IDs used for the experiment."""
|
|
201
205
|
grouped_distributional_summaries: Optional[list[dict[str, Any]]] = None
|
|
202
206
|
"""Grouped distributional summaries of the batch experiment."""
|
|
207
|
+
runs: Optional[list[Run]] = None
|
|
208
|
+
"""List of runs in the batch experiment."""
|
|
203
209
|
|
|
204
210
|
|
|
205
211
|
class BatchExperimentRun(BaseModel):
|