nextmv 0.33.0.dev0__py3-none-any.whl → 0.34.0__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/local/local.py CHANGED
@@ -36,7 +36,7 @@ LOGS_KEY = "logs"
36
36
  """
37
37
  Logs key constant used for identifying logs in the run output.
38
38
  """
39
- LOGS_FILE = "stderr.log"
39
+ LOGS_FILE = "logs.log"
40
40
  """
41
41
  Constant used for identifying the file used for logging.
42
42
  """
nextmv/manifest.py CHANGED
@@ -11,6 +11,8 @@ ManifestType
11
11
  Enum for application types based on programming language.
12
12
  ManifestRuntime
13
13
  Enum for runtime environments where apps run on Nextmv.
14
+ ManifestPythonArch
15
+ Enum for target architecture for bundling Python apps.
14
16
  ManifestBuild
15
17
  Class for build-specific attributes in the manifest.
16
18
  ManifestPythonModel
@@ -38,6 +40,11 @@ ManifestConfiguration
38
40
  Manifest
39
41
  Main class representing an app manifest for Nextmv.
40
42
 
43
+ Functions
44
+ ---------
45
+ default_python_manifest
46
+ Creates a default Python manifest as a starting point for applications.
47
+
41
48
  Constants
42
49
  --------
43
50
  MANIFEST_FILE_NAME
@@ -49,7 +56,7 @@ from enum import Enum
49
56
  from typing import Any, Optional, Union
50
57
 
51
58
  import yaml
52
- from pydantic import AliasChoices, Field
59
+ from pydantic import AliasChoices, Field, field_validator
53
60
 
54
61
  from nextmv.base_model import BaseModel
55
62
  from nextmv.input import InputFormat
@@ -166,6 +173,43 @@ class ManifestRuntime(str, Enum):
166
173
  Based on the python runtime, it provisions (pre-installs) the Hexaly solver
167
174
  to run Python applications.
168
175
  """
176
+ CUOPT = "ghcr.io/nextmv-io/runtime/cuopt:latest"
177
+ """
178
+ A runtime providing the NVIDIA cuOpt solver.
179
+ """
180
+
181
+
182
+ class ManifestPythonArch(str, Enum):
183
+ """
184
+ Target architecture for bundling Python apps.
185
+
186
+ You can import the `ManifestPythonArch` class directly from `nextmv`:
187
+
188
+ ```python
189
+ from nextmv import ManifestPythonArch
190
+ ```
191
+
192
+ Attributes
193
+ ----------
194
+ ARM64 : str
195
+ ARM 64-bit architecture.
196
+ AMD64 : str
197
+ AMD 64-bit architecture.
198
+
199
+ Examples
200
+ --------
201
+ >>> from nextmv import ManifestPythonArch
202
+ >>> arch = ManifestPythonArch.ARM64
203
+ >>> arch
204
+ <ManifestPythonArch.ARM64: 'arm64'>
205
+ >>> str(arch)
206
+ 'arm64'
207
+ """
208
+
209
+ ARM64 = "arm64"
210
+ """ARM 64-bit architecture."""
211
+ AMD64 = "amd64"
212
+ """AMD 64-bit architecture."""
169
213
 
170
214
 
171
215
  class ManifestBuild(BaseModel):
@@ -294,7 +338,7 @@ class ManifestPython(BaseModel):
294
338
 
295
339
  Parameters
296
340
  ----------
297
- pip_requirements : Optional[str], default=None
341
+ pip_requirements : Optional[Union[str, list[str]]], default=None
298
342
  Path to a requirements.txt file containing (additional) Python
299
343
  dependencies that will be bundled with the app. Alternatively, you can provide a
300
344
  list of strings, each representing a package to install, e.g.,
@@ -320,18 +364,66 @@ class ManifestPython(BaseModel):
320
364
  validation_alias=AliasChoices("pip-requirements", "pip_requirements"),
321
365
  default=None,
322
366
  )
323
- """Path to a requirements.txt file.
367
+ """
368
+ Path to a requirements.txt file or list of packages.
324
369
 
325
370
  Contains (additional) Python dependencies that will be bundled with the
326
- app.
371
+ app. Can be either a string path to a requirements.txt file or a list
372
+ of package specifications.
373
+ """
374
+ arch: Optional[ManifestPythonArch] = None
375
+ """
376
+ The architecture this model is meant to run on. One of "arm64" or "amd64". Uses
377
+ "arm64" if not specified.
378
+ """
379
+ version: Optional[Union[str, float]] = None
380
+ """
381
+ The Python version this model is meant to run with. Uses "3.11" if not specified.
327
382
  """
328
383
  model: Optional[ManifestPythonModel] = None
329
- """Information about an encoded decision model.
384
+ """
385
+ Information about an encoded decision model.
330
386
 
331
387
  As handled via mlflow. This information is used to load the decision model
332
388
  from the app bundle.
333
389
  """
334
390
 
391
+ @field_validator("version", mode="before")
392
+ @classmethod
393
+ def validate_version(cls, v: Optional[Union[str, float]]) -> Optional[str]:
394
+ """
395
+ Validate and convert the Python version field to a string.
396
+
397
+ This validator allows the version to be specified as either a float or string
398
+ in the manifest for convenience, but ensures it's stored internally as a string.
399
+
400
+ Parameters
401
+ ----------
402
+ v : Optional[Union[str, float]]
403
+ The version value to validate. Can be None, a string, or a float.
404
+
405
+ Returns
406
+ -------
407
+ Optional[str]
408
+ The version as a string, or None if the input was None.
409
+
410
+ Examples
411
+ --------
412
+ >>> ManifestPython.validate_version(3.11)
413
+ '3.11'
414
+ >>> ManifestPython.validate_version("3.11")
415
+ '3.11'
416
+ >>> ManifestPython.validate_version(None) is None
417
+ True
418
+ """
419
+ # We allow the version to be a float in the manifest for convenience, but we want
420
+ # to store it as a string internally.
421
+ if v is None:
422
+ return None
423
+ if isinstance(v, float):
424
+ return str(v)
425
+ return v
426
+
335
427
 
336
428
  class ManifestOptionUI(BaseModel):
337
429
  """
@@ -858,7 +950,23 @@ class ManifestContent(BaseModel):
858
950
  """Configuration for multi-file content format."""
859
951
 
860
952
  def model_post_init(self, __context) -> None:
861
- """Post-initialization to validate fields."""
953
+ """
954
+ Post-initialization validation to ensure format field contains valid values.
955
+
956
+ This method is automatically called by Pydantic after the model is initialized
957
+ to validate that the format field contains one of the acceptable values.
958
+
959
+ Parameters
960
+ ----------
961
+ __context : Any
962
+ Pydantic context (unused in this implementation).
963
+
964
+ Raises
965
+ ------
966
+ ValueError
967
+ If the format field contains an invalid value that is not one of the
968
+ acceptable formats (JSON, MULTI_FILE, or CSV_ARCHIVE).
969
+ """
862
970
  acceptable_formats = [InputFormat.JSON, InputFormat.MULTI_FILE, InputFormat.CSV_ARCHIVE]
863
971
  if self.format not in acceptable_formats:
864
972
  raise ValueError(f"Invalid format: {self.format}. Must be one of {acceptable_formats}.")
@@ -965,17 +1073,28 @@ class Manifest(BaseModel):
965
1073
  ['main.py', 'model_logic/']
966
1074
  """
967
1075
 
968
- files: list[str]
969
- """The files to include (or exclude) in the app. This is mandatory."""
970
-
1076
+ type: ManifestType = ManifestType.PYTHON
1077
+ """
1078
+ Type of application, based on the programming language. This is mandatory.
1079
+ """
971
1080
  runtime: ManifestRuntime = ManifestRuntime.PYTHON
972
1081
  """
973
1082
  The runtime to use for the app. It provides the environment in which the
974
1083
  app runs. This is mandatory.
975
1084
  """
976
- type: ManifestType = ManifestType.PYTHON
1085
+ python: Optional[ManifestPython] = None
977
1086
  """
978
- Type of application, based on the programming language. This is mandatory.
1087
+ Python-specific attributes. Only for Python apps. Contains further
1088
+ Python-specific attributes.
1089
+ """
1090
+ files: list[str] = Field(
1091
+ default_factory=list,
1092
+ )
1093
+ """The files to include (or exclude) in the app. This is mandatory."""
1094
+ configuration: Optional[ManifestConfiguration] = None
1095
+ """
1096
+ Configuration for the decision model. A list of options for the decision
1097
+ model. An option is a parameter that configures the decision model.
979
1098
  """
980
1099
  build: Optional[ManifestBuild] = None
981
1100
  """
@@ -1003,16 +1122,6 @@ class Manifest(BaseModel):
1003
1122
  process. This command is executed just before the app gets bundled and
1004
1123
  pushed (after the build command).
1005
1124
  """
1006
- python: Optional[ManifestPython] = None
1007
- """
1008
- Python-specific attributes. Only for Python apps. Contains further
1009
- Python-specific attributes.
1010
- """
1011
- configuration: Optional[ManifestConfiguration] = None
1012
- """
1013
- Configuration for the decision model. A list of options for the decision
1014
- model. An option is a parameter that configures the decision model.
1015
- """
1016
1125
  entrypoint: Optional[str] = None
1017
1126
  """
1018
1127
  Optional entrypoint for the decision model. When not specified, the
@@ -1024,8 +1133,33 @@ class Manifest(BaseModel):
1024
1133
  """
1025
1134
 
1026
1135
  def model_post_init(self, __context) -> None:
1136
+ """
1137
+ Post-initialization to set default entrypoint based on runtime if not specified.
1138
+
1139
+ This method is automatically called by Pydantic after the model is initialized.
1140
+ If no entrypoint is provided, it sets a default entrypoint based on the runtime:
1141
+ - Python runtimes (PYTHON, HEXALY, PYOMO, CUOPT): "./main.py"
1142
+ - DEFAULT runtime: "./main"
1143
+ - JAVA runtime: "./main.jar"
1144
+
1145
+ Parameters
1146
+ ----------
1147
+ __context : Any
1148
+ Pydantic context (unused in this implementation).
1149
+
1150
+ Raises
1151
+ ------
1152
+ ValueError
1153
+ If no entrypoint is provided and the runtime cannot be resolved to
1154
+ establish a default entrypoint.
1155
+ """
1027
1156
  if self.entrypoint is None:
1028
- if self.runtime in (ManifestRuntime.PYTHON, ManifestRuntime.HEXALY, ManifestRuntime.PYOMO):
1157
+ if self.runtime in (
1158
+ ManifestRuntime.PYTHON,
1159
+ ManifestRuntime.HEXALY,
1160
+ ManifestRuntime.PYOMO,
1161
+ ManifestRuntime.CUOPT,
1162
+ ):
1029
1163
  self.entrypoint = "./main.py"
1030
1164
  elif self.runtime == ManifestRuntime.DEFAULT:
1031
1165
  self.entrypoint = "./main"
@@ -1111,7 +1245,14 @@ class Manifest(BaseModel):
1111
1245
  """
1112
1246
 
1113
1247
  with open(os.path.join(dirpath, MANIFEST_FILE_NAME), "w") as file:
1114
- yaml.dump(self.to_dict(), file)
1248
+ yaml.dump(
1249
+ self.to_dict(),
1250
+ file,
1251
+ sort_keys=False,
1252
+ default_flow_style=False,
1253
+ indent=2,
1254
+ width=120,
1255
+ )
1115
1256
 
1116
1257
  def extract_options(self) -> Optional[Options]:
1117
1258
  """
@@ -1293,3 +1434,31 @@ class Manifest(BaseModel):
1293
1434
  )
1294
1435
 
1295
1436
  return manifest
1437
+
1438
+
1439
+ def default_python_manifest() -> Manifest:
1440
+ """
1441
+ Creates a default Python manifest as a starting point for applications
1442
+ being executed on the Nextmv Platform.
1443
+
1444
+ You can import the `default_python_manifest` function directly from `nextmv`:
1445
+
1446
+ ```python
1447
+ from nextmv import default_python_manifest
1448
+ ```
1449
+
1450
+ Returns
1451
+ -------
1452
+ Manifest
1453
+ A default Python manifest with common settings.
1454
+ """
1455
+
1456
+ m = Manifest(
1457
+ files=["main.py"],
1458
+ runtime=ManifestRuntime.PYTHON,
1459
+ type=ManifestType.PYTHON,
1460
+ python=ManifestPython(pip_requirements="requirements.txt"),
1461
+ )
1462
+ m.entrypoint = None # TODO: change this when we are ready for the entrypoint.
1463
+
1464
+ return m
nextmv/run.py CHANGED
@@ -52,7 +52,7 @@ from pydantic import AliasChoices, Field, field_validator
52
52
  from nextmv._serialization import serialize_json
53
53
  from nextmv.base_model import BaseModel
54
54
  from nextmv.input import Input, InputFormat
55
- from nextmv.output import Output, OutputFormat
55
+ from nextmv.output import Asset, Output, OutputFormat, Statistics
56
56
  from nextmv.status import Status, StatusV2
57
57
 
58
58
 
@@ -687,6 +687,56 @@ class Metadata(BaseModel):
687
687
  """Deprecated: use status_v2."""
688
688
 
689
689
 
690
+ class SyncedRun(BaseModel):
691
+ """
692
+ Information about a run that has been synced to a remote application.
693
+
694
+ You can import the `SyncedRun` class directly from `nextmv`:
695
+
696
+ ```python
697
+ from nextmv import SyncedRun
698
+ ```
699
+
700
+ Parameters
701
+ ----------
702
+ run_id : str
703
+ ID of the synced remote run. When the `Application.sync` method is
704
+ used, this field marks the association between the local run (`id`) and
705
+ the remote run (`synced_run.id`).
706
+ synced_at : datetime
707
+ Timestamp when the run was synced with the remote run.
708
+ app_id : str
709
+ The ID of the remote application that the local run was synced to.
710
+ instance_id : Optional[str], optional
711
+ The instance of the remote application that the local run was synced
712
+ to. This field is optional and may be None. If it is not specified, it
713
+ indicates that the run was synced against the default instance of the
714
+ app. Defaults to None.
715
+ """
716
+
717
+ run_id: str
718
+ """
719
+ ID of the synced remote run. When the `Application.sync` method is used,
720
+ this field marks the association between the local run (`id`) and the
721
+ remote run (`synced_run.id`)
722
+ """
723
+ synced_at: datetime
724
+ """
725
+ Timestamp when the run was synced with the remote run.
726
+ """
727
+ app_id: str
728
+ """
729
+ The ID of the remote application that the local run was synced to.
730
+ """
731
+
732
+ instance_id: Optional[str] = None
733
+ """
734
+ The instance of the remote application that the local run was synced to.
735
+ This field is optional and may be None. If it is not specified, it
736
+ indicates that the run was synced against the default instance of the app.
737
+ """
738
+
739
+
690
740
  class RunInformation(BaseModel):
691
741
  """
692
742
  Information of a run.
@@ -727,19 +777,18 @@ class RunInformation(BaseModel):
727
777
  """
728
778
  URL to the run in the Nextmv console.
729
779
  """
730
- synced_run_id: Optional[str] = None
731
- """
732
- ID of the synced remote run, if applicable. When the `Application.sync`
733
- method is used, this field marks the association between the local run
734
- (`id`) and the remote run (`synced_run_id`). This field is None if the run
735
- was not created using `Application.sync` or if the run has not been synced
736
- yet.
780
+ synced_runs: Optional[list[SyncedRun]] = None
737
781
  """
738
- synced_at: Optional[datetime] = None
739
- """
740
- Timestamp when the run was synced with the remote run. This field is
741
- None if the run was not created using `Application.sync` or if the run
742
- has not been synced yet.
782
+ List of synced runs associated with this run, if applicable. When the
783
+ `Application.sync` method is used, this field contains the associations
784
+ between the local run (`id`) and the remote runs (`synced_run.id`). This
785
+ field is None if the run was not created using `Application.sync` or if the
786
+ run has not been synced yet. It is possible to sync a single local run to
787
+ multiple remote runs. A remote run is identified by its application ID and
788
+ instance (if applicable). A local run cannot be synced to a remote run if
789
+ it is already present, this is, if there exists a record in the list with
790
+ the same application ID and instance. If there is not a repeated remote
791
+ run, a new record is added to the list.
743
792
  """
744
793
 
745
794
  def to_run(self) -> Run:
@@ -817,6 +866,83 @@ class RunInformation(BaseModel):
817
866
  input_set_id=None,
818
867
  )
819
868
 
869
+ def add_synced_run(self, synced_run: SyncedRun) -> bool:
870
+ """
871
+ Add a synced run to the RunInformation.
872
+
873
+ This method adds a `SyncedRun` instance to the list of synced runs
874
+ associated with this `RunInformation`. If the list is None, it
875
+ initializes it first. If the run has already been synced, then it is
876
+ not added to the list. A run is already synced if there exists a record
877
+ in the list with the same application ID. This method returns True if
878
+ the synced run was added, and False otherwise.
879
+
880
+ Parameters
881
+ ----------
882
+ synced_run : SyncedRun
883
+ The SyncedRun instance to add.
884
+
885
+ Returns
886
+ -------
887
+ bool
888
+ True if the synced run was added, False if it was already present.
889
+ """
890
+
891
+ if self.synced_runs is None:
892
+ self.synced_runs = [synced_run]
893
+
894
+ return True
895
+
896
+ if synced_run.instance_id is None:
897
+ for existing_run in self.synced_runs:
898
+ if existing_run.app_id == synced_run.app_id:
899
+ return False
900
+ else:
901
+ for existing_run in self.synced_runs:
902
+ if existing_run.app_id == synced_run.app_id and existing_run.instance_id == synced_run.instance_id:
903
+ return False
904
+
905
+ self.synced_runs.append(synced_run)
906
+
907
+ return True
908
+
909
+ def is_synced(self, app_id: str, instance_id: Optional[str] = None) -> tuple[SyncedRun, bool]:
910
+ """
911
+ Check if the run has been synced to a specific application and instance.
912
+
913
+ This method checks if there exists a `SyncedRun` in the list of synced
914
+ runs that matches the given application ID and optional instance ID.
915
+
916
+ Parameters
917
+ ----------
918
+ app_id : str
919
+ The application ID to check.
920
+ instance_id : Optional[str], optional
921
+ The instance ID to check. If None, only the application ID is
922
+ considered. Defaults to None.
923
+
924
+ Returns
925
+ -------
926
+ tuple[SyncedRun, bool]
927
+ A tuple containing the SyncedRun instance if found, and a boolean
928
+ indicating whether the run has been synced to the specified
929
+ application and instance.
930
+ """
931
+
932
+ if self.synced_runs is None:
933
+ return None, False
934
+
935
+ if instance_id is None:
936
+ for existing_run in self.synced_runs:
937
+ if existing_run.app_id == app_id:
938
+ return existing_run, True
939
+ else:
940
+ for existing_run in self.synced_runs:
941
+ if existing_run.app_id == app_id and existing_run.instance_id == instance_id:
942
+ return existing_run, True
943
+
944
+ return None, False
945
+
820
946
 
821
947
  class ErrorLog(BaseModel):
822
948
  """
@@ -1154,6 +1280,16 @@ class ExternalRunResult(BaseModel):
1154
1280
  """Error message of the run."""
1155
1281
  execution_duration: Optional[int] = None
1156
1282
  """Duration of the run, in milliseconds."""
1283
+ statistics_upload_id: Optional[str] = None
1284
+ """
1285
+ ID of the statistics upload. Use this field when working with `CSV_ARCHIVE`
1286
+ or `MULTI_FILE` output formats.
1287
+ """
1288
+ assets_upload_id: Optional[str] = None
1289
+ """
1290
+ ID of the assets upload. Use this field when working with `CSV_ARCHIVE`
1291
+ or `MULTI_FILE` output formats.
1292
+ """
1157
1293
 
1158
1294
  def __post_init_post_parse__(self):
1159
1295
  """
@@ -1265,6 +1401,18 @@ class TrackedRun:
1265
1401
  when working with `CSV_ARCHIVE` or `MULTI_FILE`. If both `output` and
1266
1402
  `output_dir_path` are specified, the `output` is ignored, and the files
1267
1403
  are saved in the directory instead. Defaults to None.
1404
+ statistics : Statistics or dict[str, Any], optional
1405
+ Statistics of the run being tracked. Only use this field if you want to
1406
+ track statistics for `CSV_ARCHIVE` or `MULTI_FILE` output formats. If you
1407
+ are working with `JSON` or `TEXT` output formats, this field will be
1408
+ ignored, as the statistics are extracted directly from the `output`.
1409
+ This field is optional. Defaults to None.
1410
+ assets : list[Asset or dict[str, Any]], optional
1411
+ Assets associated with the run being tracked. Only use this field if you
1412
+ want to track assets for `CSV_ARCHIVE` or `MULTI_FILE` output formats.
1413
+ If you are working with `JSON` or `TEXT` output formats, this field will
1414
+ be ignored, as the assets are extracted directly from the `output`.
1415
+ This field is optional. Defaults to None.
1268
1416
 
1269
1417
  Examples
1270
1418
  --------
@@ -1365,6 +1513,20 @@ class TrackedRun:
1365
1513
  `output_dir_path` are specified, the `output` is ignored, and the files
1366
1514
  are saved in the directory instead.
1367
1515
  """
1516
+ statistics: Optional[Union[Statistics, dict[str, Any]]] = None
1517
+ """
1518
+ Statistics of the run being tracked. Only use this field if you want to
1519
+ track statistics for `CSV_ARCHIVE` or `MULTI_FILE` output formats. If you
1520
+ are working with `JSON` or `TEXT` output formats, this field will be
1521
+ ignored, as the statistics are extracted directly from the `output`.
1522
+ """
1523
+ assets: Optional[list[Union[Asset, dict[str, Any]]]] = None
1524
+ """
1525
+ Assets associated with the run being tracked. Only use this field if you
1526
+ want to track assets for `CSV_ARCHIVE` or `MULTI_FILE` output formats.
1527
+ If you are working with `JSON` or `TEXT` output formats, this field will
1528
+ be ignored, as the assets are extracted directly from the `output`.
1529
+ """
1368
1530
 
1369
1531
  def __post_init__(self): # noqa: C901
1370
1532
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextmv
3
- Version: 0.33.0.dev0
3
+ Version: 0.34.0
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/
@@ -1,29 +1,29 @@
1
- nextmv/__about__.py,sha256=swx5y44doM60f9hpn91hbwEUw-qTWVfvgrZ4zO7sCP0,29
1
+ nextmv/__about__.py,sha256=R6JmJlUTOJ25ql5gmHiwKZDMDym2RLkSYwWgTeG9wAQ,24
2
2
  nextmv/__entrypoint__.py,sha256=dA0iwwHtrq6Z9w9FxmxKLoBGLyhe7jWtUAU-Y3PEgHg,1094
3
- nextmv/__init__.py,sha256=pW2HMcJnNSFqF_tj77TtqpddEeCosTKS7NxGNPDp7mU,3620
3
+ nextmv/__init__.py,sha256=C2f8MteVvvOX1Wj-0GFjfUt-0RzCT0zpLpLI2yyZQw8,3796
4
4
  nextmv/_serialization.py,sha256=JlSl6BL0M2Esf7F89GsGIZ__Pp8RnFRNM0UxYhuuYU4,2853
5
5
  nextmv/base_model.py,sha256=qmJ4AsYr9Yv01HQX_BERrn3229gyoZrYyP9tcyqNfeU,2311
6
6
  nextmv/deprecated.py,sha256=kEVfyQ-nT0v2ePXTNldjQG9uH5IlfQVy3L4tztIxwmU,1638
7
7
  nextmv/input.py,sha256=m9sVfO9ZL3F5i1l8amEtlWlbkekyUP4C3y9DduHWGFs,40211
8
8
  nextmv/logger.py,sha256=kNIbu46MisrzYe4T0hNMpWfRTKKacDVvbtQcNys_c_E,2513
9
- nextmv/manifest.py,sha256=wzGDrGleIgYvRvKyy73acjd68cGdCLD_7x_Dy3UhCaI,44266
9
+ nextmv/manifest.py,sha256=vo4GJk2yF6-6cA1M5YrynlXKqupH2vQE7HByph6ne4k,49256
10
10
  nextmv/model.py,sha256=vI3pSV3iTwjRPflar7nAg-6h98XRUyi9II5O2J06-Kc,15018
11
11
  nextmv/options.py,sha256=yPJu5lYMbV6YioMwAXv7ctpZUggLXKlZc9CqIbUFvE4,37895
12
12
  nextmv/output.py,sha256=HdvWYG3gIzwoXquulaEVI4LLchXJDjkbag0BkBPM0vQ,55128
13
13
  nextmv/polling.py,sha256=nfefvWI1smm-lIzaXE-4DMlojp6KXIvVi88XLJYUmo8,9724
14
- nextmv/run.py,sha256=lAWWkLml1C7wkXSvN8orBjudoz72Qv5ZCHCWY9e7xaY,45813
14
+ nextmv/run.py,sha256=8B9hh-jWJpoMSJiDmgmXaqvmzTicWCn75UTJu7Nf7Cs,52401
15
15
  nextmv/safe.py,sha256=VAK4fGEurbLNji4Pg5Okga5XQSbI4aI9JJf95_68Z20,3867
16
16
  nextmv/status.py,sha256=SCDLhh2om3yeO5FxO0x-_RShQsZNXEpjHNdCGdb3VUI,2787
17
17
  nextmv/cloud/__init__.py,sha256=2wI72lhWq81BYv1OpS0OOTT5-3sivpX0H4z5ANPoLMc,5051
18
- nextmv/cloud/acceptance_test.py,sha256=ZvOaVzhy3sHb5Vi9uBGhZJPggLN0oEmEvLKyc830zQ8,27439
18
+ nextmv/cloud/acceptance_test.py,sha256=ZEzCMrfJF-nUFr1nEr4IDgcoyavPhnanjFuPBJ79tAk,27731
19
19
  nextmv/cloud/account.py,sha256=jIdGNyI3l3dVh2PuriAwAOrEuWRM150WgzxcBMVBNRw,6058
20
- nextmv/cloud/application.py,sha256=wieXFWijmCsgEDpmefLWs010BkHMbAdLLV7Cwmncu5I,140555
20
+ nextmv/cloud/application.py,sha256=oUpw6I1r4u9Cn0pnlylWlm23hPgZKsg_vnBXbqTtU-w,139693
21
21
  nextmv/cloud/batch_experiment.py,sha256=13ciRpgBabMMTyazfdfEAymD3rTPrTAAorECsANxxuA,10397
22
22
  nextmv/cloud/client.py,sha256=E0DiUb377jvEnpXlRnfT1PGCI0Jm0lTUoX5VqeU91lk,18165
23
23
  nextmv/cloud/ensemble.py,sha256=glrRgyRFcEH12fNUhEl1FOo6xOTDEaF478dxfX0wj2Y,8604
24
24
  nextmv/cloud/input_set.py,sha256=NkzA6_hwgD-YwoirzwvZrObIoBTfurry7Os3jo4DyXc,4236
25
25
  nextmv/cloud/instance.py,sha256=SS4tbp0LQMWDaeYpwcNxJei82oi_Hozv1t5i3QGjASY,4024
26
- nextmv/cloud/package.py,sha256=cG75DptN4sxXaT8ruDh2EY2duaK5Jwg16X2LV0BP8ts,13021
26
+ nextmv/cloud/package.py,sha256=Xmt-daAeN9QJKpquV28IiZa2eYCX0P3wSS564JHvrtY,14495
27
27
  nextmv/cloud/scenario.py,sha256=JRFTDiFBcrgud6wE2qDHUu5oO-Ur3zbPYhhB6ONCxTo,14263
28
28
  nextmv/cloud/secrets.py,sha256=fA5cX0jfTsPVZWV7433wzETGlXpWRLHGswuObx9e6FQ,6820
29
29
  nextmv/cloud/url.py,sha256=Fz70ywkWdCLmP21ZBmJwZi5kDbjpmsX_VlwVF_xQeHg,1836
@@ -38,13 +38,13 @@ nextmv/default_app/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
38
38
  nextmv/default_app/src/main.py,sha256=WWeN_xl_mcPhICl3rSCvdEjRkFXGmAnej88FhS-fAmc,884
39
39
  nextmv/default_app/src/visuals.py,sha256=WYK_YBnLmYo3TpVev1CpoNCuW5R7hk9QIkeCmvMn1Fs,1014
40
40
  nextmv/local/__init__.py,sha256=6BsoqlK4dw6X11_uKzz9gBPfxKpdiol2FYO8R3X73SE,116
41
- nextmv/local/application.py,sha256=qq14ihKxymg5NHqhU56qTu6lVmMYWLGYUJC4MrhWB68,45815
42
- nextmv/local/executor.py,sha256=ohAUrIRohcH_qGglK1hSFR0W6bPBSuMAcMwVkW5G4vM,24338
41
+ nextmv/local/application.py,sha256=yJDlbQB_mh29Y541Mt6a6zyT3XutdtzjqSd0mlOeteo,47002
42
+ nextmv/local/executor.py,sha256=7rxVkpyZ4GyTH7hjJX7rdM0hCo7_fSqX4EiA8YHZpC8,36624
43
43
  nextmv/local/geojson_handler.py,sha256=7FavJdkUonop-yskjis0x3qFGB8A5wZyoBUblw-bVhw,12540
44
- nextmv/local/local.py,sha256=wUHuoAXqJIZpTJBh056hmQuiPEjlZvLTR2BC6Ino-WI,2619
44
+ nextmv/local/local.py,sha256=cp56UpI8h19Ob6Jvb_Ni0ceXH5Vv3ET_iPTDe6ftq3Y,2617
45
45
  nextmv/local/plotly_handler.py,sha256=bLb50e3AkVr_W-F6S7lXfeRdN60mG2jk3UElNmhoMWU,1930
46
46
  nextmv/local/runner.py,sha256=hwkITHrQG_J9TzxufnaP1mjLWG-iSsNQD66UFZY4pp4,8602
47
- nextmv-0.33.0.dev0.dist-info/METADATA,sha256=GU6x---pvDI4R1SBV9BW1J5fVLLPxllbrccj6kLyApA,16013
48
- nextmv-0.33.0.dev0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- nextmv-0.33.0.dev0.dist-info/licenses/LICENSE,sha256=ZIbK-sSWA-OZprjNbmJAglYRtl5_K4l9UwAV3PGJAPc,11349
50
- nextmv-0.33.0.dev0.dist-info/RECORD,,
47
+ nextmv-0.34.0.dist-info/METADATA,sha256=xaYGEjnGpH8t_ULjbHULvcEVtvMXNQ6B5Wx41tone0o,16008
48
+ nextmv-0.34.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
+ nextmv-0.34.0.dist-info/licenses/LICENSE,sha256=ZIbK-sSWA-OZprjNbmJAglYRtl5_K4l9UwAV3PGJAPc,11349
50
+ nextmv-0.34.0.dist-info/RECORD,,