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.
@@ -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, intent: StopIntent) -> None:
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(
@@ -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, (dict, list)):
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."""
@@ -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
- statistics=nextmv.Statistics(
30
- result=nextmv.ResultStatistics(
31
- value=1.23,
32
- custom={"message": message},
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 ASSETS_KEY, OUTPUTS_KEY, SOLUTIONS_KEY, STATISTICS_KEY, Asset, OutputFormat, VisualSchema
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
@@ -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], (int, float)) and isinstance(coords[1], (int, float)):
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
- ... statistics="my-outputs/statistics.json",
844
+ ... metrics="my-outputs/metrics.json",
843
845
  ... assets="my-outputs/assets.json",
844
846
  ... solutions="my-outputs/solutions/"
845
847
  ... )
846
- >>> output_config.statistics
847
- 'my-outputs/statistics.json'
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
- ... statistics="my-outputs/statistics.json",
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
- ... statistics="my-outputs/statistics.json",
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
- ... statistics=nextroute_output.statistics.to_dict(),
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
- ... statistics={"processing_time": 0.5}
237
+ ... metrics={"processing_time": 0.5}
238
238
  ... )
239
239
  """
240
240
 
nextmv/options.py CHANGED
@@ -695,7 +695,7 @@ class Options:
695
695
  help=argparse.SUPPRESS,
696
696
  default="1",
697
697
  )
698
- args, _ = parser.parse_known_args()
698
+ args = parser.parse_args()
699
699
 
700
700
  for arg in vars(args):
701
701
  if arg == "fff" or arg == "f":
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 solution, including run metrics and result data.
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
- >>> run_stats = RunStatistics(duration=30.0, iterations=100)
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
- ... statistics=stats,
938
+ ... metrics=metrics,
926
939
  ... json_configurations={"indent": 4}
927
940
  ... )
928
941
  >>> output_dict = output.to_dict()
929
- >>> "solution" in output_dict and "statistics" in output_dict
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. If the statistics are not provided, an
976
- empty dictionary will be used.
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, Statistics
1232
+ >>> from nextmv.output import LocalOutputWriter, Output, Metrics
1197
1233
  >>> writer = LocalOutputWriter()
1198
- >>> output = Output(solution={"result": 42}, statistics=Statistics())
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.dev6
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'