nextmv 1.0.0.dev3__py3-none-any.whl → 1.0.0.dev5__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 +0 -4
- nextmv/_serialization.py +1 -1
- nextmv/cli/CONTRIBUTING.md +81 -29
- nextmv/cli/cloud/acceptance/create.py +24 -26
- nextmv/cli/cloud/acceptance/delete.py +7 -8
- nextmv/cli/cloud/acceptance/get.py +9 -10
- nextmv/cli/cloud/acceptance/list.py +3 -3
- nextmv/cli/cloud/acceptance/update.py +6 -6
- nextmv/cli/cloud/account/__init__.py +3 -3
- nextmv/cli/cloud/account/create.py +11 -11
- nextmv/cli/cloud/account/delete.py +6 -7
- nextmv/cli/cloud/account/get.py +3 -3
- nextmv/cli/cloud/account/update.py +5 -5
- nextmv/cli/cloud/app/create.py +25 -26
- nextmv/cli/cloud/app/delete.py +5 -6
- nextmv/cli/cloud/app/exists.py +2 -2
- nextmv/cli/cloud/app/get.py +2 -2
- nextmv/cli/cloud/app/list.py +3 -3
- nextmv/cli/cloud/app/push.py +368 -54
- nextmv/cli/cloud/app/update.py +12 -12
- nextmv/cli/cloud/batch/create.py +26 -28
- nextmv/cli/cloud/batch/delete.py +5 -6
- nextmv/cli/cloud/batch/get.py +8 -8
- nextmv/cli/cloud/batch/list.py +3 -3
- nextmv/cli/cloud/batch/metadata.py +4 -4
- nextmv/cli/cloud/batch/update.py +6 -6
- nextmv/cli/cloud/data/__init__.py +1 -1
- nextmv/cli/cloud/data/upload.py +15 -15
- nextmv/cli/cloud/ensemble/__init__.py +2 -0
- nextmv/cli/cloud/ensemble/create.py +21 -22
- nextmv/cli/cloud/ensemble/delete.py +5 -6
- nextmv/cli/cloud/ensemble/get.py +4 -4
- nextmv/cli/cloud/ensemble/list.py +63 -0
- nextmv/cli/cloud/ensemble/update.py +9 -9
- nextmv/cli/cloud/input_set/create.py +20 -22
- nextmv/cli/cloud/input_set/get.py +3 -3
- nextmv/cli/cloud/input_set/list.py +3 -3
- nextmv/cli/cloud/input_set/update.py +24 -24
- nextmv/cli/cloud/instance/create.py +14 -15
- nextmv/cli/cloud/instance/delete.py +5 -6
- nextmv/cli/cloud/instance/exists.py +2 -2
- nextmv/cli/cloud/instance/get.py +2 -2
- nextmv/cli/cloud/instance/list.py +3 -3
- nextmv/cli/cloud/instance/update.py +14 -14
- nextmv/cli/cloud/managed_input/create.py +14 -16
- nextmv/cli/cloud/managed_input/delete.py +6 -7
- nextmv/cli/cloud/managed_input/get.py +3 -3
- nextmv/cli/cloud/managed_input/list.py +3 -3
- nextmv/cli/cloud/managed_input/update.py +9 -9
- nextmv/cli/cloud/run/cancel.py +2 -2
- nextmv/cli/cloud/run/create.py +32 -33
- nextmv/cli/cloud/run/get.py +8 -8
- nextmv/cli/cloud/run/input.py +4 -4
- nextmv/cli/cloud/run/list.py +6 -6
- nextmv/cli/cloud/run/logs.py +9 -10
- nextmv/cli/cloud/run/metadata.py +4 -4
- nextmv/cli/cloud/run/track.py +32 -33
- nextmv/cli/cloud/scenario/create.py +21 -21
- nextmv/cli/cloud/scenario/delete.py +5 -6
- nextmv/cli/cloud/scenario/get.py +8 -8
- nextmv/cli/cloud/scenario/list.py +3 -3
- nextmv/cli/cloud/scenario/metadata.py +4 -4
- nextmv/cli/cloud/scenario/update.py +6 -6
- nextmv/cli/cloud/secrets/create.py +17 -17
- nextmv/cli/cloud/secrets/delete.py +5 -6
- nextmv/cli/cloud/secrets/get.py +4 -4
- nextmv/cli/cloud/secrets/list.py +3 -3
- nextmv/cli/cloud/secrets/update.py +17 -20
- nextmv/cli/cloud/shadow/create.py +31 -31
- nextmv/cli/cloud/shadow/delete.py +5 -6
- nextmv/cli/cloud/shadow/get.py +2 -2
- nextmv/cli/cloud/shadow/list.py +3 -3
- nextmv/cli/cloud/shadow/metadata.py +4 -4
- nextmv/cli/cloud/shadow/start.py +3 -3
- nextmv/cli/cloud/shadow/stop.py +4 -6
- nextmv/cli/cloud/shadow/update.py +6 -6
- nextmv/cli/cloud/switchback/create.py +19 -15
- nextmv/cli/cloud/switchback/delete.py +5 -6
- nextmv/cli/cloud/switchback/get.py +3 -3
- nextmv/cli/cloud/switchback/list.py +3 -3
- nextmv/cli/cloud/switchback/metadata.py +6 -6
- nextmv/cli/cloud/switchback/start.py +4 -4
- nextmv/cli/cloud/switchback/stop.py +4 -6
- nextmv/cli/cloud/switchback/update.py +6 -6
- nextmv/cli/cloud/upload/create.py +2 -2
- nextmv/cli/cloud/version/create.py +9 -10
- nextmv/cli/cloud/version/delete.py +5 -6
- nextmv/cli/cloud/version/exists.py +2 -2
- nextmv/cli/cloud/version/get.py +2 -2
- nextmv/cli/cloud/version/list.py +3 -3
- nextmv/cli/cloud/version/update.py +8 -8
- nextmv/cli/community/clone.py +12 -10
- nextmv/cli/community/list.py +9 -9
- nextmv/cli/configuration/config.py +43 -10
- nextmv/cli/configuration/create.py +3 -3
- nextmv/cli/configuration/delete.py +7 -7
- nextmv/cli/configuration/list.py +3 -3
- nextmv/cli/confirm.py +34 -0
- nextmv/cli/main.py +27 -36
- nextmv/cli/message.py +2 -2
- nextmv/cli/version.py +1 -1
- nextmv/cloud/__init__.py +0 -38
- nextmv/cloud/acceptance_test.py +1 -65
- nextmv/cloud/account.py +1 -6
- nextmv/cloud/application/__init__.py +192 -54
- nextmv/cloud/application/_batch_scenario.py +4 -19
- nextmv/cloud/application/_instance.py +3 -3
- nextmv/cloud/application/_managed_input.py +2 -2
- nextmv/cloud/application/_run.py +8 -1
- nextmv/cloud/application/_shadow.py +2 -2
- nextmv/cloud/application/_switchback.py +12 -4
- nextmv/cloud/application/_version.py +4 -3
- nextmv/cloud/client.py +1 -1
- nextmv/cloud/shadow.py +43 -4
- nextmv/cloud/switchback.py +46 -9
- nextmv/default_app/main.py +4 -6
- nextmv/deprecated.py +5 -3
- nextmv/input.py +0 -52
- nextmv/local/executor.py +83 -3
- nextmv/local/geojson_handler.py +1 -1
- nextmv/local/runner.py +1 -1
- nextmv/manifest.py +11 -7
- nextmv/model.py +2 -2
- nextmv/options.py +10 -255
- nextmv/output.py +57 -83
- nextmv/run.py +13 -13
- nextmv/status.py +1 -51
- {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev5.dist-info}/METADATA +1 -1
- nextmv-1.0.0.dev5.dist-info/RECORD +183 -0
- nextmv-1.0.0.dev3.dist-info/RECORD +0 -181
- {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev5.dist-info}/WHEEL +0 -0
- {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev5.dist-info}/entry_points.txt +0 -0
- {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev5.dist-info}/licenses/LICENSE +0 -0
nextmv/cloud/switchback.py
CHANGED
|
@@ -91,10 +91,10 @@ class SwitchbackPlan(BaseModel):
|
|
|
91
91
|
|
|
92
92
|
Parameters
|
|
93
93
|
----------
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
start : datetime, optional
|
|
95
|
+
Start time of the switchback test.
|
|
96
|
+
units : list[SwitchbackPlanUnit], optional
|
|
97
|
+
List of switchback plan units.
|
|
98
98
|
"""
|
|
99
99
|
|
|
100
100
|
start: datetime | None = None
|
|
@@ -151,7 +151,10 @@ class SwitchbackTestMetadata(BaseModel):
|
|
|
151
151
|
"""The current status of the switchback test."""
|
|
152
152
|
|
|
153
153
|
|
|
154
|
-
class
|
|
154
|
+
# This class uses some fields defined in SwitchbackTestMetadata. We are not
|
|
155
|
+
# using inheritance to help the user understand the full structure when using
|
|
156
|
+
# tools like intellisense.
|
|
157
|
+
class SwitchbackTest(BaseModel):
|
|
155
158
|
"""
|
|
156
159
|
A Nextmv Cloud switchback test definition.
|
|
157
160
|
|
|
@@ -167,16 +170,50 @@ class SwitchbackTest(SwitchbackTestMetadata):
|
|
|
167
170
|
|
|
168
171
|
Parameters
|
|
169
172
|
----------
|
|
173
|
+
switchback_test_id : str, optional
|
|
174
|
+
The unique identifier of the switchback test.
|
|
175
|
+
name : str, optional
|
|
176
|
+
Name of the switchback test.
|
|
177
|
+
description : str, optional
|
|
178
|
+
Description of the switchback test.
|
|
179
|
+
app_id : str, optional
|
|
180
|
+
ID of the application to which the switchback test belongs.
|
|
181
|
+
created_at : datetime, optional
|
|
182
|
+
Creation date of the switchback test.
|
|
183
|
+
updated_at : datetime, optional
|
|
184
|
+
Last update date of the switchback test.
|
|
185
|
+
status : ExperimentStatus, optional
|
|
186
|
+
The current status of the switchback test.
|
|
187
|
+
started_at : datetime, optional
|
|
188
|
+
Start date of the switchback test, if applicable.
|
|
170
189
|
completed_at : datetime, optional
|
|
171
190
|
Completion date of the switchback test, if applicable.
|
|
172
191
|
comparison : TestComparisonSingle, optional
|
|
173
192
|
Test comparison defined in the switchback test.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
plan : SwitchbackPlan, optional
|
|
194
|
+
Switchback plan defining the intervals and instance switching.
|
|
195
|
+
runs : list[Run], optional
|
|
196
|
+
List of runs in the switchback test.
|
|
178
197
|
"""
|
|
179
198
|
|
|
199
|
+
switchback_test_id: str | None = Field(
|
|
200
|
+
serialization_alias="id",
|
|
201
|
+
validation_alias=AliasChoices("id", "switchback_test_id"),
|
|
202
|
+
default=None,
|
|
203
|
+
)
|
|
204
|
+
"""The unique identifier of the switchback test."""
|
|
205
|
+
name: str | None = None
|
|
206
|
+
"""Name of the switchback test."""
|
|
207
|
+
description: str | None = None
|
|
208
|
+
"""Description of the switchback test."""
|
|
209
|
+
app_id: str | None = None
|
|
210
|
+
"""ID of the application to which the switchback test belongs."""
|
|
211
|
+
created_at: datetime | None = None
|
|
212
|
+
"""Creation date of the switchback test."""
|
|
213
|
+
updated_at: datetime | None = None
|
|
214
|
+
"""Last update date of the switchback test."""
|
|
215
|
+
status: ExperimentStatus | None = None
|
|
216
|
+
"""The current status of the switchback test."""
|
|
180
217
|
started_at: datetime | None = None
|
|
181
218
|
"""Start date of the switchback test, if applicable."""
|
|
182
219
|
completed_at: datetime | None = None
|
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/deprecated.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Utilities for handling deprecated functionality within the Nextmv Python SDK.
|
|
2
3
|
|
|
3
4
|
This module provides tools to mark functions, methods, or features as deprecated,
|
|
4
5
|
emitting appropriate warnings to users. These warnings inform users that the
|
|
@@ -13,7 +14,8 @@ import warnings
|
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def deprecated(name: str, reason: str) -> None:
|
|
16
|
-
"""
|
|
17
|
+
"""
|
|
18
|
+
Mark functionality as deprecated with a warning message.
|
|
17
19
|
|
|
18
20
|
This function emits a DeprecationWarning when called, indicating that
|
|
19
21
|
the functionality will be removed in a future release.
|
|
@@ -40,7 +42,7 @@ def deprecated(name: str, reason: str) -> None:
|
|
|
40
42
|
|
|
41
43
|
warnings.simplefilter("always", DeprecationWarning)
|
|
42
44
|
warnings.warn(
|
|
43
|
-
f"{name}: {reason}. This functionality will be removed in
|
|
45
|
+
f"{name}: {reason}. This functionality will be removed in the next major release.",
|
|
44
46
|
category=DeprecationWarning,
|
|
45
47
|
stacklevel=2,
|
|
46
48
|
)
|
nextmv/input.py
CHANGED
|
@@ -38,7 +38,6 @@ from enum import Enum
|
|
|
38
38
|
from typing import Any
|
|
39
39
|
|
|
40
40
|
from nextmv._serialization import serialize_json
|
|
41
|
-
from nextmv.deprecated import deprecated
|
|
42
41
|
from nextmv.options import Options
|
|
43
42
|
|
|
44
43
|
INPUTS_KEY = "inputs"
|
|
@@ -941,57 +940,6 @@ class LocalInputLoader(InputLoader):
|
|
|
941
940
|
return data
|
|
942
941
|
|
|
943
942
|
|
|
944
|
-
def load_local(
|
|
945
|
-
input_format: InputFormat | None = InputFormat.JSON,
|
|
946
|
-
options: Options | None = None,
|
|
947
|
-
path: str | None = None,
|
|
948
|
-
csv_configurations: dict[str, Any] | None = None,
|
|
949
|
-
) -> Input:
|
|
950
|
-
"""
|
|
951
|
-
!!! warning
|
|
952
|
-
`load_local` is deprecated, use `load` instead.
|
|
953
|
-
|
|
954
|
-
Load input data from local sources.
|
|
955
|
-
|
|
956
|
-
This is a convenience function for instantiating a `LocalInputLoader`
|
|
957
|
-
and calling its `load` method.
|
|
958
|
-
|
|
959
|
-
Parameters
|
|
960
|
-
----------
|
|
961
|
-
input_format : InputFormat, optional
|
|
962
|
-
Format of the input data. Default is `InputFormat.JSON`.
|
|
963
|
-
options : Options, optional
|
|
964
|
-
Options for loading the input data.
|
|
965
|
-
path : str, optional
|
|
966
|
-
Path to the input data.
|
|
967
|
-
csv_configurations : dict[str, Any], optional
|
|
968
|
-
Configurations for loading CSV files. Custom kwargs for
|
|
969
|
-
Python's `csv.DictReader`.
|
|
970
|
-
|
|
971
|
-
Returns
|
|
972
|
-
-------
|
|
973
|
-
Input
|
|
974
|
-
The loaded input data in an Input object.
|
|
975
|
-
|
|
976
|
-
Raises
|
|
977
|
-
------
|
|
978
|
-
ValueError
|
|
979
|
-
If the path is invalid or data format is incorrect.
|
|
980
|
-
|
|
981
|
-
See Also
|
|
982
|
-
--------
|
|
983
|
-
load : The recommended function to use instead.
|
|
984
|
-
"""
|
|
985
|
-
|
|
986
|
-
deprecated(
|
|
987
|
-
name="load_local",
|
|
988
|
-
reason="`load_local` is deprecated, use `load` instead",
|
|
989
|
-
)
|
|
990
|
-
|
|
991
|
-
loader = LocalInputLoader()
|
|
992
|
-
return loader.load(input_format, options, path, csv_configurations)
|
|
993
|
-
|
|
994
|
-
|
|
995
943
|
_LOCAL_INPUT_LOADER = LocalInputLoader()
|
|
996
944
|
"""Default instance of LocalInputLoader used by the load function."""
|
|
997
945
|
|
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/local/runner.py
CHANGED
|
@@ -204,7 +204,7 @@ def new_run(
|
|
|
204
204
|
if description is None:
|
|
205
205
|
description = f"Local run created at {created_at.isoformat().replace('+00:00', 'Z')}"
|
|
206
206
|
|
|
207
|
-
if name is None:
|
|
207
|
+
if name is None or name == "":
|
|
208
208
|
name = f"local run {run_id}"
|
|
209
209
|
|
|
210
210
|
information = RunInformation(
|
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
|
|