nextmv 1.0.0.dev4__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/cloud/acceptance/create.py +12 -12
- nextmv/cli/cloud/app/push.py +294 -204
- nextmv/cli/confirm.py +5 -3
- nextmv/cloud/__init__.py +0 -38
- nextmv/cloud/acceptance_test.py +1 -65
- nextmv/cloud/account.py +1 -6
- nextmv/cloud/application/__init__.py +2 -0
- nextmv/cloud/application/_batch_scenario.py +2 -17
- nextmv/cloud/application/_instance.py +1 -1
- nextmv/cloud/application/_managed_input.py +1 -1
- nextmv/cloud/application/_run.py +8 -1
- nextmv/cloud/application/_shadow.py +1 -1
- nextmv/cloud/application/_switchback.py +1 -1
- nextmv/cloud/application/_version.py +1 -1
- nextmv/cloud/client.py +1 -1
- 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.dev4.dist-info → nextmv-1.0.0.dev5.dist-info}/METADATA +1 -1
- {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev5.dist-info}/RECORD +36 -36
- {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev5.dist-info}/WHEEL +0 -0
- {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev5.dist-info}/entry_points.txt +0 -0
- {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev5.dist-info}/licenses/LICENSE +0 -0
nextmv/cloud/__init__.py
CHANGED
|
@@ -1,42 +1,5 @@
|
|
|
1
1
|
"""Functionality for interacting with the Nextmv Cloud."""
|
|
2
2
|
|
|
3
|
-
# These imports are kept for backwards compatibility but the preferred import path is
|
|
4
|
-
# from nextmv directly. These imports will be removed in a future release.
|
|
5
|
-
from nextmv.manifest import MANIFEST_FILE_NAME as MANIFEST_FILE_NAME
|
|
6
|
-
from nextmv.manifest import Manifest as Manifest
|
|
7
|
-
from nextmv.manifest import ManifestBuild as ManifestBuild
|
|
8
|
-
from nextmv.manifest import ManifestContent as ManifestContent
|
|
9
|
-
from nextmv.manifest import ManifestContentMultiFile as ManifestContentMultiFile
|
|
10
|
-
from nextmv.manifest import ManifestContentMultiFileInput as ManifestContentMultiFileInput
|
|
11
|
-
from nextmv.manifest import ManifestContentMultiFileOutput as ManifestContentMultiFileOutput
|
|
12
|
-
from nextmv.manifest import ManifestOption as ManifestOption
|
|
13
|
-
from nextmv.manifest import ManifestPython as ManifestPython
|
|
14
|
-
from nextmv.manifest import ManifestPythonModel as ManifestPythonModel
|
|
15
|
-
from nextmv.manifest import ManifestRuntime as ManifestRuntime
|
|
16
|
-
from nextmv.manifest import ManifestType as ManifestType
|
|
17
|
-
from nextmv.polling import PollingOptions as PollingOptions
|
|
18
|
-
from nextmv.polling import poll as poll
|
|
19
|
-
from nextmv.run import ErrorLog as ErrorLog
|
|
20
|
-
from nextmv.run import ExternalRunResult as ExternalRunResult
|
|
21
|
-
from nextmv.run import Format as Format
|
|
22
|
-
from nextmv.run import FormatInput as FormatInput
|
|
23
|
-
from nextmv.run import FormatOutput as FormatOutput
|
|
24
|
-
from nextmv.run import Metadata as Metadata
|
|
25
|
-
from nextmv.run import RunConfiguration as RunConfiguration
|
|
26
|
-
from nextmv.run import RunInformation as RunInformation
|
|
27
|
-
from nextmv.run import RunLog as RunLog
|
|
28
|
-
from nextmv.run import RunQueuing as RunQueuing
|
|
29
|
-
from nextmv.run import RunResult as RunResult
|
|
30
|
-
from nextmv.run import RunType as RunType
|
|
31
|
-
from nextmv.run import RunTypeConfiguration as RunTypeConfiguration
|
|
32
|
-
from nextmv.run import TrackedRun as TrackedRun
|
|
33
|
-
from nextmv.run import TrackedRunStatus as TrackedRunStatus
|
|
34
|
-
from nextmv.run import run_duration as run_duration
|
|
35
|
-
from nextmv.safe import safe_id as safe_id
|
|
36
|
-
from nextmv.safe import safe_name_and_id as safe_name_and_id
|
|
37
|
-
from nextmv.status import Status as Status
|
|
38
|
-
from nextmv.status import StatusV2 as StatusV2
|
|
39
|
-
|
|
40
3
|
from .acceptance_test import AcceptanceTest as AcceptanceTest
|
|
41
4
|
from .acceptance_test import AcceptanceTestResults as AcceptanceTestResults
|
|
42
5
|
from .acceptance_test import Comparison as Comparison
|
|
@@ -52,7 +15,6 @@ from .acceptance_test import MetricToleranceType as MetricToleranceType
|
|
|
52
15
|
from .acceptance_test import MetricType as MetricType
|
|
53
16
|
from .acceptance_test import ResultStatistics as ResultStatistics
|
|
54
17
|
from .acceptance_test import StatisticType as StatisticType
|
|
55
|
-
from .acceptance_test import ToleranceType as ToleranceType
|
|
56
18
|
from .account import Account as Account
|
|
57
19
|
from .account import AccountMember as AccountMember
|
|
58
20
|
from .account import Queue as Queue
|
nextmv/cloud/acceptance_test.py
CHANGED
|
@@ -13,7 +13,7 @@ StatisticType : Enum
|
|
|
13
13
|
Type of statistical process for collapsing multiple values of a metric.
|
|
14
14
|
Comparison : Enum
|
|
15
15
|
Comparison operators to use for comparing two metrics.
|
|
16
|
-
|
|
16
|
+
MetricToleranceType : Enum
|
|
17
17
|
Type of tolerance used for a metric.
|
|
18
18
|
ExperimentStatus : Enum
|
|
19
19
|
Status of an acceptance test experiment.
|
|
@@ -46,7 +46,6 @@ from enum import Enum
|
|
|
46
46
|
|
|
47
47
|
from nextmv.base_model import BaseModel
|
|
48
48
|
from nextmv.cloud.batch_experiment import ExperimentStatus
|
|
49
|
-
from nextmv.deprecated import deprecated
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
class MetricType(str, Enum):
|
|
@@ -212,69 +211,6 @@ class Comparison(str, Enum):
|
|
|
212
211
|
"""Not equal to metric type."""
|
|
213
212
|
|
|
214
213
|
|
|
215
|
-
class ToleranceType(str, Enum):
|
|
216
|
-
"""
|
|
217
|
-
!!! warning
|
|
218
|
-
`ToleranceType` is deprecated, use `MetricToleranceType` instead.
|
|
219
|
-
|
|
220
|
-
Type of tolerance used for a metric.
|
|
221
|
-
|
|
222
|
-
You can import the `ToleranceType` class directly from `cloud`:
|
|
223
|
-
|
|
224
|
-
```python
|
|
225
|
-
from nextmv.cloud import ToleranceType
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
This enumeration defines the different types of tolerances that can be used
|
|
229
|
-
when comparing metrics in acceptance tests.
|
|
230
|
-
|
|
231
|
-
Attributes
|
|
232
|
-
----------
|
|
233
|
-
undefined : str
|
|
234
|
-
Undefined tolerance type (empty string).
|
|
235
|
-
absolute : str
|
|
236
|
-
Absolute tolerance type, using a fixed value.
|
|
237
|
-
relative : str
|
|
238
|
-
Relative tolerance type, using a percentage.
|
|
239
|
-
|
|
240
|
-
Examples
|
|
241
|
-
--------
|
|
242
|
-
>>> from nextmv.cloud import ToleranceType
|
|
243
|
-
>>> tol_type = ToleranceType.absolute
|
|
244
|
-
>>> tol_type
|
|
245
|
-
<ToleranceType.absolute: 'absolute'>
|
|
246
|
-
"""
|
|
247
|
-
|
|
248
|
-
undefined = ""
|
|
249
|
-
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
250
|
-
Undefined tolerance type."""
|
|
251
|
-
absolute = "absolute"
|
|
252
|
-
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
253
|
-
Absolute tolerance type."""
|
|
254
|
-
relative = "relative"
|
|
255
|
-
"""ToleranceType is deprecated, please use MetricToleranceType instead.
|
|
256
|
-
Relative tolerance type."""
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
# Override __getattribute__ to emit deprecation warnings when enum values are accessed
|
|
260
|
-
_original_getattribute = ToleranceType.__class__.__getattribute__
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
def _deprecated_getattribute(cls, name: str):
|
|
264
|
-
# Only emit deprecation warning if this is specifically the ToleranceType class
|
|
265
|
-
if cls is ToleranceType and name in ("undefined", "absolute", "relative"):
|
|
266
|
-
deprecated(
|
|
267
|
-
f"ToleranceType.{name}",
|
|
268
|
-
"ToleranceType is deprecated and will be removed in a future version. "
|
|
269
|
-
"Please use MetricToleranceType instead",
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
return _original_getattribute(cls, name)
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
ToleranceType.__class__.__getattribute__ = _deprecated_getattribute
|
|
276
|
-
|
|
277
|
-
|
|
278
214
|
class MetricToleranceType(str, Enum):
|
|
279
215
|
"""
|
|
280
216
|
Type of tolerance used for a metric.
|
nextmv/cloud/account.py
CHANGED
|
@@ -21,7 +21,7 @@ from pydantic import AliasChoices, Field
|
|
|
21
21
|
|
|
22
22
|
from nextmv.base_model import BaseModel
|
|
23
23
|
from nextmv.cloud.client import Client
|
|
24
|
-
from nextmv.status import
|
|
24
|
+
from nextmv.status import StatusV2
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class QueuedRun(BaseModel):
|
|
@@ -57,8 +57,6 @@ class QueuedRun(BaseModel):
|
|
|
57
57
|
ID of the application version used for the run.
|
|
58
58
|
execution_class : str
|
|
59
59
|
Execution class used for the run.
|
|
60
|
-
status : Status
|
|
61
|
-
Deprecated: use status_v2.
|
|
62
60
|
status_v2 : StatusV2
|
|
63
61
|
Status of the run.
|
|
64
62
|
|
|
@@ -74,7 +72,6 @@ class QueuedRun(BaseModel):
|
|
|
74
72
|
... "application_instance_id": "appins-123456",
|
|
75
73
|
... "application_version_id": "appver-123456",
|
|
76
74
|
... "execution_class": "standard",
|
|
77
|
-
... "status": "RUNNING",
|
|
78
75
|
... "status_v2": "RUNNING"
|
|
79
76
|
... })
|
|
80
77
|
>>> print(queued_run.name)
|
|
@@ -99,8 +96,6 @@ class QueuedRun(BaseModel):
|
|
|
99
96
|
"""ID of the application version used for the run."""
|
|
100
97
|
execution_class: str
|
|
101
98
|
"""Execution class used for the run."""
|
|
102
|
-
status: Status
|
|
103
|
-
"""Deprecated: use status_v2."""
|
|
104
99
|
status_v2: StatusV2
|
|
105
100
|
"""Status of the run."""
|
|
106
101
|
|
|
@@ -867,6 +867,8 @@ class Application(
|
|
|
867
867
|
output_config = multi_config["output_configuration"] = {}
|
|
868
868
|
if content.multi_file.output.statistics:
|
|
869
869
|
output_config["statistics_path"] = content.multi_file.output.statistics
|
|
870
|
+
if content.multi_file.output.metrics:
|
|
871
|
+
output_config["metrics_path"] = content.multi_file.output.metrics
|
|
870
872
|
if content.multi_file.output.assets:
|
|
871
873
|
output_config["assets_path"] = content.multi_file.output.assets
|
|
872
874
|
if content.multi_file.output.solutions:
|
|
@@ -10,7 +10,6 @@ from nextmv.cloud.batch_experiment import (
|
|
|
10
10
|
BatchExperimentMetadata,
|
|
11
11
|
BatchExperimentRun,
|
|
12
12
|
ExperimentStatus,
|
|
13
|
-
to_runs,
|
|
14
13
|
)
|
|
15
14
|
from nextmv.cloud.input_set import InputSet, ManagedInput
|
|
16
15
|
from nextmv.cloud.scenario import Scenario, ScenarioInputType, _option_sets, _scenarios_by_id
|
|
@@ -258,7 +257,6 @@ class ApplicationBatchMixin:
|
|
|
258
257
|
self: "Application",
|
|
259
258
|
name: str | None = None,
|
|
260
259
|
input_set_id: str | None = None,
|
|
261
|
-
instance_ids: list[str] | None = None,
|
|
262
260
|
description: str | None = None,
|
|
263
261
|
id: str | None = None,
|
|
264
262
|
option_sets: dict[str, dict[str, str]] | None = None,
|
|
@@ -274,9 +272,6 @@ class ApplicationBatchMixin:
|
|
|
274
272
|
Name of the batch experiment. If not provided, the ID will be used as the name.
|
|
275
273
|
input_set_id: str | None
|
|
276
274
|
ID of the input set to use for the batch experiment.
|
|
277
|
-
instance_ids: list[str]
|
|
278
|
-
This argument is deprecated, use `runs` instead.
|
|
279
|
-
List of instance IDs to use for the batch experiment.
|
|
280
275
|
description: Optional[str]
|
|
281
276
|
Optional description of the batch experiment.
|
|
282
277
|
id: Optional[str]
|
|
@@ -308,7 +303,7 @@ class ApplicationBatchMixin:
|
|
|
308
303
|
id = safe_id("batch")
|
|
309
304
|
|
|
310
305
|
# Use ID as name if name not provided
|
|
311
|
-
if name is None:
|
|
306
|
+
if name is None or name == "":
|
|
312
307
|
name = id
|
|
313
308
|
|
|
314
309
|
payload = {
|
|
@@ -317,11 +312,6 @@ class ApplicationBatchMixin:
|
|
|
317
312
|
}
|
|
318
313
|
if input_set_id is not None:
|
|
319
314
|
payload["input_set_id"] = input_set_id
|
|
320
|
-
if instance_ids is not None:
|
|
321
|
-
input_set = self.input_set(input_set_id)
|
|
322
|
-
runs = to_runs(instance_ids, input_set)
|
|
323
|
-
payload_runs = [run.to_dict() for run in runs]
|
|
324
|
-
payload["runs"] = payload_runs
|
|
325
315
|
if description is not None:
|
|
326
316
|
payload["description"] = description
|
|
327
317
|
if option_sets is not None:
|
|
@@ -346,7 +336,6 @@ class ApplicationBatchMixin:
|
|
|
346
336
|
self: "Application",
|
|
347
337
|
name: str | None = None,
|
|
348
338
|
input_set_id: str | None = None,
|
|
349
|
-
instance_ids: list[str] | None = None,
|
|
350
339
|
description: str | None = None,
|
|
351
340
|
id: str | None = None,
|
|
352
341
|
option_sets: dict[str, dict[str, str]] | None = None,
|
|
@@ -368,9 +357,6 @@ class ApplicationBatchMixin:
|
|
|
368
357
|
Name of the batch experiment. If not provided, the ID will be used as the name.
|
|
369
358
|
input_set_id: str
|
|
370
359
|
ID of the input set to use for the batch experiment.
|
|
371
|
-
instance_ids: list[str]
|
|
372
|
-
List of instance IDs to use for the batch experiment. This argument
|
|
373
|
-
is deprecated, use `runs` instead.
|
|
374
360
|
description: Optional[str]
|
|
375
361
|
Optional description of the batch experiment.
|
|
376
362
|
id: Optional[str]
|
|
@@ -402,7 +388,6 @@ class ApplicationBatchMixin:
|
|
|
402
388
|
batch_id = self.new_batch_experiment(
|
|
403
389
|
name=name,
|
|
404
390
|
input_set_id=input_set_id,
|
|
405
|
-
instance_ids=instance_ids,
|
|
406
391
|
description=description,
|
|
407
392
|
id=id,
|
|
408
393
|
option_sets=option_sets,
|
|
@@ -485,7 +470,7 @@ class ApplicationBatchMixin:
|
|
|
485
470
|
id = safe_id("scenario")
|
|
486
471
|
|
|
487
472
|
# Use ID as name if name not provided
|
|
488
|
-
if name is None:
|
|
473
|
+
if name is None or name == "":
|
|
489
474
|
name = id
|
|
490
475
|
|
|
491
476
|
scenarios_by_id = _scenarios_by_id(scenarios)
|
nextmv/cloud/application/_run.py
CHANGED
|
@@ -21,7 +21,14 @@ from nextmv.cloud.url import DownloadURL
|
|
|
21
21
|
from nextmv.input import Input, InputFormat
|
|
22
22
|
from nextmv.logger import log
|
|
23
23
|
from nextmv.options import Options
|
|
24
|
-
from nextmv.output import
|
|
24
|
+
from nextmv.output import (
|
|
25
|
+
ASSETS_KEY,
|
|
26
|
+
STATISTICS_KEY,
|
|
27
|
+
Asset,
|
|
28
|
+
Output,
|
|
29
|
+
OutputFormat,
|
|
30
|
+
Statistics,
|
|
31
|
+
)
|
|
25
32
|
from nextmv.polling import DEFAULT_POLLING_OPTIONS, PollingOptions, poll
|
|
26
33
|
from nextmv.run import (
|
|
27
34
|
ExternalRunResult,
|
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/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
|
|