nextmv 0.31.0__py3-none-any.whl → 0.33.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/runner.py CHANGED
@@ -11,8 +11,6 @@ new_run
11
11
  Function to initialize a new run.
12
12
  record_input
13
13
  Function to write the input to the appropriate location.
14
- calculate_files_size
15
- Function to calculate the total size of files in a directory.
16
14
  """
17
15
 
18
16
  import importlib.util
@@ -24,7 +22,8 @@ import sys
24
22
  from datetime import datetime, timezone
25
23
  from typing import Any, Optional, Union
26
24
 
27
- from nextmv.input import DEFAULT_INPUT_JSON_FILE, INPUTS_KEY
25
+ from nextmv.input import INPUTS_KEY
26
+ from nextmv.local.local import DEFAULT_INPUT_JSON_FILE, NEXTMV_DIR, RUNS_KEY, calculate_files_size
28
27
  from nextmv.manifest import Manifest
29
28
  from nextmv.run import Format, FormatInput, Metadata, RunInformation, StatusV2
30
29
  from nextmv.safe import safe_id
@@ -176,7 +175,7 @@ def new_run(
176
175
  """
177
176
 
178
177
  # First, ensure the runs directory exists.
179
- runs_dir = os.path.join(src, ".nextmv", "runs")
178
+ runs_dir = os.path.join(src, NEXTMV_DIR, RUNS_KEY)
180
179
  os.makedirs(runs_dir, exist_ok=True)
181
180
 
182
181
  # Create a new run directory.
@@ -273,40 +272,3 @@ def record_input(
273
272
 
274
273
  # Update the input size in the run information file.
275
274
  calculate_files_size(run_dir, run_id, run_inputs_dir, metadata_key="input_size")
276
-
277
-
278
- def calculate_files_size(run_dir: str, run_id: str, dir_path: str, metadata_key: str) -> None:
279
- """
280
- Calculates the total size of the files in a directory, in bytes.
281
-
282
- The calculated size is stored in the run information metadata under the
283
- specified key.
284
-
285
- Parameters
286
- ----------
287
- run_dir : str
288
- The path to the run directory.
289
- run_id : str
290
- The ID of the run.
291
- dir_path : str
292
- The path to the directory whose size is to be calculated.
293
- metadata_key : str
294
- The key under which to store the calculated size in the run information
295
- metadata.
296
- """
297
-
298
- total_size = 0
299
- for dirpath, _, filenames in os.walk(dir_path):
300
- for f in filenames:
301
- fp = os.path.join(dirpath, f)
302
- # Skip if it is a symbolic link
303
- if not os.path.islink(fp):
304
- total_size += os.path.getsize(fp)
305
-
306
- info_file = os.path.join(run_dir, f"{run_id}.json")
307
- with open(info_file, "r+") as f:
308
- info = json.load(f)
309
- info["metadata"][metadata_key] = total_size
310
- f.seek(0)
311
- json.dump(info, f, indent=2)
312
- f.truncate()
nextmv/manifest.py CHANGED
@@ -49,7 +49,7 @@ from enum import Enum
49
49
  from typing import Any, Optional, Union
50
50
 
51
51
  import yaml
52
- from pydantic import AliasChoices, Field
52
+ from pydantic import AliasChoices, Field, field_validator
53
53
 
54
54
  from nextmv.base_model import BaseModel
55
55
  from nextmv.input import InputFormat
@@ -166,6 +166,43 @@ class ManifestRuntime(str, Enum):
166
166
  Based on the python runtime, it provisions (pre-installs) the Hexaly solver
167
167
  to run Python applications.
168
168
  """
169
+ CUOPT = "ghcr.io/nextmv-io/runtime/cuopt:latest"
170
+ """
171
+ A runtime providing the NVIDIA cuOpt solver.
172
+ """
173
+
174
+
175
+ class ManifestPythonArch(str, Enum):
176
+ """
177
+ Target architecture for bundling Python apps.
178
+
179
+ You can import the `ManifestPythonArch` class directly from `nextmv`:
180
+
181
+ ```python
182
+ from nextmv import ManifestPythonArch
183
+ ```
184
+
185
+ Attributes
186
+ ----------
187
+ ARM64 : str
188
+ ARM 64-bit architecture.
189
+ AMD64 : str
190
+ AMD 64-bit architecture.
191
+
192
+ Examples
193
+ --------
194
+ >>> from nextmv import ManifestPythonArch
195
+ >>> arch = ManifestPythonArch.ARM64
196
+ >>> arch
197
+ <ManifestPythonArch.ARM64: 'arm64'>
198
+ >>> str(arch)
199
+ 'arm64'
200
+ """
201
+
202
+ ARM64 = "arm64"
203
+ """ARM 64-bit architecture."""
204
+ AMD64 = "amd64"
205
+ """AMD 64-bit architecture."""
169
206
 
170
207
 
171
208
  class ManifestBuild(BaseModel):
@@ -325,6 +362,12 @@ class ManifestPython(BaseModel):
325
362
  Contains (additional) Python dependencies that will be bundled with the
326
363
  app.
327
364
  """
365
+ arch: Optional[ManifestPythonArch] = None
366
+ """The architecture this model is meant to run on. One of "arm64" or "amd64". Uses
367
+ "arm64" if not specified."""
368
+ version: Optional[Union[str, float]] = None
369
+ """The Python version this model is meant to run with. Uses "3.11" if not specified.
370
+ """
328
371
  model: Optional[ManifestPythonModel] = None
329
372
  """Information about an encoded decision model.
330
373
 
@@ -332,6 +375,17 @@ class ManifestPython(BaseModel):
332
375
  from the app bundle.
333
376
  """
334
377
 
378
+ @field_validator("version", mode="before")
379
+ @classmethod
380
+ def validate_version(cls, v: Optional[Union[str, float]]) -> Optional[str]:
381
+ # We allow the version to be a float in the manifest for convenience, but we want
382
+ # to store it as a string internally.
383
+ if v is None:
384
+ return None
385
+ if isinstance(v, float):
386
+ return str(v)
387
+ return v
388
+
335
389
 
336
390
  class ManifestOptionUI(BaseModel):
337
391
  """
@@ -1025,7 +1079,12 @@ class Manifest(BaseModel):
1025
1079
 
1026
1080
  def model_post_init(self, __context) -> None:
1027
1081
  if self.entrypoint is None:
1028
- if self.runtime in (ManifestRuntime.PYTHON, ManifestRuntime.HEXALY, ManifestRuntime.PYOMO):
1082
+ if self.runtime in (
1083
+ ManifestRuntime.PYTHON,
1084
+ ManifestRuntime.HEXALY,
1085
+ ManifestRuntime.PYOMO,
1086
+ ManifestRuntime.CUOPT,
1087
+ ):
1029
1088
  self.entrypoint = "./main.py"
1030
1089
  elif self.runtime == ManifestRuntime.DEFAULT:
1031
1090
  self.entrypoint = "./main"
nextmv/output.py CHANGED
@@ -41,20 +41,16 @@ Functions
41
41
  write
42
42
  Write the output to the specified destination.
43
43
 
44
- Constants
45
- ---------
46
- ASSETS_KEY
44
+ Attributes
45
+ ----------
46
+ ASSETS_KEY : str
47
47
  Assets key constant used for identifying assets in the run output.
48
- STATISTICS_KEY
48
+ STATISTICS_KEY : str
49
49
  Statistics key constant used for identifying statistics in the run output.
50
- SOLUTIONS_KEY
50
+ SOLUTIONS_KEY : str
51
51
  Solutions key constant used for identifying solutions in the run output.
52
- OUTPUTS_KEY
52
+ OUTPUTS_KEY : str
53
53
  Outputs key constant used for identifying outputs in the run output.
54
- LOGS_FILE
55
- Constant used for identifying the file used for logging.
56
- DEFAULT_OUTPUT_JSON_FILE
57
- Constant for the default output JSON file name.
58
54
  """
59
55
 
60
56
  import copy
@@ -90,22 +86,6 @@ OUTPUTS_KEY = "outputs"
90
86
  """
91
87
  Outputs key constant used for identifying outputs in the run output.
92
88
  """
93
- OUTPUT_KEY = "output"
94
- """
95
- Output key constant used for identifying output in the run output.
96
- """
97
- LOGS_KEY = "logs"
98
- """
99
- Logs key constant used for identifying logs in the run output.
100
- """
101
- LOGS_FILE = "stderr.log"
102
- """
103
- Constant used for identifying the file used for logging.
104
- """
105
- DEFAULT_OUTPUT_JSON_FILE = "solution.json"
106
- """
107
- Constant for the default output JSON file name.
108
- """
109
89
 
110
90
 
111
91
  class RunStatistics(BaseModel):