nextmv 1.0.0.dev6__py3-none-any.whl → 1.0.0.dev8__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/_serialization.py +1 -1
- nextmv/cli/cloud/acceptance/create.py +12 -12
- nextmv/cli/cloud/app/push.py +15 -15
- nextmv/cli/cloud/input_set/__init__.py +0 -2
- nextmv/cli/cloud/run/create.py +9 -4
- nextmv/cli/cloud/shadow/stop.py +2 -14
- nextmv/cli/cloud/switchback/stop.py +2 -14
- nextmv/cli/community/clone.py +197 -11
- nextmv/cli/community/list.py +116 -46
- nextmv/cloud/__init__.py +0 -4
- nextmv/cloud/application/__init__.py +200 -1
- nextmv/cloud/application/_input_set.py +6 -42
- nextmv/cloud/application/_run.py +8 -1
- nextmv/cloud/application/_shadow.py +3 -9
- nextmv/cloud/application/_switchback.py +1 -10
- nextmv/cloud/batch_experiment.py +1 -3
- nextmv/cloud/client.py +1 -1
- nextmv/cloud/shadow.py +0 -25
- nextmv/default_app/main.py +4 -6
- nextmv/local/executor.py +83 -3
- nextmv/local/geojson_handler.py +1 -1
- nextmv/manifest.py +11 -7
- nextmv/model.py +2 -2
- nextmv/options.py +1 -1
- nextmv/output.py +57 -21
- nextmv/run.py +12 -3
- {nextmv-1.0.0.dev6.dist-info → nextmv-1.0.0.dev8.dist-info}/METADATA +1 -3
- {nextmv-1.0.0.dev6.dist-info → nextmv-1.0.0.dev8.dist-info}/RECORD +32 -34
- nextmv/cli/cloud/input_set/delete.py +0 -67
- nextmv/cloud/community.py +0 -441
- {nextmv-1.0.0.dev6.dist-info → nextmv-1.0.0.dev8.dist-info}/WHEEL +0 -0
- {nextmv-1.0.0.dev6.dist-info → nextmv-1.0.0.dev8.dist-info}/entry_points.txt +0 -0
- {nextmv-1.0.0.dev6.dist-info → nextmv-1.0.0.dev8.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,7 +5,6 @@ Application mixin for managing switchback tests.
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from nextmv.cloud.shadow import StopIntent
|
|
9
8
|
from nextmv.cloud.switchback import SwitchbackTest, SwitchbackTestMetadata, TestComparisonSingle
|
|
10
9
|
from nextmv.run import Run
|
|
11
10
|
from nextmv.safe import safe_id
|
|
@@ -258,7 +257,7 @@ class ApplicationSwitchbackMixin:
|
|
|
258
257
|
endpoint=f"{self.experiments_endpoint}/switchback/{switchback_test_id}/start",
|
|
259
258
|
)
|
|
260
259
|
|
|
261
|
-
def stop_switchback_test(self: "Application", switchback_test_id: str
|
|
260
|
+
def stop_switchback_test(self: "Application", switchback_test_id: str) -> None:
|
|
262
261
|
"""
|
|
263
262
|
Stop a switchback test. The test should already have started before using
|
|
264
263
|
this method.
|
|
@@ -268,23 +267,15 @@ class ApplicationSwitchbackMixin:
|
|
|
268
267
|
switchback_test_id : str
|
|
269
268
|
ID of the switchback test to stop.
|
|
270
269
|
|
|
271
|
-
intent : StopIntent
|
|
272
|
-
Intent for stopping the switchback test.
|
|
273
|
-
|
|
274
270
|
Raises
|
|
275
271
|
------
|
|
276
272
|
requests.HTTPError
|
|
277
273
|
If the response status code is not 2xx.
|
|
278
274
|
"""
|
|
279
275
|
|
|
280
|
-
payload = {
|
|
281
|
-
"intent": intent.value,
|
|
282
|
-
}
|
|
283
|
-
|
|
284
276
|
_ = self.client.request(
|
|
285
277
|
method="PUT",
|
|
286
278
|
endpoint=f"{self.experiments_endpoint}/switchback/{switchback_test_id}/stop",
|
|
287
|
-
payload=payload,
|
|
288
279
|
)
|
|
289
280
|
|
|
290
281
|
def update_switchback_test(
|
nextmv/cloud/batch_experiment.py
CHANGED
|
@@ -30,9 +30,7 @@ class ExperimentStatus(str, Enum):
|
|
|
30
30
|
|
|
31
31
|
You can import the `ExperimentStatus` class directly from `cloud`:
|
|
32
32
|
|
|
33
|
-
```python
|
|
34
|
-
from nextmv.cloud import ExperimentStatus
|
|
35
|
-
```
|
|
33
|
+
```python from nextmv.cloud import ExperimentStatus ```
|
|
36
34
|
|
|
37
35
|
This enum represents the comprehensive set of possible states for an
|
|
38
36
|
experiment in Nextmv Cloud.
|
nextmv/cloud/client.py
CHANGED
|
@@ -303,7 +303,7 @@ class Client:
|
|
|
303
303
|
if data is not None:
|
|
304
304
|
kwargs["data"] = data
|
|
305
305
|
if payload is not None:
|
|
306
|
-
if isinstance(payload,
|
|
306
|
+
if isinstance(payload, dict | list):
|
|
307
307
|
data = deflated_serialize_json(payload, json_configurations=json_configurations)
|
|
308
308
|
kwargs["data"] = data
|
|
309
309
|
else:
|
nextmv/cloud/shadow.py
CHANGED
|
@@ -19,7 +19,6 @@ ShadowTest
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from datetime import datetime
|
|
22
|
-
from enum import Enum
|
|
23
22
|
from typing import Any
|
|
24
23
|
|
|
25
24
|
from pydantic import AliasChoices, Field
|
|
@@ -228,27 +227,3 @@ class ShadowTest(BaseModel):
|
|
|
228
227
|
"""Grouped distributional summaries of the shadow test."""
|
|
229
228
|
runs: list[Run] | None = None
|
|
230
229
|
"""List of runs in the shadow test."""
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
class StopIntent(str, Enum):
|
|
234
|
-
"""
|
|
235
|
-
Intent for stopping a shadow test.
|
|
236
|
-
|
|
237
|
-
You can import the `StopIntent` class directly from `cloud`:
|
|
238
|
-
|
|
239
|
-
```python
|
|
240
|
-
from nextmv.cloud import StopIntent
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
Attributes
|
|
244
|
-
----------
|
|
245
|
-
complete : str
|
|
246
|
-
The test is marked as complete.
|
|
247
|
-
cancel : str
|
|
248
|
-
The test is canceled.
|
|
249
|
-
"""
|
|
250
|
-
|
|
251
|
-
complete = "complete"
|
|
252
|
-
"""The test is marked as complete."""
|
|
253
|
-
cancel = "cancel"
|
|
254
|
-
"""The test is canceled."""
|
nextmv/default_app/main.py
CHANGED
|
@@ -26,12 +26,10 @@ assets = create_visuals(name, input.data["radius"], input.data["distance"])
|
|
|
26
26
|
output = nextmv.Output(
|
|
27
27
|
options=options,
|
|
28
28
|
solution={"message": message},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
),
|
|
34
|
-
),
|
|
29
|
+
metrics={
|
|
30
|
+
"value": 1.23,
|
|
31
|
+
"custom": {"message": message},
|
|
32
|
+
},
|
|
35
33
|
assets=assets,
|
|
36
34
|
)
|
|
37
35
|
nextmv.write(output)
|
nextmv/local/executor.py
CHANGED
|
@@ -22,6 +22,8 @@ process_run_information
|
|
|
22
22
|
Function to update run metadata including duration and status.
|
|
23
23
|
process_run_logs
|
|
24
24
|
Function to process and save run logs.
|
|
25
|
+
process_run_metrics
|
|
26
|
+
Function to process and save run metrics.
|
|
25
27
|
process_run_statistics
|
|
26
28
|
Function to process and save run statistics.
|
|
27
29
|
process_run_assets
|
|
@@ -57,7 +59,16 @@ from nextmv.local.local import (
|
|
|
57
59
|
)
|
|
58
60
|
from nextmv.local.plotly_handler import handle_plotly_visual
|
|
59
61
|
from nextmv.manifest import Manifest, ManifestType
|
|
60
|
-
from nextmv.output import
|
|
62
|
+
from nextmv.output import (
|
|
63
|
+
ASSETS_KEY,
|
|
64
|
+
METRICS_KEY,
|
|
65
|
+
OUTPUTS_KEY,
|
|
66
|
+
SOLUTIONS_KEY,
|
|
67
|
+
STATISTICS_KEY,
|
|
68
|
+
Asset,
|
|
69
|
+
OutputFormat,
|
|
70
|
+
VisualSchema,
|
|
71
|
+
)
|
|
61
72
|
from nextmv.status import StatusV2
|
|
62
73
|
|
|
63
74
|
|
|
@@ -305,7 +316,7 @@ def process_run_output(
|
|
|
305
316
|
) -> None:
|
|
306
317
|
"""
|
|
307
318
|
Processes the result of the subprocess run. This function is in charge of
|
|
308
|
-
handling the run results, including solutions, statistics, logs, assets,
|
|
319
|
+
handling the run results, including solutions, statistics, metrics, logs, assets,
|
|
309
320
|
and visuals.
|
|
310
321
|
|
|
311
322
|
Parameters
|
|
@@ -347,6 +358,13 @@ def process_run_output(
|
|
|
347
358
|
result=result,
|
|
348
359
|
stdout_output=stdout_output,
|
|
349
360
|
)
|
|
361
|
+
process_run_metrics(
|
|
362
|
+
temp_run_outputs_dir=temp_run_outputs_dir,
|
|
363
|
+
outputs_dir=outputs_dir,
|
|
364
|
+
stdout_output=stdout_output,
|
|
365
|
+
temp_src=temp_src,
|
|
366
|
+
manifest=manifest,
|
|
367
|
+
)
|
|
350
368
|
process_run_statistics(
|
|
351
369
|
temp_run_outputs_dir=temp_run_outputs_dir,
|
|
352
370
|
outputs_dir=outputs_dir,
|
|
@@ -499,6 +517,65 @@ def process_run_logs(
|
|
|
499
517
|
|
|
500
518
|
f.write(std_err)
|
|
501
519
|
|
|
520
|
+
def process_run_metrics(
|
|
521
|
+
temp_run_outputs_dir: str,
|
|
522
|
+
outputs_dir: str,
|
|
523
|
+
stdout_output: str | dict[str, Any],
|
|
524
|
+
temp_src: str,
|
|
525
|
+
manifest: Manifest,
|
|
526
|
+
) -> None:
|
|
527
|
+
"""
|
|
528
|
+
Processes the metrics of the run. Checks for an outputs/metrics folder
|
|
529
|
+
or custom metrics file location from manifest. If found, copies to run
|
|
530
|
+
directory. Otherwise, attempts to extract metrics from stdout.
|
|
531
|
+
|
|
532
|
+
Parameters
|
|
533
|
+
----------
|
|
534
|
+
temp_run_outputs_dir : str
|
|
535
|
+
The path to the temporary outputs directory.
|
|
536
|
+
outputs_dir : str
|
|
537
|
+
The path to the outputs directory in the run directory.
|
|
538
|
+
stdout_output : Union[str, dict[str, Any]]
|
|
539
|
+
The stdout output of the run, either as raw string or parsed dictionary.
|
|
540
|
+
temp_src : str
|
|
541
|
+
The path to the temporary source directory.
|
|
542
|
+
manifest : Manifest
|
|
543
|
+
The application manifest containing configuration and custom paths.
|
|
544
|
+
"""
|
|
545
|
+
|
|
546
|
+
metrics_dst = os.path.join(outputs_dir, METRICS_KEY)
|
|
547
|
+
os.makedirs(metrics_dst, exist_ok=True)
|
|
548
|
+
metrics_file = f"{METRICS_KEY}.json"
|
|
549
|
+
|
|
550
|
+
# Check for custom location in manifest and override metrics_src if needed.
|
|
551
|
+
if (
|
|
552
|
+
manifest.configuration is not None
|
|
553
|
+
and manifest.configuration.content is not None
|
|
554
|
+
and manifest.configuration.content.format == OutputFormat.MULTI_FILE
|
|
555
|
+
and manifest.configuration.content.multi_file is not None
|
|
556
|
+
):
|
|
557
|
+
metrics_src_file = os.path.join(temp_src, manifest.configuration.content.multi_file.output.metrics)
|
|
558
|
+
|
|
559
|
+
# If the custom metrics file exists, copy it to the metrics destination
|
|
560
|
+
if os.path.exists(metrics_src_file) and os.path.isfile(metrics_src_file):
|
|
561
|
+
metrics_dst_file = os.path.join(metrics_dst, metrics_file)
|
|
562
|
+
shutil.copy2(metrics_src_file, metrics_dst_file)
|
|
563
|
+
return
|
|
564
|
+
|
|
565
|
+
metrics_src = os.path.join(temp_run_outputs_dir, METRICS_KEY)
|
|
566
|
+
if os.path.exists(metrics_src) and os.path.isdir(metrics_src):
|
|
567
|
+
shutil.copytree(metrics_src, metrics_dst, dirs_exist_ok=True)
|
|
568
|
+
return
|
|
569
|
+
|
|
570
|
+
if not isinstance(stdout_output, dict):
|
|
571
|
+
return
|
|
572
|
+
|
|
573
|
+
if METRICS_KEY not in stdout_output:
|
|
574
|
+
return
|
|
575
|
+
|
|
576
|
+
with open(os.path.join(metrics_dst, metrics_file), "w") as f:
|
|
577
|
+
metrics = {METRICS_KEY: stdout_output[METRICS_KEY]}
|
|
578
|
+
json.dump(metrics, f, indent=2)
|
|
502
579
|
|
|
503
580
|
def process_run_statistics(
|
|
504
581
|
temp_run_outputs_dir: str,
|
|
@@ -508,6 +585,9 @@ def process_run_statistics(
|
|
|
508
585
|
manifest: Manifest,
|
|
509
586
|
) -> None:
|
|
510
587
|
"""
|
|
588
|
+
!!! warning
|
|
589
|
+
`process_run_statistics` is deprecated, use `process_run_metrics` instead.
|
|
590
|
+
|
|
511
591
|
Processes the statistics of the run. Checks for an outputs/statistics folder
|
|
512
592
|
or custom statistics file location from manifest. If found, copies to run
|
|
513
593
|
directory. Otherwise, attempts to extract statistics from stdout.
|
|
@@ -848,7 +928,7 @@ def _copy_new_or_modified_files( # noqa: C901
|
|
|
848
928
|
This function identifies files that are either new (not present in the original
|
|
849
929
|
source) or have been modified (different content, checksum, or modification time)
|
|
850
930
|
compared to the original source. It excludes files that exist in specified
|
|
851
|
-
exclusion directories to avoid copying input data, statistics, or assets as
|
|
931
|
+
exclusion directories to avoid copying input data, statistics, metrics, or assets as
|
|
852
932
|
solution outputs.
|
|
853
933
|
|
|
854
934
|
Parameters
|
nextmv/local/geojson_handler.py
CHANGED
|
@@ -111,7 +111,7 @@ def extract_coordinates(coords, all_coords) -> None:
|
|
|
111
111
|
like Polygons and MultiPolygons
|
|
112
112
|
"""
|
|
113
113
|
if isinstance(coords, list):
|
|
114
|
-
if len(coords) == 2 and isinstance(coords[0],
|
|
114
|
+
if len(coords) == 2 and isinstance(coords[0], int | float) and isinstance(coords[1], int | float):
|
|
115
115
|
# This is a coordinate pair [lon, lat]
|
|
116
116
|
all_coords.append(coords)
|
|
117
117
|
else:
|
nextmv/manifest.py
CHANGED
|
@@ -829,7 +829,9 @@ class ManifestContentMultiFileOutput(BaseModel):
|
|
|
829
829
|
Parameters
|
|
830
830
|
----------
|
|
831
831
|
statistics : Optional[str], default=""
|
|
832
|
-
The path to the statistics file.
|
|
832
|
+
Deprecated: Use `metrics` instead. The path to the statistics file.
|
|
833
|
+
metrics : Optional[str], default=""
|
|
834
|
+
The path to the metrics file.
|
|
833
835
|
assets : Optional[str], default=""
|
|
834
836
|
The path to the assets file.
|
|
835
837
|
solutions : Optional[str], default=""
|
|
@@ -839,16 +841,18 @@ class ManifestContentMultiFileOutput(BaseModel):
|
|
|
839
841
|
--------
|
|
840
842
|
>>> from nextmv import ManifestContentMultiFileOutput
|
|
841
843
|
>>> output_config = ManifestContentMultiFileOutput(
|
|
842
|
-
...
|
|
844
|
+
... metrics="my-outputs/metrics.json",
|
|
843
845
|
... assets="my-outputs/assets.json",
|
|
844
846
|
... solutions="my-outputs/solutions/"
|
|
845
847
|
... )
|
|
846
|
-
>>> output_config.
|
|
847
|
-
'my-outputs/
|
|
848
|
+
>>> output_config.metrics
|
|
849
|
+
'my-outputs/metrics.json'
|
|
848
850
|
"""
|
|
849
851
|
|
|
850
852
|
statistics: str | None = ""
|
|
851
|
-
"""The path to the statistics file."""
|
|
853
|
+
"""Deprecated: Use `metrics` instead. The path to the statistics file."""
|
|
854
|
+
metrics: str | None = ""
|
|
855
|
+
"""The path to the metrics file."""
|
|
852
856
|
assets: str | None = ""
|
|
853
857
|
"""The path to the assets file."""
|
|
854
858
|
solutions: str | None = ""
|
|
@@ -878,7 +882,7 @@ class ManifestContentMultiFile(BaseModel):
|
|
|
878
882
|
>>> multi_file_config = ManifestContentMultiFile(
|
|
879
883
|
... input=ManifestContentMultiFileInput(path="data/input/"),
|
|
880
884
|
... output=ManifestContentMultiFileOutput(
|
|
881
|
-
...
|
|
885
|
+
... metrics="my-outputs/metrics.json",
|
|
882
886
|
... assets="my-outputs/assets.json",
|
|
883
887
|
... solutions="my-outputs/solutions/"
|
|
884
888
|
... )
|
|
@@ -919,7 +923,7 @@ class ManifestContent(BaseModel):
|
|
|
919
923
|
... multi_file=ManifestContentMultiFile(
|
|
920
924
|
... input=ManifestContentMultiFileInput(path="data/input/"),
|
|
921
925
|
... output=ManifestContentMultiFileOutput(
|
|
922
|
-
...
|
|
926
|
+
... metrics="my-outputs/metrics.json",
|
|
923
927
|
... assets="my-outputs/assets.json",
|
|
924
928
|
... solutions="my-outputs/solutions/"
|
|
925
929
|
... )
|
nextmv/model.py
CHANGED
|
@@ -195,7 +195,7 @@ class Model:
|
|
|
195
195
|
... return nextmv.Output(
|
|
196
196
|
... options=input.options,
|
|
197
197
|
... solution=nextroute_output.solutions[0].to_dict(),
|
|
198
|
-
...
|
|
198
|
+
... metrics=nextroute_output.metrics.to_dict(),
|
|
199
199
|
... )
|
|
200
200
|
"""
|
|
201
201
|
|
|
@@ -234,7 +234,7 @@ class Model:
|
|
|
234
234
|
... return Output(
|
|
235
235
|
... options=input.options,
|
|
236
236
|
... solution=result,
|
|
237
|
-
...
|
|
237
|
+
... metrics={"processing_time": 0.5}
|
|
238
238
|
... )
|
|
239
239
|
"""
|
|
240
240
|
|
nextmv/options.py
CHANGED
nextmv/output.py
CHANGED
|
@@ -8,9 +8,9 @@ destinations.
|
|
|
8
8
|
Classes
|
|
9
9
|
-------
|
|
10
10
|
RunStatistics
|
|
11
|
-
Statistics about a general run.
|
|
11
|
+
Deprecated: Statistics about a general run.
|
|
12
12
|
ResultStatistics
|
|
13
|
-
Statistics about a specific result.
|
|
13
|
+
Deprecated: Statistics about a specific result.
|
|
14
14
|
DataPoint
|
|
15
15
|
A data point representing a 2D coordinate.
|
|
16
16
|
Series
|
|
@@ -18,7 +18,10 @@ Series
|
|
|
18
18
|
SeriesData
|
|
19
19
|
Data container for multiple series of data points.
|
|
20
20
|
Statistics
|
|
21
|
-
Complete statistics container for a
|
|
21
|
+
Deprecated: Use metrics instead. Complete statistics container for a
|
|
22
|
+
solution, including run metrics and result data.
|
|
23
|
+
Metrics
|
|
24
|
+
Metrics container for a solution.
|
|
22
25
|
OutputFormat
|
|
23
26
|
Enumeration of supported output formats.
|
|
24
27
|
SolutionFile
|
|
@@ -46,7 +49,9 @@ Attributes
|
|
|
46
49
|
ASSETS_KEY : str
|
|
47
50
|
Assets key constant used for identifying assets in the run output.
|
|
48
51
|
STATISTICS_KEY : str
|
|
49
|
-
Statistics key constant used for identifying statistics in the run output.
|
|
52
|
+
Deprecated: Use METRICS_KEY instead. Statistics key constant used for identifying statistics in the run output.
|
|
53
|
+
METRICS_KEY : str
|
|
54
|
+
Metrics key constant used for identifying metrics in the run output.
|
|
50
55
|
SOLUTIONS_KEY : str
|
|
51
56
|
Solutions key constant used for identifying solutions in the run output.
|
|
52
57
|
OUTPUTS_KEY : str
|
|
@@ -75,7 +80,11 @@ Assets key constant used for identifying assets in the run output.
|
|
|
75
80
|
"""
|
|
76
81
|
STATISTICS_KEY = "statistics"
|
|
77
82
|
"""
|
|
78
|
-
Statistics key constant used for identifying statistics in the run output.
|
|
83
|
+
Deprecated: Use METRICS_KEY instead. Statistics key constant used for identifying statistics in the run output.
|
|
84
|
+
"""
|
|
85
|
+
METRICS_KEY = "metrics"
|
|
86
|
+
"""
|
|
87
|
+
Metrics key constant used for identifying metrics in the run output.
|
|
79
88
|
"""
|
|
80
89
|
SOLUTIONS_KEY = "solutions"
|
|
81
90
|
"""
|
|
@@ -89,7 +98,7 @@ Outputs key constant used for identifying outputs in the run output.
|
|
|
89
98
|
|
|
90
99
|
class RunStatistics(BaseModel):
|
|
91
100
|
"""
|
|
92
|
-
Statistics about a general run.
|
|
101
|
+
Deprecated: Statistics about a general run.
|
|
93
102
|
|
|
94
103
|
You can import the `RunStatistics` class directly from `nextmv`:
|
|
95
104
|
|
|
@@ -129,7 +138,7 @@ class RunStatistics(BaseModel):
|
|
|
129
138
|
|
|
130
139
|
class ResultStatistics(BaseModel):
|
|
131
140
|
"""
|
|
132
|
-
Statistics about a specific result.
|
|
141
|
+
Deprecated: Statistics about a specific result.
|
|
133
142
|
|
|
134
143
|
You can import the `ResultStatistics` class directly from `nextmv`:
|
|
135
144
|
|
|
@@ -169,7 +178,7 @@ class ResultStatistics(BaseModel):
|
|
|
169
178
|
|
|
170
179
|
class DataPoint(BaseModel):
|
|
171
180
|
"""
|
|
172
|
-
A data point representing a 2D coordinate.
|
|
181
|
+
Deprecated: A data point representing a 2D coordinate.
|
|
173
182
|
|
|
174
183
|
You can import the `DataPoint` class directly from `nextmv`:
|
|
175
184
|
|
|
@@ -202,7 +211,7 @@ class DataPoint(BaseModel):
|
|
|
202
211
|
|
|
203
212
|
class Series(BaseModel):
|
|
204
213
|
"""
|
|
205
|
-
A series of data points for visualization or analysis.
|
|
214
|
+
Deprecated: A series of data points for visualization or analysis.
|
|
206
215
|
|
|
207
216
|
You can import the `Series` class directly from `nextmv`:
|
|
208
217
|
|
|
@@ -236,7 +245,7 @@ class Series(BaseModel):
|
|
|
236
245
|
|
|
237
246
|
class SeriesData(BaseModel):
|
|
238
247
|
"""
|
|
239
|
-
Data container for multiple series of data points.
|
|
248
|
+
Deprecated: Data container for multiple series of data points.
|
|
240
249
|
|
|
241
250
|
You can import the `SeriesData` class directly from `nextmv`:
|
|
242
251
|
|
|
@@ -271,6 +280,9 @@ class SeriesData(BaseModel):
|
|
|
271
280
|
|
|
272
281
|
class Statistics(BaseModel):
|
|
273
282
|
"""
|
|
283
|
+
!!! warning
|
|
284
|
+
`Statistics` is deprecated, use `Metrics` instead.
|
|
285
|
+
|
|
274
286
|
Complete statistics container for a solution, including run metrics and
|
|
275
287
|
result data.
|
|
276
288
|
|
|
@@ -877,7 +889,9 @@ class Output:
|
|
|
877
889
|
The solution to the decision problem. The type must match the
|
|
878
890
|
`output_format`. Default is None.
|
|
879
891
|
statistics : Optional[Union[Statistics, dict[str, Any]]], optional
|
|
880
|
-
Statistics of the solution. Default is None.
|
|
892
|
+
Deprecated: Use Metrics instead. Statistics of the solution. Default is None.
|
|
893
|
+
metrics : Optional[dict[str, Any]], optional
|
|
894
|
+
Metrics of the solution. Default is None.
|
|
881
895
|
csv_configurations : Optional[dict[str, Any]], optional
|
|
882
896
|
Configuration for writing CSV files. Default is None.
|
|
883
897
|
json_configurations : Optional[dict[str, Any]], optional
|
|
@@ -916,17 +930,16 @@ class Output:
|
|
|
916
930
|
Examples
|
|
917
931
|
--------
|
|
918
932
|
>>> from nextmv.output import Output, OutputFormat, Statistics, RunStatistics
|
|
919
|
-
>>>
|
|
920
|
-
>>> stats = Statistics(run=run_stats)
|
|
933
|
+
>>> metrics = {"duration": 30.0, "iterations": 100}
|
|
921
934
|
>>> solution = {"routes": [{"vehicle": 1, "stops": [1, 2, 3]}, {"vehicle": 2, "stops": [4, 5]}]}
|
|
922
935
|
>>> output = Output(
|
|
923
936
|
... output_format=OutputFormat.JSON,
|
|
924
937
|
... solution=solution,
|
|
925
|
-
...
|
|
938
|
+
... metrics=metrics,
|
|
926
939
|
... json_configurations={"indent": 4}
|
|
927
940
|
... )
|
|
928
941
|
>>> output_dict = output.to_dict()
|
|
929
|
-
>>> "solution" in output_dict and "
|
|
942
|
+
>>> "solution" in output_dict and "metrics" in output_dict
|
|
930
943
|
True
|
|
931
944
|
"""
|
|
932
945
|
|
|
@@ -969,11 +982,16 @@ class Output:
|
|
|
969
982
|
"""
|
|
970
983
|
statistics: Statistics | dict[str, Any] | None = None
|
|
971
984
|
"""
|
|
985
|
+
Deprecated: Use Metrics instead.
|
|
972
986
|
Statistics of the solution. These statistics can be of type `Statistics` or a
|
|
973
987
|
simple dictionary. If the statistics are of type `Statistics`, they will be
|
|
974
988
|
serialized to a dictionary using the `to_dict` method. If they are a
|
|
975
|
-
dictionary, they will be used as is.
|
|
976
|
-
|
|
989
|
+
dictionary, they will be used as is.
|
|
990
|
+
"""
|
|
991
|
+
metrics: dict[str, Any] | None = None
|
|
992
|
+
"""
|
|
993
|
+
Metrics of the solution. These metrics should be provided as a simple or
|
|
994
|
+
nested dictionary.
|
|
977
995
|
"""
|
|
978
996
|
csv_configurations: dict[str, Any] | None = None
|
|
979
997
|
"""
|
|
@@ -1088,7 +1106,7 @@ class Output:
|
|
|
1088
1106
|
# Statistics need to end up as a dict, so we achieve that based on the
|
|
1089
1107
|
# type of statistics that were used to create the class.
|
|
1090
1108
|
if self.statistics is None:
|
|
1091
|
-
statistics =
|
|
1109
|
+
statistics = None
|
|
1092
1110
|
elif isinstance(self.statistics, Statistics):
|
|
1093
1111
|
statistics = self.statistics.to_dict()
|
|
1094
1112
|
elif isinstance(self.statistics, dict):
|
|
@@ -1098,6 +1116,18 @@ class Output:
|
|
|
1098
1116
|
f"unsupported statistics type: {type(self.statistics)}, supported types are `Statistics` or `dict`"
|
|
1099
1117
|
)
|
|
1100
1118
|
|
|
1119
|
+
if self.metrics is None:
|
|
1120
|
+
metrics = None
|
|
1121
|
+
elif isinstance(self.metrics, dict):
|
|
1122
|
+
metrics = self.metrics
|
|
1123
|
+
else:
|
|
1124
|
+
raise TypeError(f"unsupported metrics type: {type(self.metrics)}, supported type is `dict`")
|
|
1125
|
+
|
|
1126
|
+
# if both metrics and statistics are None, set statistics to an
|
|
1127
|
+
# empty dict for backward compatibility
|
|
1128
|
+
if statistics is None and metrics is None:
|
|
1129
|
+
statistics = {}
|
|
1130
|
+
|
|
1101
1131
|
# Assets need to end up as a list of dicts, so we achieve that based on
|
|
1102
1132
|
# the type of each asset in the list.
|
|
1103
1133
|
assets = []
|
|
@@ -1117,10 +1147,16 @@ class Output:
|
|
|
1117
1147
|
output_dict = {
|
|
1118
1148
|
"options": options,
|
|
1119
1149
|
"solution": self.solution if self.solution is not None else {},
|
|
1120
|
-
STATISTICS_KEY: statistics,
|
|
1121
1150
|
ASSETS_KEY: assets,
|
|
1122
1151
|
}
|
|
1123
1152
|
|
|
1153
|
+
# Only include statistics in output if it's not None
|
|
1154
|
+
if statistics is not None:
|
|
1155
|
+
output_dict[STATISTICS_KEY] = statistics
|
|
1156
|
+
|
|
1157
|
+
if metrics is not None:
|
|
1158
|
+
output_dict[METRICS_KEY] = metrics
|
|
1159
|
+
|
|
1124
1160
|
# Add the auxiliary configurations to the output dictionary if they are
|
|
1125
1161
|
# defined and not empty.
|
|
1126
1162
|
if (
|
|
@@ -1193,9 +1229,9 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1193
1229
|
|
|
1194
1230
|
Examples
|
|
1195
1231
|
--------
|
|
1196
|
-
>>> from nextmv.output import LocalOutputWriter, Output,
|
|
1232
|
+
>>> from nextmv.output import LocalOutputWriter, Output, Metrics
|
|
1197
1233
|
>>> writer = LocalOutputWriter()
|
|
1198
|
-
>>> output = Output(solution={"result": 42},
|
|
1234
|
+
>>> output = Output(solution={"result": 42}, metrics={"time": 1.23})
|
|
1199
1235
|
>>> # Write to stdout
|
|
1200
1236
|
>>> writer.write(output, path=None)
|
|
1201
1237
|
>>> # Write to a file
|
nextmv/run.py
CHANGED
|
@@ -434,6 +434,9 @@ class RunInfoStatistics(BaseModel):
|
|
|
434
434
|
"""List of statistics indicators."""
|
|
435
435
|
|
|
436
436
|
|
|
437
|
+
RunInfoMetrics = RunInfoStatistics
|
|
438
|
+
|
|
439
|
+
|
|
437
440
|
class OptionsSummaryItem(BaseModel):
|
|
438
441
|
"""
|
|
439
442
|
Summary item for options used in a run.
|
|
@@ -529,7 +532,9 @@ class Run(BaseModel):
|
|
|
529
532
|
experiment_id : str, optional
|
|
530
533
|
ID of the experiment associated with the run. Defaults to None.
|
|
531
534
|
statistics : RunInfoStatistics, optional
|
|
532
|
-
Statistics of the run. Defaults to None.
|
|
535
|
+
Deprecated: Statistics of the run. Defaults to None.
|
|
536
|
+
metrics: RunInfoMetrics, optional
|
|
537
|
+
Metrics of the run. Defaults to None.
|
|
533
538
|
input_id : str, optional
|
|
534
539
|
ID of the input associated with the run. Defaults to None.
|
|
535
540
|
option_set : str, optional
|
|
@@ -603,7 +608,9 @@ class Run(BaseModel):
|
|
|
603
608
|
experiment_id: str | None = None
|
|
604
609
|
"""ID of the experiment associated with the run."""
|
|
605
610
|
statistics: RunInfoStatistics | None = None
|
|
606
|
-
"""Statistics of the run."""
|
|
611
|
+
"""Deprecated: Statistics of the run."""
|
|
612
|
+
metrics: RunInfoMetrics | None = None
|
|
613
|
+
"""Metrics of the run."""
|
|
607
614
|
input_id: str | None = None
|
|
608
615
|
"""ID of the input associated with the run."""
|
|
609
616
|
option_set: str | None = None
|
|
@@ -677,7 +684,9 @@ class Metadata(BaseModel):
|
|
|
677
684
|
status_v2: StatusV2
|
|
678
685
|
"""Status of the run."""
|
|
679
686
|
statistics: dict[str, Any] | None = None
|
|
680
|
-
"""User defined statistics of the run."""
|
|
687
|
+
"""Deprecated: User defined statistics of the run."""
|
|
688
|
+
metrics: dict[str, Any] | None = None
|
|
689
|
+
"""User defined metrics of the run."""
|
|
681
690
|
|
|
682
691
|
def run_is_finalized(self) -> bool:
|
|
683
692
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextmv
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev8
|
|
4
4
|
Summary: The all-purpose Python SDK for Nextmv
|
|
5
5
|
Project-URL: Homepage, https://www.nextmv.io
|
|
6
6
|
Project-URL: Documentation, https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
|
|
@@ -230,13 +230,11 @@ Provides-Extra: dev
|
|
|
230
230
|
Requires-Dist: build>=1.0.3; extra == 'dev'
|
|
231
231
|
Requires-Dist: folium>=0.20.0; extra == 'dev'
|
|
232
232
|
Requires-Dist: mlflow>=2.19.0; extra == 'dev'
|
|
233
|
-
Requires-Dist: nextpipe>=0.6.0.dev0; extra == 'dev'
|
|
234
233
|
Requires-Dist: nextroute>=1.11.1; extra == 'dev'
|
|
235
234
|
Requires-Dist: openpyxl>=3.1.5; extra == 'dev'
|
|
236
235
|
Requires-Dist: pandas>=2.2.3; extra == 'dev'
|
|
237
236
|
Requires-Dist: plotly>=6.0.1; extra == 'dev'
|
|
238
237
|
Requires-Dist: pydantic>=2.5.2; extra == 'dev'
|
|
239
|
-
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
240
238
|
Requires-Dist: pyyaml>=6.0.1; extra == 'dev'
|
|
241
239
|
Requires-Dist: requests>=2.31.0; extra == 'dev'
|
|
242
240
|
Requires-Dist: ruff>=0.1.7; extra == 'dev'
|