nextmv 0.30.0__py3-none-any.whl → 0.31.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/__about__.py +1 -1
- nextmv/__init__.py +40 -0
- nextmv/cloud/__init__.py +38 -33
- nextmv/cloud/account.py +1 -1
- nextmv/cloud/application.py +212 -481
- nextmv/cloud/input_set.py +1 -1
- nextmv/cloud/package.py +1 -1
- nextmv/cloud/url.py +73 -0
- nextmv/default_app/.gitignore +1 -0
- nextmv/default_app/app.yaml +2 -0
- nextmv/default_app/src/main.py +2 -1
- nextmv/input.py +17 -1
- nextmv/local/__init__.py +5 -0
- nextmv/local/application.py +1147 -0
- nextmv/local/executor.py +718 -0
- nextmv/local/geojson_handler.py +323 -0
- nextmv/local/plotly_handler.py +61 -0
- nextmv/local/runner.py +312 -0
- nextmv/{cloud/manifest.py → manifest.py} +110 -69
- nextmv/output.py +61 -8
- nextmv/polling.py +287 -0
- nextmv/{cloud/run.py → run.py} +390 -53
- nextmv/{cloud/safe.py → safe.py} +35 -3
- nextmv/{cloud/status.py → status.py} +9 -9
- {nextmv-0.30.0.dist-info → nextmv-0.31.0.dist-info}/METADATA +5 -1
- nextmv-0.31.0.dist-info/RECORD +46 -0
- nextmv-0.30.0.dist-info/RECORD +0 -37
- {nextmv-0.30.0.dist-info → nextmv-0.31.0.dist-info}/WHEEL +0 -0
- {nextmv-0.30.0.dist-info → nextmv-0.31.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Module with the logic for handling an app manifest.
|
|
2
3
|
|
|
3
4
|
This module provides classes and functions for managing Nextmv app manifests.
|
|
4
5
|
Manifest files (app.yaml) define how an application is built, run, and deployed
|
|
5
|
-
on the Nextmv
|
|
6
|
+
on the Nextmv platform.
|
|
6
7
|
|
|
7
8
|
Classes
|
|
8
9
|
-------
|
|
9
10
|
ManifestType
|
|
10
11
|
Enum for application types based on programming language.
|
|
11
12
|
ManifestRuntime
|
|
12
|
-
Enum for runtime environments where apps run on Nextmv
|
|
13
|
+
Enum for runtime environments where apps run on Nextmv.
|
|
13
14
|
ManifestBuild
|
|
14
15
|
Class for build-specific attributes in the manifest.
|
|
15
16
|
ManifestPythonModel
|
|
@@ -24,14 +25,22 @@ ManifestOptions
|
|
|
24
25
|
Class containing a list of options for the decision model.
|
|
25
26
|
ManifestValidation
|
|
26
27
|
Class for validation rules for options in the manifest.
|
|
28
|
+
ManifestContentMultiFileInput
|
|
29
|
+
Class for multi-file content format input configuration.
|
|
30
|
+
ManifestContentMultiFileOutput
|
|
31
|
+
Class for multi-file content format output configuration.
|
|
32
|
+
ManifestContentMultiFile
|
|
33
|
+
Class for multi-file content format configuration.
|
|
34
|
+
ManifestContent
|
|
35
|
+
Class for content configuration specifying how app input/output is handled.
|
|
27
36
|
ManifestConfiguration
|
|
28
37
|
Class for configuration settings for the decision model.
|
|
29
38
|
Manifest
|
|
30
|
-
Main class representing an app manifest for Nextmv
|
|
39
|
+
Main class representing an app manifest for Nextmv.
|
|
31
40
|
|
|
32
41
|
Constants
|
|
33
42
|
--------
|
|
34
|
-
|
|
43
|
+
MANIFEST_FILE_NAME
|
|
35
44
|
Name of the app manifest file.
|
|
36
45
|
"""
|
|
37
46
|
|
|
@@ -52,10 +61,10 @@ MANIFEST_FILE_NAME = "app.yaml"
|
|
|
52
61
|
|
|
53
62
|
This constant defines the standard filename for Nextmv app manifest files.
|
|
54
63
|
|
|
55
|
-
You can import the `
|
|
64
|
+
You can import the `MANIFEST_FILE_NAME` constant directly from `nextmv`:
|
|
56
65
|
|
|
57
66
|
```python
|
|
58
|
-
from nextmv
|
|
67
|
+
from nextmv import MANIFEST_FILE_NAME
|
|
59
68
|
```
|
|
60
69
|
|
|
61
70
|
Notes
|
|
@@ -68,10 +77,10 @@ class ManifestType(str, Enum):
|
|
|
68
77
|
"""
|
|
69
78
|
Type of application in the manifest, based on the programming language.
|
|
70
79
|
|
|
71
|
-
You can import the `ManifestType` class directly from `
|
|
80
|
+
You can import the `ManifestType` class directly from `nextmv`:
|
|
72
81
|
|
|
73
82
|
```python
|
|
74
|
-
from nextmv
|
|
83
|
+
from nextmv import ManifestType
|
|
75
84
|
```
|
|
76
85
|
|
|
77
86
|
This enum defines the supported programming languages for applications
|
|
@@ -88,7 +97,7 @@ class ManifestType(str, Enum):
|
|
|
88
97
|
|
|
89
98
|
Examples
|
|
90
99
|
--------
|
|
91
|
-
>>> from nextmv
|
|
100
|
+
>>> from nextmv import ManifestType
|
|
92
101
|
>>> manifest_type = ManifestType.PYTHON
|
|
93
102
|
>>> manifest_type
|
|
94
103
|
<ManifestType.PYTHON: 'python'>
|
|
@@ -108,10 +117,10 @@ class ManifestRuntime(str, Enum):
|
|
|
108
117
|
"""
|
|
109
118
|
Runtime (environment) where the app will be run on Nextmv Cloud.
|
|
110
119
|
|
|
111
|
-
You can import the `ManifestRuntime` class directly from `
|
|
120
|
+
You can import the `ManifestRuntime` class directly from `nextmv`:
|
|
112
121
|
|
|
113
122
|
```python
|
|
114
|
-
from nextmv
|
|
123
|
+
from nextmv import ManifestRuntime
|
|
115
124
|
```
|
|
116
125
|
|
|
117
126
|
This enum defines the supported runtime environments for applications
|
|
@@ -133,7 +142,7 @@ class ManifestRuntime(str, Enum):
|
|
|
133
142
|
|
|
134
143
|
Examples
|
|
135
144
|
--------
|
|
136
|
-
>>> from nextmv
|
|
145
|
+
>>> from nextmv import ManifestRuntime
|
|
137
146
|
>>> runtime = ManifestRuntime.PYTHON
|
|
138
147
|
>>> runtime
|
|
139
148
|
<ManifestRuntime.PYTHON: 'ghcr.io/nextmv-io/runtime/python:3.11'>
|
|
@@ -163,10 +172,10 @@ class ManifestBuild(BaseModel):
|
|
|
163
172
|
"""
|
|
164
173
|
Build-specific attributes.
|
|
165
174
|
|
|
166
|
-
You can import the `ManifestBuild` class directly from `
|
|
175
|
+
You can import the `ManifestBuild` class directly from `nextmv`:
|
|
167
176
|
|
|
168
177
|
```python
|
|
169
|
-
from nextmv
|
|
178
|
+
from nextmv import ManifestBuild
|
|
170
179
|
```
|
|
171
180
|
|
|
172
181
|
Parameters
|
|
@@ -182,7 +191,7 @@ class ManifestBuild(BaseModel):
|
|
|
182
191
|
|
|
183
192
|
Examples
|
|
184
193
|
--------
|
|
185
|
-
>>> from nextmv
|
|
194
|
+
>>> from nextmv import ManifestBuild
|
|
186
195
|
>>> build_config = ManifestBuild(
|
|
187
196
|
... command="make build",
|
|
188
197
|
... environment={"DEBUG": "true"}
|
|
@@ -216,7 +225,7 @@ class ManifestBuild(BaseModel):
|
|
|
216
225
|
|
|
217
226
|
Examples
|
|
218
227
|
--------
|
|
219
|
-
>>> from nextmv
|
|
228
|
+
>>> from nextmv import ManifestBuild
|
|
220
229
|
>>> build_config = ManifestBuild(environment={"COUNT": 1, "NAME": "test"})
|
|
221
230
|
>>> build_config.environment_to_dict()
|
|
222
231
|
{'COUNT': '1', 'NAME': 'test'}
|
|
@@ -235,10 +244,10 @@ class ManifestPythonModel(BaseModel):
|
|
|
235
244
|
"""
|
|
236
245
|
Model-specific instructions for a Python app.
|
|
237
246
|
|
|
238
|
-
You can import the `ManifestPythonModel` class directly from `
|
|
247
|
+
You can import the `ManifestPythonModel` class directly from `nextmv`:
|
|
239
248
|
|
|
240
249
|
```python
|
|
241
|
-
from nextmv
|
|
250
|
+
from nextmv import ManifestPythonModel
|
|
242
251
|
```
|
|
243
252
|
|
|
244
253
|
Parameters
|
|
@@ -253,7 +262,7 @@ class ManifestPythonModel(BaseModel):
|
|
|
253
262
|
|
|
254
263
|
Examples
|
|
255
264
|
--------
|
|
256
|
-
>>> from nextmv
|
|
265
|
+
>>> from nextmv import ManifestPythonModel
|
|
257
266
|
>>> python_model_config = ManifestPythonModel(
|
|
258
267
|
... name="routing_model",
|
|
259
268
|
... options=[{"name": "max_vehicles", "type": "int", "default": 10}]
|
|
@@ -277,10 +286,10 @@ class ManifestPython(BaseModel):
|
|
|
277
286
|
"""
|
|
278
287
|
Python-specific instructions.
|
|
279
288
|
|
|
280
|
-
You can import the `ManifestPython` class directly from `
|
|
289
|
+
You can import the `ManifestPython` class directly from `nextmv`:
|
|
281
290
|
|
|
282
291
|
```python
|
|
283
|
-
from nextmv
|
|
292
|
+
from nextmv import ManifestPython
|
|
284
293
|
```
|
|
285
294
|
|
|
286
295
|
Parameters
|
|
@@ -297,7 +306,7 @@ class ManifestPython(BaseModel):
|
|
|
297
306
|
|
|
298
307
|
Examples
|
|
299
308
|
--------
|
|
300
|
-
>>> from nextmv
|
|
309
|
+
>>> from nextmv import ManifestPython, ManifestPythonModel
|
|
301
310
|
>>> python_config = ManifestPython(
|
|
302
311
|
... pip_requirements="requirements.txt",
|
|
303
312
|
... model=ManifestPythonModel(name="my_model")
|
|
@@ -328,10 +337,10 @@ class ManifestOptionUI(BaseModel):
|
|
|
328
337
|
"""
|
|
329
338
|
UI attributes for an option in the manifest.
|
|
330
339
|
|
|
331
|
-
You can import the `ManifestOptionUI` class directly from `
|
|
340
|
+
You can import the `ManifestOptionUI` class directly from `nextmv`:
|
|
332
341
|
|
|
333
342
|
```python
|
|
334
|
-
from nextmv
|
|
343
|
+
from nextmv import ManifestOptionUI
|
|
335
344
|
```
|
|
336
345
|
|
|
337
346
|
Parameters
|
|
@@ -343,7 +352,7 @@ class ManifestOptionUI(BaseModel):
|
|
|
343
352
|
"toggle". This attribute is not used in the local `Options` class, but
|
|
344
353
|
it is used in the Nextmv Cloud UI to define the type of control to use for
|
|
345
354
|
the option. This will be validated by the Nextmv Cloud, and availability
|
|
346
|
-
is based on
|
|
355
|
+
is based on option_type.
|
|
347
356
|
hidden_from : list[str], optional
|
|
348
357
|
A list of team roles to which this option will be hidden in the UI. For
|
|
349
358
|
example, if you want to hide an option from the "operator" role, you can
|
|
@@ -354,7 +363,7 @@ class ManifestOptionUI(BaseModel):
|
|
|
354
363
|
|
|
355
364
|
Examples
|
|
356
365
|
--------
|
|
357
|
-
>>> from nextmv
|
|
366
|
+
>>> from nextmv import ManifestOptionUI
|
|
358
367
|
>>> ui_config = ManifestOptionUI(control_type="input")
|
|
359
368
|
>>> ui_config.control_type
|
|
360
369
|
'input'
|
|
@@ -374,10 +383,10 @@ class ManifestOption(BaseModel):
|
|
|
374
383
|
"""
|
|
375
384
|
An option for the decision model that is recorded in the manifest.
|
|
376
385
|
|
|
377
|
-
You can import the `ManifestOption` class directly from `
|
|
386
|
+
You can import the `ManifestOption` class directly from `nextmv`:
|
|
378
387
|
|
|
379
388
|
```python
|
|
380
|
-
from nextmv
|
|
389
|
+
from nextmv import ManifestOption
|
|
381
390
|
```
|
|
382
391
|
|
|
383
392
|
Parameters
|
|
@@ -409,7 +418,7 @@ class ManifestOption(BaseModel):
|
|
|
409
418
|
|
|
410
419
|
Examples
|
|
411
420
|
--------
|
|
412
|
-
>>> from nextmv
|
|
421
|
+
>>> from nextmv import ManifestOption
|
|
413
422
|
>>> option = ManifestOption(
|
|
414
423
|
... name="solve.duration",
|
|
415
424
|
... option_type="string",
|
|
@@ -462,7 +471,7 @@ class ManifestOption(BaseModel):
|
|
|
462
471
|
Examples
|
|
463
472
|
--------
|
|
464
473
|
>>> from nextmv.options import Option
|
|
465
|
-
>>> from nextmv
|
|
474
|
+
>>> from nextmv import ManifestOption
|
|
466
475
|
>>> sdk_option = Option(name="max_stops", option_type=int, default=100)
|
|
467
476
|
>>> manifest_opt = ManifestOption.from_option(sdk_option)
|
|
468
477
|
>>> manifest_opt.name
|
|
@@ -514,7 +523,7 @@ class ManifestOption(BaseModel):
|
|
|
514
523
|
|
|
515
524
|
Examples
|
|
516
525
|
--------
|
|
517
|
-
>>> from nextmv
|
|
526
|
+
>>> from nextmv import ManifestOption
|
|
518
527
|
>>> manifest_opt = ManifestOption(name="max_stops", option_type="int", default=100)
|
|
519
528
|
>>> sdk_option = manifest_opt.to_option()
|
|
520
529
|
>>> sdk_option.name
|
|
@@ -552,10 +561,10 @@ class ManifestValidation(BaseModel):
|
|
|
552
561
|
"""
|
|
553
562
|
Validation rules for options in the manifest.
|
|
554
563
|
|
|
555
|
-
You can import the `ManifestValidation` class directly from `
|
|
564
|
+
You can import the `ManifestValidation` class directly from `nextmv`:
|
|
556
565
|
|
|
557
566
|
```python
|
|
558
|
-
from nextmv
|
|
567
|
+
from nextmv import ManifestValidation
|
|
559
568
|
```
|
|
560
569
|
|
|
561
570
|
Parameters
|
|
@@ -569,7 +578,7 @@ class ManifestValidation(BaseModel):
|
|
|
569
578
|
|
|
570
579
|
Examples
|
|
571
580
|
--------
|
|
572
|
-
>>> from nextmv
|
|
581
|
+
>>> from nextmv import ManifestValidation
|
|
573
582
|
>>> validation = ManifestValidation(enforce="all")
|
|
574
583
|
>>> validation.enforce
|
|
575
584
|
'all'
|
|
@@ -588,10 +597,10 @@ class ManifestOptions(BaseModel):
|
|
|
588
597
|
"""
|
|
589
598
|
Options for the decision model.
|
|
590
599
|
|
|
591
|
-
You can import the `ManifestOptions` class directly from `
|
|
600
|
+
You can import the `ManifestOptions` class directly from `nextmv`:
|
|
592
601
|
|
|
593
602
|
```python
|
|
594
|
-
from nextmv
|
|
603
|
+
from nextmv import ManifestOptions
|
|
595
604
|
```
|
|
596
605
|
|
|
597
606
|
Parameters
|
|
@@ -603,7 +612,7 @@ class ManifestOptions(BaseModel):
|
|
|
603
612
|
is a parameter that configures the decision model.
|
|
604
613
|
validation: Optional[ManifestValidation], default=None
|
|
605
614
|
Optional validation rules for all options.
|
|
606
|
-
format: Optional[list[str]], default=None
|
|
615
|
+
format : Optional[list[str]], default=None
|
|
607
616
|
A list of strings that define how options are transformed into command
|
|
608
617
|
line arguments. Use `{{name}}` to refer to the option name and
|
|
609
618
|
`{{value}}` to refer to the option value.
|
|
@@ -611,7 +620,7 @@ class ManifestOptions(BaseModel):
|
|
|
611
620
|
|
|
612
621
|
Examples
|
|
613
622
|
--------
|
|
614
|
-
>>> from nextmv
|
|
623
|
+
>>> from nextmv import ManifestOptions, ManifestOption
|
|
615
624
|
>>> options_config = ManifestOptions(
|
|
616
625
|
... strict=True,
|
|
617
626
|
... validation=ManifestValidation(enforce="all"),
|
|
@@ -677,7 +686,7 @@ class ManifestOptions(BaseModel):
|
|
|
677
686
|
Examples
|
|
678
687
|
--------
|
|
679
688
|
>>> from nextmv.options import Options, Option
|
|
680
|
-
>>> from nextmv
|
|
689
|
+
>>> from nextmv import ManifestOptions
|
|
681
690
|
>>> sdk_options = Options(Option("max_vehicles", int, 5))
|
|
682
691
|
>>> manifest_options = ManifestOptions.from_options(sdk_options)
|
|
683
692
|
>>> manifest_options.items[0].name
|
|
@@ -697,10 +706,10 @@ class ManifestContentMultiFileInput(BaseModel):
|
|
|
697
706
|
"""
|
|
698
707
|
Configuration for multi-file content format input.
|
|
699
708
|
|
|
700
|
-
You can import the `ManifestContentMultiFileInput` class directly from `
|
|
709
|
+
You can import the `ManifestContentMultiFileInput` class directly from `nextmv`:
|
|
701
710
|
|
|
702
711
|
```python
|
|
703
|
-
from nextmv
|
|
712
|
+
from nextmv import ManifestContentMultiFileInput
|
|
704
713
|
```
|
|
705
714
|
|
|
706
715
|
Parameters
|
|
@@ -711,7 +720,7 @@ class ManifestContentMultiFileInput(BaseModel):
|
|
|
711
720
|
|
|
712
721
|
Examples
|
|
713
722
|
--------
|
|
714
|
-
>>> from nextmv
|
|
723
|
+
>>> from nextmv import ManifestContentMultiFileInput
|
|
715
724
|
>>> input_config = ManifestContentMultiFileInput(path="data/input/")
|
|
716
725
|
>>> input_config.path
|
|
717
726
|
'data/input/'
|
|
@@ -725,10 +734,10 @@ class ManifestContentMultiFileOutput(BaseModel):
|
|
|
725
734
|
"""
|
|
726
735
|
Configuration for multi-file content format output.
|
|
727
736
|
|
|
728
|
-
You can import the `ManifestContentMultiFileOutput` class directly from `
|
|
737
|
+
You can import the `ManifestContentMultiFileOutput` class directly from `nextmv`:
|
|
729
738
|
|
|
730
739
|
```python
|
|
731
|
-
from nextmv
|
|
740
|
+
from nextmv import ManifestContentMultiFileOutput
|
|
732
741
|
```
|
|
733
742
|
|
|
734
743
|
Parameters
|
|
@@ -742,7 +751,7 @@ class ManifestContentMultiFileOutput(BaseModel):
|
|
|
742
751
|
|
|
743
752
|
Examples
|
|
744
753
|
--------
|
|
745
|
-
>>> from nextmv
|
|
754
|
+
>>> from nextmv import ManifestContentMultiFileOutput
|
|
746
755
|
>>> output_config = ManifestContentMultiFileOutput(
|
|
747
756
|
... statistics="my-outputs/statistics.json",
|
|
748
757
|
... assets="my-outputs/assets.json",
|
|
@@ -764,10 +773,10 @@ class ManifestContentMultiFile(BaseModel):
|
|
|
764
773
|
"""
|
|
765
774
|
Configuration for multi-file content format.
|
|
766
775
|
|
|
767
|
-
You can import the `ManifestContentMultiFile` class directly from `
|
|
776
|
+
You can import the `ManifestContentMultiFile` class directly from `nextmv`:
|
|
768
777
|
|
|
769
778
|
```python
|
|
770
|
-
from nextmv
|
|
779
|
+
from nextmv import ManifestContentMultiFile
|
|
771
780
|
```
|
|
772
781
|
|
|
773
782
|
Parameters
|
|
@@ -779,7 +788,7 @@ class ManifestContentMultiFile(BaseModel):
|
|
|
779
788
|
|
|
780
789
|
Examples
|
|
781
790
|
--------
|
|
782
|
-
>>> from nextmv
|
|
791
|
+
>>> from nextmv import ManifestContentMultiFile, ManifestContentMultiFileInput, ManifestContentMultiFileOutput
|
|
783
792
|
>>> multi_file_config = ManifestContentMultiFile(
|
|
784
793
|
... input=ManifestContentMultiFileInput(path="data/input/"),
|
|
785
794
|
... output=ManifestContentMultiFileOutput(
|
|
@@ -803,10 +812,10 @@ class ManifestContent(BaseModel):
|
|
|
803
812
|
"""
|
|
804
813
|
Content configuration for specifying how the app input/output is handled.
|
|
805
814
|
|
|
806
|
-
You can import the `ManifestContent` class directly from `
|
|
815
|
+
You can import the `ManifestContent` class directly from `nextmv`:
|
|
807
816
|
|
|
808
817
|
```python
|
|
809
|
-
from nextmv
|
|
818
|
+
from nextmv import ManifestContent
|
|
810
819
|
```
|
|
811
820
|
|
|
812
821
|
Parameters
|
|
@@ -818,7 +827,7 @@ class ManifestContent(BaseModel):
|
|
|
818
827
|
|
|
819
828
|
Examples
|
|
820
829
|
--------
|
|
821
|
-
>>> from nextmv
|
|
830
|
+
>>> from nextmv import ManifestContent
|
|
822
831
|
>>> content_config = ManifestContent(
|
|
823
832
|
... format="multi-file",
|
|
824
833
|
... multi_file=ManifestContentMultiFile(
|
|
@@ -836,9 +845,11 @@ class ManifestContent(BaseModel):
|
|
|
836
845
|
'data/input/'
|
|
837
846
|
"""
|
|
838
847
|
|
|
839
|
-
format:
|
|
840
|
-
"""
|
|
841
|
-
|
|
848
|
+
format: InputFormat
|
|
849
|
+
"""
|
|
850
|
+
The format of the content. Can only be `InputFormat.JSON`,
|
|
851
|
+
`InputFormat.MULTI_FILE`, or `InputFormat.CSV_ARCHIVE`.
|
|
852
|
+
"""
|
|
842
853
|
multi_file: Optional[ManifestContentMultiFile] = Field(
|
|
843
854
|
serialization_alias="multi-file",
|
|
844
855
|
validation_alias=AliasChoices("multi-file", "multi_file"),
|
|
@@ -846,7 +857,7 @@ class ManifestContent(BaseModel):
|
|
|
846
857
|
)
|
|
847
858
|
"""Configuration for multi-file content format."""
|
|
848
859
|
|
|
849
|
-
def
|
|
860
|
+
def model_post_init(self, __context) -> None:
|
|
850
861
|
"""Post-initialization to validate fields."""
|
|
851
862
|
acceptable_formats = [InputFormat.JSON, InputFormat.MULTI_FILE, InputFormat.CSV_ARCHIVE]
|
|
852
863
|
if self.format not in acceptable_formats:
|
|
@@ -857,10 +868,10 @@ class ManifestConfiguration(BaseModel):
|
|
|
857
868
|
"""
|
|
858
869
|
Configuration for the decision model.
|
|
859
870
|
|
|
860
|
-
You can import the `ManifestConfiguration` class directly from `
|
|
871
|
+
You can import the `ManifestConfiguration` class directly from `nextmv`:
|
|
861
872
|
|
|
862
873
|
```python
|
|
863
|
-
from nextmv
|
|
874
|
+
from nextmv import ManifestConfiguration
|
|
864
875
|
```
|
|
865
876
|
|
|
866
877
|
Parameters
|
|
@@ -870,7 +881,7 @@ class ManifestConfiguration(BaseModel):
|
|
|
870
881
|
|
|
871
882
|
Examples
|
|
872
883
|
--------
|
|
873
|
-
>>> from nextmv
|
|
884
|
+
>>> from nextmv import ManifestConfiguration, ManifestOptions, ManifestOption
|
|
874
885
|
>>> model_config = ManifestConfiguration(
|
|
875
886
|
... options=ManifestOptions(
|
|
876
887
|
... items=[ManifestOption(name="debug_mode", option_type="bool", default=False)]
|
|
@@ -890,10 +901,10 @@ class Manifest(BaseModel):
|
|
|
890
901
|
"""
|
|
891
902
|
Represents an app manifest (`app.yaml`) for Nextmv Cloud.
|
|
892
903
|
|
|
893
|
-
You can import the `Manifest` class directly from `
|
|
904
|
+
You can import the `Manifest` class directly from `nextmv`:
|
|
894
905
|
|
|
895
906
|
```python
|
|
896
|
-
from nextmv
|
|
907
|
+
from nextmv import Manifest
|
|
897
908
|
```
|
|
898
909
|
|
|
899
910
|
An application that runs on the Nextmv Platform must contain a file named
|
|
@@ -935,10 +946,16 @@ class Manifest(BaseModel):
|
|
|
935
946
|
configuration : Optional[ManifestConfiguration], default=None
|
|
936
947
|
A list of options for the decision model. An option is a
|
|
937
948
|
parameter that configures the decision model.
|
|
949
|
+
entrypoint : Optional[str], default=None
|
|
950
|
+
Optional entrypoint for the decision model. When not specified, the
|
|
951
|
+
following default entrypoints are used, according to the `.runtime`:
|
|
952
|
+
- `ManifestRuntime.PYTHON`, `ManifestRuntime.HEXALY`, `ManifestRuntime.PYOMO`: `./main.py`
|
|
953
|
+
- `ManifestRuntime.DEFAULT`: `./main`
|
|
954
|
+
- Java: `./main.jar`
|
|
938
955
|
|
|
939
956
|
Examples
|
|
940
957
|
--------
|
|
941
|
-
>>> from nextmv
|
|
958
|
+
>>> from nextmv import Manifest, ManifestRuntime, ManifestType
|
|
942
959
|
>>> manifest = Manifest(
|
|
943
960
|
... files=["main.py", "model_logic/"],
|
|
944
961
|
... runtime=ManifestRuntime.PYTHON,
|
|
@@ -996,6 +1013,29 @@ class Manifest(BaseModel):
|
|
|
996
1013
|
Configuration for the decision model. A list of options for the decision
|
|
997
1014
|
model. An option is a parameter that configures the decision model.
|
|
998
1015
|
"""
|
|
1016
|
+
entrypoint: Optional[str] = None
|
|
1017
|
+
"""
|
|
1018
|
+
Optional entrypoint for the decision model. When not specified, the
|
|
1019
|
+
following default entrypoints are used, according to the `.runtime`:
|
|
1020
|
+
|
|
1021
|
+
- `ManifestRuntime.PYTHON`, `ManifestRuntime.HEXALY`, `ManifestRuntime.PYOMO`: `./main.py`
|
|
1022
|
+
- `ManifestRuntime.DEFAULT`: `./main`
|
|
1023
|
+
- Java: `./main.jar`
|
|
1024
|
+
"""
|
|
1025
|
+
|
|
1026
|
+
def model_post_init(self, __context) -> None:
|
|
1027
|
+
if self.entrypoint is None:
|
|
1028
|
+
if self.runtime in (ManifestRuntime.PYTHON, ManifestRuntime.HEXALY, ManifestRuntime.PYOMO):
|
|
1029
|
+
self.entrypoint = "./main.py"
|
|
1030
|
+
elif self.runtime == ManifestRuntime.DEFAULT:
|
|
1031
|
+
self.entrypoint = "./main"
|
|
1032
|
+
elif self.runtime == ManifestRuntime.JAVA:
|
|
1033
|
+
self.entrypoint = "./main.jar"
|
|
1034
|
+
else:
|
|
1035
|
+
raise ValueError(
|
|
1036
|
+
f'entrypoint is not provided but the runtime "{self.runtime}" could not '
|
|
1037
|
+
"be resolved to establish a default entrypoint"
|
|
1038
|
+
)
|
|
999
1039
|
|
|
1000
1040
|
@classmethod
|
|
1001
1041
|
def from_yaml(cls, dirpath: str) -> "Manifest":
|
|
@@ -1034,7 +1074,7 @@ class Manifest(BaseModel):
|
|
|
1034
1074
|
type: python
|
|
1035
1075
|
```
|
|
1036
1076
|
|
|
1037
|
-
>>> from nextmv
|
|
1077
|
+
>>> from nextmv import Manifest
|
|
1038
1078
|
>>> # manifest = Manifest.from_yaml("./my_app_dir") # This would be run
|
|
1039
1079
|
>>> # assert manifest.type == "python"
|
|
1040
1080
|
"""
|
|
@@ -1065,7 +1105,7 @@ class Manifest(BaseModel):
|
|
|
1065
1105
|
|
|
1066
1106
|
Examples
|
|
1067
1107
|
--------
|
|
1068
|
-
>>> from nextmv
|
|
1108
|
+
>>> from nextmv import Manifest
|
|
1069
1109
|
>>> manifest = Manifest(files=["solver.py"], type="python")
|
|
1070
1110
|
>>> # manifest.to_yaml("./output_dir") # This would create ./output_dir/app.yaml
|
|
1071
1111
|
"""
|
|
@@ -1088,7 +1128,7 @@ class Manifest(BaseModel):
|
|
|
1088
1128
|
|
|
1089
1129
|
Examples
|
|
1090
1130
|
--------
|
|
1091
|
-
>>> from nextmv
|
|
1131
|
+
>>> from nextmv import Manifest, ManifestConfiguration, ManifestOptions, ManifestOption
|
|
1092
1132
|
>>> manifest = Manifest(
|
|
1093
1133
|
... files=["main.py"],
|
|
1094
1134
|
... configuration=ManifestConfiguration(
|
|
@@ -1150,8 +1190,9 @@ class Manifest(BaseModel):
|
|
|
1150
1190
|
|
|
1151
1191
|
Examples
|
|
1152
1192
|
--------
|
|
1153
|
-
>>> from nextmv.model import ModelConfiguration
|
|
1154
|
-
>>> from nextmv.
|
|
1193
|
+
>>> from nextmv.model import ModelConfiguration
|
|
1194
|
+
>>> from nextmv.options import Options, Option
|
|
1195
|
+
>>> from nextmv import Manifest
|
|
1155
1196
|
>>> opts = Options(Option(name="vehicle_count", option_type=int, default=5))
|
|
1156
1197
|
>>> mc = ModelConfiguration(name="vehicle_router", options=opts)
|
|
1157
1198
|
>>> manifest = Manifest.from_model_configuration(mc)
|
|
@@ -1213,7 +1254,7 @@ class Manifest(BaseModel):
|
|
|
1213
1254
|
----------
|
|
1214
1255
|
options : nextmv.options.Options
|
|
1215
1256
|
The options to include in the manifest.
|
|
1216
|
-
validation : nextmv.options.OptionsEnforcement default=None
|
|
1257
|
+
validation : nextmv.options.OptionsEnforcement, default=None
|
|
1217
1258
|
The validation rules for the options. This is used to set the
|
|
1218
1259
|
`validation` attribute of the `ManifestOptions`.
|
|
1219
1260
|
|
|
@@ -1225,7 +1266,7 @@ class Manifest(BaseModel):
|
|
|
1225
1266
|
Examples
|
|
1226
1267
|
--------
|
|
1227
1268
|
>>> from nextmv.options import Options, Option
|
|
1228
|
-
>>> from nextmv
|
|
1269
|
+
>>> from nextmv import Manifest
|
|
1229
1270
|
>>> opts = Options(
|
|
1230
1271
|
... Option(name="max_runtime", option_type=str, default="60s"),
|
|
1231
1272
|
... Option(name="use_heuristic", option_type=bool, default=True)
|
nextmv/output.py
CHANGED
|
@@ -40,6 +40,21 @@ Functions
|
|
|
40
40
|
---------
|
|
41
41
|
write
|
|
42
42
|
Write the output to the specified destination.
|
|
43
|
+
|
|
44
|
+
Constants
|
|
45
|
+
---------
|
|
46
|
+
ASSETS_KEY
|
|
47
|
+
Assets key constant used for identifying assets in the run output.
|
|
48
|
+
STATISTICS_KEY
|
|
49
|
+
Statistics key constant used for identifying statistics in the run output.
|
|
50
|
+
SOLUTIONS_KEY
|
|
51
|
+
Solutions key constant used for identifying solutions in the run output.
|
|
52
|
+
OUTPUTS_KEY
|
|
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.
|
|
43
58
|
"""
|
|
44
59
|
|
|
45
60
|
import copy
|
|
@@ -59,6 +74,39 @@ from nextmv.deprecated import deprecated
|
|
|
59
74
|
from nextmv.logger import reset_stdout
|
|
60
75
|
from nextmv.options import Options
|
|
61
76
|
|
|
77
|
+
ASSETS_KEY = "assets"
|
|
78
|
+
"""
|
|
79
|
+
Assets key constant used for identifying assets in the run output.
|
|
80
|
+
"""
|
|
81
|
+
STATISTICS_KEY = "statistics"
|
|
82
|
+
"""
|
|
83
|
+
Statistics key constant used for identifying statistics in the run output.
|
|
84
|
+
"""
|
|
85
|
+
SOLUTIONS_KEY = "solutions"
|
|
86
|
+
"""
|
|
87
|
+
Solutions key constant used for identifying solutions in the run output.
|
|
88
|
+
"""
|
|
89
|
+
OUTPUTS_KEY = "outputs"
|
|
90
|
+
"""
|
|
91
|
+
Outputs key constant used for identifying outputs in the run output.
|
|
92
|
+
"""
|
|
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
|
+
|
|
62
110
|
|
|
63
111
|
class RunStatistics(BaseModel):
|
|
64
112
|
"""
|
|
@@ -495,6 +543,8 @@ class OutputFormat(str, Enum):
|
|
|
495
543
|
CSV archive format: multiple CSV files.
|
|
496
544
|
MULTI_FILE : str
|
|
497
545
|
Multi-file format: multiple files in a directory.
|
|
546
|
+
TEXT : str
|
|
547
|
+
Text format, utf-8 encoded.
|
|
498
548
|
"""
|
|
499
549
|
|
|
500
550
|
JSON = "json"
|
|
@@ -503,6 +553,8 @@ class OutputFormat(str, Enum):
|
|
|
503
553
|
"""CSV archive format: multiple CSV files."""
|
|
504
554
|
MULTI_FILE = "multi-file"
|
|
505
555
|
"""Multi-file format: multiple files in a directory."""
|
|
556
|
+
TEXT = "text"
|
|
557
|
+
"""Text format, utf-8 encoded."""
|
|
506
558
|
|
|
507
559
|
|
|
508
560
|
@dataclass
|
|
@@ -1072,8 +1124,8 @@ class Output:
|
|
|
1072
1124
|
output_dict = {
|
|
1073
1125
|
"options": options,
|
|
1074
1126
|
"solution": self.solution if self.solution is not None else {},
|
|
1075
|
-
|
|
1076
|
-
|
|
1127
|
+
STATISTICS_KEY: statistics,
|
|
1128
|
+
ASSETS_KEY: assets,
|
|
1077
1129
|
}
|
|
1078
1130
|
|
|
1079
1131
|
# Add the auxiliary configurations to the output dictionary if they are
|
|
@@ -1232,8 +1284,8 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1232
1284
|
serialized = serialize_json(
|
|
1233
1285
|
{
|
|
1234
1286
|
"options": output_dict.get("options", {}),
|
|
1235
|
-
|
|
1236
|
-
|
|
1287
|
+
STATISTICS_KEY: output_dict.get(STATISTICS_KEY, {}),
|
|
1288
|
+
ASSETS_KEY: output_dict.get(ASSETS_KEY, []),
|
|
1237
1289
|
},
|
|
1238
1290
|
json_configurations=json_configurations,
|
|
1239
1291
|
)
|
|
@@ -1281,7 +1333,7 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1281
1333
|
ValueError
|
|
1282
1334
|
If the path is an existing file instead of a directory.
|
|
1283
1335
|
"""
|
|
1284
|
-
dir_path =
|
|
1336
|
+
dir_path = OUTPUTS_KEY
|
|
1285
1337
|
if path is not None and path != "":
|
|
1286
1338
|
if os.path.isfile(path):
|
|
1287
1339
|
raise ValueError(f"The path refers to an existing file: {path}")
|
|
@@ -1299,13 +1351,13 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1299
1351
|
parent_dir=dir_path,
|
|
1300
1352
|
json_configurations=json_configurations,
|
|
1301
1353
|
output_dict=output_dict,
|
|
1302
|
-
element_key=
|
|
1354
|
+
element_key=STATISTICS_KEY,
|
|
1303
1355
|
)
|
|
1304
1356
|
self._write_multi_file_element(
|
|
1305
1357
|
parent_dir=dir_path,
|
|
1306
1358
|
json_configurations=json_configurations,
|
|
1307
1359
|
output_dict=output_dict,
|
|
1308
|
-
element_key=
|
|
1360
|
+
element_key=ASSETS_KEY,
|
|
1309
1361
|
)
|
|
1310
1362
|
self._write_multi_file_solution(dir_path=dir_path, output=output)
|
|
1311
1363
|
|
|
@@ -1350,7 +1402,7 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1350
1402
|
if output.solution_files is None:
|
|
1351
1403
|
return
|
|
1352
1404
|
|
|
1353
|
-
solutions_dir = os.path.join(dir_path,
|
|
1405
|
+
solutions_dir = os.path.join(dir_path, SOLUTIONS_KEY)
|
|
1354
1406
|
|
|
1355
1407
|
if not os.path.exists(solutions_dir):
|
|
1356
1408
|
os.makedirs(solutions_dir)
|
|
@@ -1381,6 +1433,7 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1381
1433
|
OutputFormat.JSON: _write_json,
|
|
1382
1434
|
OutputFormat.CSV_ARCHIVE: _write_archive,
|
|
1383
1435
|
OutputFormat.MULTI_FILE: _write_multi_file,
|
|
1436
|
+
OutputFormat.TEXT: _write_json,
|
|
1384
1437
|
}
|
|
1385
1438
|
"""Dictionary mapping output formats to writer functions."""
|
|
1386
1439
|
|