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
nextmv/{cloud/run.py → run.py}
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
This module contains definitions for an app run.
|
|
2
3
|
|
|
3
4
|
Classes
|
|
4
5
|
-------
|
|
@@ -50,19 +51,19 @@ from pydantic import AliasChoices, Field
|
|
|
50
51
|
|
|
51
52
|
from nextmv._serialization import serialize_json
|
|
52
53
|
from nextmv.base_model import BaseModel
|
|
53
|
-
from nextmv.cloud.status import Status, StatusV2
|
|
54
54
|
from nextmv.input import Input, InputFormat
|
|
55
55
|
from nextmv.output import Output, OutputFormat
|
|
56
|
+
from nextmv.status import Status, StatusV2
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
def run_duration(start: Union[datetime, float], end: Union[datetime, float]) -> int:
|
|
59
60
|
"""
|
|
60
61
|
Calculate the duration of a run in milliseconds.
|
|
61
62
|
|
|
62
|
-
You can import the `run_duration` function directly from `
|
|
63
|
+
You can import the `run_duration` function directly from `nextmv`:
|
|
63
64
|
|
|
64
65
|
```python
|
|
65
|
-
from nextmv
|
|
66
|
+
from nextmv import run_duration
|
|
66
67
|
```
|
|
67
68
|
|
|
68
69
|
Parameters
|
|
@@ -116,16 +117,27 @@ class FormatInput(BaseModel):
|
|
|
116
117
|
"""
|
|
117
118
|
Input format for a run configuration.
|
|
118
119
|
|
|
119
|
-
You can import the `FormatInput` class directly from `
|
|
120
|
+
You can import the `FormatInput` class directly from `nextmv`:
|
|
120
121
|
|
|
121
122
|
```python
|
|
122
|
-
from nextmv
|
|
123
|
+
from nextmv import FormatInput
|
|
123
124
|
```
|
|
124
125
|
|
|
125
126
|
Parameters
|
|
126
127
|
----------
|
|
127
128
|
input_type : InputFormat, optional
|
|
128
129
|
Type of the input format. Defaults to `InputFormat.JSON`.
|
|
130
|
+
|
|
131
|
+
Examples
|
|
132
|
+
--------
|
|
133
|
+
>>> from nextmv import FormatInput, InputFormat
|
|
134
|
+
>>> format_input = FormatInput()
|
|
135
|
+
>>> format_input.input_type
|
|
136
|
+
<InputFormat.JSON: 'json'>
|
|
137
|
+
|
|
138
|
+
>>> format_input = FormatInput(input_type=InputFormat.TEXT)
|
|
139
|
+
>>> format_input.input_type
|
|
140
|
+
<InputFormat.TEXT: 'text'>
|
|
129
141
|
"""
|
|
130
142
|
|
|
131
143
|
input_type: InputFormat = Field(
|
|
@@ -140,16 +152,27 @@ class FormatOutput(BaseModel):
|
|
|
140
152
|
"""
|
|
141
153
|
Output format for a run configuration.
|
|
142
154
|
|
|
143
|
-
You can import the `FormatOutput` class directly from `
|
|
155
|
+
You can import the `FormatOutput` class directly from `nextmv`:
|
|
144
156
|
|
|
145
157
|
```python
|
|
146
|
-
from nextmv
|
|
158
|
+
from nextmv import FormatOutput
|
|
147
159
|
```
|
|
148
160
|
|
|
149
161
|
Parameters
|
|
150
162
|
----------
|
|
151
163
|
output_type : OutputFormat, optional
|
|
152
164
|
Type of the output format. Defaults to `OutputFormat.JSON`.
|
|
165
|
+
|
|
166
|
+
Examples
|
|
167
|
+
--------
|
|
168
|
+
>>> from nextmv import FormatOutput, OutputFormat
|
|
169
|
+
>>> format_output = FormatOutput()
|
|
170
|
+
>>> format_output.output_type
|
|
171
|
+
<OutputFormat.JSON: 'json'>
|
|
172
|
+
|
|
173
|
+
>>> format_output = FormatOutput(output_type=OutputFormat.CSV_ARCHIVE)
|
|
174
|
+
>>> format_output.output_type
|
|
175
|
+
<OutputFormat.CSV_ARCHIVE: 'csv_archive'>
|
|
153
176
|
"""
|
|
154
177
|
|
|
155
178
|
output_type: OutputFormat = Field(
|
|
@@ -164,16 +187,30 @@ class Format(BaseModel):
|
|
|
164
187
|
"""
|
|
165
188
|
Format for a run configuration.
|
|
166
189
|
|
|
167
|
-
You can import the `Format` class directly from `
|
|
190
|
+
You can import the `Format` class directly from `nextmv`:
|
|
168
191
|
|
|
169
192
|
```python
|
|
170
|
-
from nextmv
|
|
193
|
+
from nextmv import Format
|
|
171
194
|
```
|
|
172
195
|
|
|
173
196
|
Parameters
|
|
174
197
|
----------
|
|
175
198
|
format_input : FormatInput
|
|
176
199
|
Input format for the run configuration.
|
|
200
|
+
format_output : FormatOutput, optional
|
|
201
|
+
Output format for the run configuration. Defaults to None.
|
|
202
|
+
|
|
203
|
+
Examples
|
|
204
|
+
--------
|
|
205
|
+
>>> from nextmv import Format, FormatInput, FormatOutput, InputFormat, OutputFormat
|
|
206
|
+
>>> format_config = Format(
|
|
207
|
+
... format_input=FormatInput(input_type=InputFormat.JSON),
|
|
208
|
+
... format_output=FormatOutput(output_type=OutputFormat.JSON)
|
|
209
|
+
... )
|
|
210
|
+
>>> format_config.format_input.input_type
|
|
211
|
+
<InputFormat.JSON: 'json'>
|
|
212
|
+
>>> format_config.format_output.output_type
|
|
213
|
+
<OutputFormat.JSON: 'json'>
|
|
177
214
|
"""
|
|
178
215
|
|
|
179
216
|
format_input: FormatInput = Field(
|
|
@@ -193,10 +230,10 @@ class Metadata(BaseModel):
|
|
|
193
230
|
"""
|
|
194
231
|
Metadata of a run, whether it was successful or not.
|
|
195
232
|
|
|
196
|
-
You can import the `Metadata` class directly from `
|
|
233
|
+
You can import the `Metadata` class directly from `nextmv`:
|
|
197
234
|
|
|
198
235
|
```python
|
|
199
|
-
from nextmv
|
|
236
|
+
from nextmv import Metadata
|
|
200
237
|
```
|
|
201
238
|
|
|
202
239
|
Parameters
|
|
@@ -217,6 +254,8 @@ class Metadata(BaseModel):
|
|
|
217
254
|
Size of the input in bytes.
|
|
218
255
|
output_size : float
|
|
219
256
|
Size of the output in bytes.
|
|
257
|
+
format : Format
|
|
258
|
+
Format of the input and output of the run.
|
|
220
259
|
status : Status
|
|
221
260
|
Deprecated: use status_v2.
|
|
222
261
|
status_v2 : StatusV2
|
|
@@ -241,20 +280,21 @@ class Metadata(BaseModel):
|
|
|
241
280
|
"""Size of the output in bytes."""
|
|
242
281
|
format: Format
|
|
243
282
|
"""Format of the input and output of the run."""
|
|
244
|
-
status: Status
|
|
245
|
-
"""Deprecated: use status_v2."""
|
|
246
283
|
status_v2: StatusV2
|
|
247
284
|
"""Status of the run."""
|
|
248
285
|
|
|
286
|
+
status: Optional[Status] = None
|
|
287
|
+
"""Deprecated: use status_v2."""
|
|
288
|
+
|
|
249
289
|
|
|
250
290
|
class RunInformation(BaseModel):
|
|
251
291
|
"""
|
|
252
292
|
Information of a run.
|
|
253
293
|
|
|
254
|
-
You can import the `RunInformation` class directly from `
|
|
294
|
+
You can import the `RunInformation` class directly from `nextmv`:
|
|
255
295
|
|
|
256
296
|
```python
|
|
257
|
-
from nextmv
|
|
297
|
+
from nextmv import RunInformation
|
|
258
298
|
```
|
|
259
299
|
|
|
260
300
|
Parameters
|
|
@@ -284,16 +324,33 @@ class RunInformation(BaseModel):
|
|
|
284
324
|
user_email: str
|
|
285
325
|
"""Email of the user who submitted the run."""
|
|
286
326
|
console_url: str = Field(default="")
|
|
327
|
+
"""
|
|
328
|
+
URL to the run in the Nextmv console.
|
|
329
|
+
"""
|
|
330
|
+
synced_run_id: Optional[str] = None
|
|
331
|
+
"""
|
|
332
|
+
ID of the synced remote run, if applicable. When the `Application.sync`
|
|
333
|
+
method is used, this field marks the association between the local run
|
|
334
|
+
(`id`) and the remote run (`synced_run_id`). This field is None if the run
|
|
335
|
+
was not created using `Application.sync` or if the run has not been synced
|
|
336
|
+
yet.
|
|
337
|
+
"""
|
|
338
|
+
synced_at: Optional[datetime] = None
|
|
339
|
+
"""
|
|
340
|
+
Timestamp when the run was synced with the remote run. This field is
|
|
341
|
+
None if the run was not created using `Application.sync` or if the run
|
|
342
|
+
has not been synced yet.
|
|
343
|
+
"""
|
|
287
344
|
|
|
288
345
|
|
|
289
346
|
class ErrorLog(BaseModel):
|
|
290
347
|
"""
|
|
291
348
|
Error log of a run, when it was not successful.
|
|
292
349
|
|
|
293
|
-
You can import the `ErrorLog` class directly from `
|
|
350
|
+
You can import the `ErrorLog` class directly from `nextmv`:
|
|
294
351
|
|
|
295
352
|
```python
|
|
296
|
-
from nextmv
|
|
353
|
+
from nextmv import ErrorLog
|
|
297
354
|
```
|
|
298
355
|
|
|
299
356
|
Parameters
|
|
@@ -318,10 +375,10 @@ class RunResult(RunInformation):
|
|
|
318
375
|
"""
|
|
319
376
|
Result of a run, whether it was successful or not.
|
|
320
377
|
|
|
321
|
-
You can import the `RunResult` class directly from `
|
|
378
|
+
You can import the `RunResult` class directly from `nextmv`:
|
|
322
379
|
|
|
323
380
|
```python
|
|
324
|
-
from nextmv
|
|
381
|
+
from nextmv import RunResult
|
|
325
382
|
```
|
|
326
383
|
|
|
327
384
|
Parameters
|
|
@@ -344,16 +401,28 @@ class RunLog(BaseModel):
|
|
|
344
401
|
"""
|
|
345
402
|
Log of a run.
|
|
346
403
|
|
|
347
|
-
You can import the `RunLog` class directly from `
|
|
404
|
+
You can import the `RunLog` class directly from `nextmv`:
|
|
348
405
|
|
|
349
406
|
```python
|
|
350
|
-
from nextmv
|
|
407
|
+
from nextmv import RunLog
|
|
351
408
|
```
|
|
352
409
|
|
|
353
410
|
Parameters
|
|
354
411
|
----------
|
|
355
412
|
log : str
|
|
356
413
|
Log of the run.
|
|
414
|
+
|
|
415
|
+
Examples
|
|
416
|
+
--------
|
|
417
|
+
>>> from nextmv import RunLog
|
|
418
|
+
>>> run_log = RunLog(log="Optimization completed successfully")
|
|
419
|
+
>>> run_log.log
|
|
420
|
+
'Optimization completed successfully'
|
|
421
|
+
|
|
422
|
+
>>> # Multi-line log
|
|
423
|
+
>>> multi_line_log = RunLog(log="Starting optimization\\nProcessing data\\nCompleted")
|
|
424
|
+
>>> multi_line_log.log
|
|
425
|
+
'Starting optimization\\nProcessing data\\nCompleted'
|
|
357
426
|
"""
|
|
358
427
|
|
|
359
428
|
log: str
|
|
@@ -364,10 +433,10 @@ class RunType(str, Enum):
|
|
|
364
433
|
"""
|
|
365
434
|
The actual type of the run.
|
|
366
435
|
|
|
367
|
-
You can import the `RunType` class directly from `
|
|
436
|
+
You can import the `RunType` class directly from `nextmv`:
|
|
368
437
|
|
|
369
438
|
```python
|
|
370
|
-
from nextmv
|
|
439
|
+
from nextmv import RunType
|
|
371
440
|
```
|
|
372
441
|
|
|
373
442
|
Parameters
|
|
@@ -378,6 +447,24 @@ class RunType(str, Enum):
|
|
|
378
447
|
External run type.
|
|
379
448
|
ENSEMBLE : str
|
|
380
449
|
Ensemble run type.
|
|
450
|
+
|
|
451
|
+
Examples
|
|
452
|
+
--------
|
|
453
|
+
>>> from nextmv import RunType
|
|
454
|
+
>>> run_type = RunType.STANDARD
|
|
455
|
+
>>> run_type
|
|
456
|
+
<RunType.STANDARD: 'standard'>
|
|
457
|
+
>>> run_type.value
|
|
458
|
+
'standard'
|
|
459
|
+
|
|
460
|
+
>>> # Creating from string
|
|
461
|
+
>>> external_type = RunType("external")
|
|
462
|
+
>>> external_type
|
|
463
|
+
<RunType.EXTERNAL: 'external'>
|
|
464
|
+
|
|
465
|
+
>>> # All available types
|
|
466
|
+
>>> list(RunType)
|
|
467
|
+
[<RunType.STANDARD: 'standard'>, <RunType.EXTERNAL: 'external'>, <RunType.ENSEMBLE: 'ensemble'>]
|
|
381
468
|
"""
|
|
382
469
|
|
|
383
470
|
STANDARD = "standard"
|
|
@@ -393,10 +480,10 @@ class RunTypeConfiguration(BaseModel):
|
|
|
393
480
|
Defines the configuration for the type of the run that is being executed
|
|
394
481
|
on an application.
|
|
395
482
|
|
|
396
|
-
You can import the `RunTypeConfiguration` class directly from `
|
|
483
|
+
You can import the `RunTypeConfiguration` class directly from `nextmv`:
|
|
397
484
|
|
|
398
485
|
```python
|
|
399
|
-
from nextmv
|
|
486
|
+
from nextmv import RunTypeConfiguration
|
|
400
487
|
```
|
|
401
488
|
|
|
402
489
|
Parameters
|
|
@@ -407,6 +494,35 @@ class RunTypeConfiguration(BaseModel):
|
|
|
407
494
|
ID of the definition for the run type. Defaults to None.
|
|
408
495
|
reference_id : str, optional
|
|
409
496
|
ID of the reference for the run type. Defaults to None.
|
|
497
|
+
|
|
498
|
+
Examples
|
|
499
|
+
--------
|
|
500
|
+
>>> from nextmv import RunTypeConfiguration, RunType
|
|
501
|
+
>>> config = RunTypeConfiguration(run_type=RunType.STANDARD)
|
|
502
|
+
>>> config.run_type
|
|
503
|
+
<RunType.STANDARD: 'standard'>
|
|
504
|
+
>>> config.definition_id is None
|
|
505
|
+
True
|
|
506
|
+
|
|
507
|
+
>>> # External run with reference
|
|
508
|
+
>>> external_config = RunTypeConfiguration(
|
|
509
|
+
... run_type=RunType.EXTERNAL,
|
|
510
|
+
... reference_id="ref-12345"
|
|
511
|
+
... )
|
|
512
|
+
>>> external_config.run_type
|
|
513
|
+
<RunType.EXTERNAL: 'external'>
|
|
514
|
+
>>> external_config.reference_id
|
|
515
|
+
'ref-12345'
|
|
516
|
+
|
|
517
|
+
>>> # Ensemble run with definition
|
|
518
|
+
>>> ensemble_config = RunTypeConfiguration(
|
|
519
|
+
... run_type=RunType.ENSEMBLE,
|
|
520
|
+
... definition_id="def-67890"
|
|
521
|
+
... )
|
|
522
|
+
>>> ensemble_config.run_type
|
|
523
|
+
<RunType.ENSEMBLE: 'ensemble'>
|
|
524
|
+
>>> ensemble_config.definition_id
|
|
525
|
+
'def-67890'
|
|
410
526
|
"""
|
|
411
527
|
|
|
412
528
|
run_type: RunType = Field(
|
|
@@ -424,10 +540,10 @@ class RunQueuing(BaseModel):
|
|
|
424
540
|
"""
|
|
425
541
|
RunQueuing configuration for a run.
|
|
426
542
|
|
|
427
|
-
You can import the `RunQueuing` class directly from `
|
|
543
|
+
You can import the `RunQueuing` class directly from `nextmv`:
|
|
428
544
|
|
|
429
545
|
```python
|
|
430
|
-
from nextmv
|
|
546
|
+
from nextmv import RunQueuing
|
|
431
547
|
```
|
|
432
548
|
|
|
433
549
|
Parameters
|
|
@@ -438,6 +554,25 @@ class RunQueuing(BaseModel):
|
|
|
438
554
|
disabled : bool, optional
|
|
439
555
|
Whether the run should be queued, or not. If True, the run will not be
|
|
440
556
|
queued. If False, the run will be queued. Defaults to None.
|
|
557
|
+
|
|
558
|
+
Examples
|
|
559
|
+
--------
|
|
560
|
+
>>> from nextmv import RunQueuing
|
|
561
|
+
>>> queuing = RunQueuing(priority=1, disabled=False)
|
|
562
|
+
>>> queuing.priority
|
|
563
|
+
1
|
|
564
|
+
>>> queuing.disabled
|
|
565
|
+
False
|
|
566
|
+
|
|
567
|
+
>>> # High priority run
|
|
568
|
+
>>> high_priority = RunQueuing(priority=1)
|
|
569
|
+
>>> high_priority.priority
|
|
570
|
+
1
|
|
571
|
+
|
|
572
|
+
>>> # Disabled queuing
|
|
573
|
+
>>> no_queue = RunQueuing(disabled=True)
|
|
574
|
+
>>> no_queue.disabled
|
|
575
|
+
True
|
|
441
576
|
"""
|
|
442
577
|
|
|
443
578
|
priority: Optional[int] = None
|
|
@@ -473,10 +608,10 @@ class RunConfiguration(BaseModel):
|
|
|
473
608
|
"""
|
|
474
609
|
Configuration for an app run.
|
|
475
610
|
|
|
476
|
-
You can import the `RunConfiguration` class directly from `
|
|
611
|
+
You can import the `RunConfiguration` class directly from `nextmv`:
|
|
477
612
|
|
|
478
613
|
```python
|
|
479
|
-
from nextmv
|
|
614
|
+
from nextmv import RunConfiguration
|
|
480
615
|
```
|
|
481
616
|
|
|
482
617
|
Parameters
|
|
@@ -491,6 +626,23 @@ class RunConfiguration(BaseModel):
|
|
|
491
626
|
ID of the secrets collection to use for the run. Defaults to None.
|
|
492
627
|
queuing : RunQueuing, optional
|
|
493
628
|
Queuing configuration for the run. Defaults to None.
|
|
629
|
+
|
|
630
|
+
Examples
|
|
631
|
+
--------
|
|
632
|
+
>>> from nextmv import RunConfiguration, RunQueuing
|
|
633
|
+
>>> config = RunConfiguration(
|
|
634
|
+
... execution_class="large",
|
|
635
|
+
... queuing=RunQueuing(priority=1)
|
|
636
|
+
... )
|
|
637
|
+
>>> config.execution_class
|
|
638
|
+
'large'
|
|
639
|
+
>>> config.queuing.priority
|
|
640
|
+
1
|
|
641
|
+
|
|
642
|
+
>>> # Basic configuration
|
|
643
|
+
>>> basic_config = RunConfiguration()
|
|
644
|
+
>>> basic_config.format is None
|
|
645
|
+
True
|
|
494
646
|
"""
|
|
495
647
|
|
|
496
648
|
execution_class: Optional[str] = None
|
|
@@ -515,10 +667,28 @@ class RunConfiguration(BaseModel):
|
|
|
515
667
|
|
|
516
668
|
Parameters
|
|
517
669
|
----------
|
|
518
|
-
input : Input or dict[str, Any] or BaseModel or str
|
|
670
|
+
input : Input or dict[str, Any] or BaseModel or str
|
|
519
671
|
The input to use for resolving the run configuration.
|
|
520
672
|
dir_path : str, optional
|
|
521
673
|
The directory path where inputs can be loaded from.
|
|
674
|
+
|
|
675
|
+
Examples
|
|
676
|
+
--------
|
|
677
|
+
>>> from nextmv import RunConfiguration
|
|
678
|
+
>>> config = RunConfiguration()
|
|
679
|
+
>>> config.resolve({"key": "value"})
|
|
680
|
+
>>> config.format.format_input.input_type
|
|
681
|
+
<InputFormat.JSON: 'json'>
|
|
682
|
+
|
|
683
|
+
>>> config = RunConfiguration()
|
|
684
|
+
>>> config.resolve("text input")
|
|
685
|
+
>>> config.format.format_input.input_type
|
|
686
|
+
<InputFormat.TEXT: 'text'>
|
|
687
|
+
|
|
688
|
+
>>> config = RunConfiguration()
|
|
689
|
+
>>> config.resolve({}, dir_path="/path/to/files")
|
|
690
|
+
>>> config.format.format_input.input_type
|
|
691
|
+
<InputFormat.MULTI_FILE: 'multi_file'>
|
|
522
692
|
"""
|
|
523
693
|
|
|
524
694
|
# If the value is set by the user, do not change it.
|
|
@@ -560,10 +730,10 @@ class ExternalRunResult(BaseModel):
|
|
|
560
730
|
Result of a run used to configure a new application run as an
|
|
561
731
|
external one.
|
|
562
732
|
|
|
563
|
-
You can import the `ExternalRunResult` class directly from `
|
|
733
|
+
You can import the `ExternalRunResult` class directly from `nextmv`:
|
|
564
734
|
|
|
565
735
|
```python
|
|
566
|
-
from nextmv
|
|
736
|
+
from nextmv import ExternalRunResult
|
|
567
737
|
```
|
|
568
738
|
|
|
569
739
|
Parameters
|
|
@@ -578,6 +748,32 @@ class ExternalRunResult(BaseModel):
|
|
|
578
748
|
Error message of the run. Defaults to None.
|
|
579
749
|
execution_duration : int, optional
|
|
580
750
|
Duration of the run, in milliseconds. Defaults to None.
|
|
751
|
+
|
|
752
|
+
Examples
|
|
753
|
+
--------
|
|
754
|
+
>>> from nextmv import ExternalRunResult
|
|
755
|
+
>>> # Successful external run
|
|
756
|
+
>>> result = ExternalRunResult(
|
|
757
|
+
... output_upload_id="upload-12345",
|
|
758
|
+
... status="succeeded",
|
|
759
|
+
... execution_duration=5000
|
|
760
|
+
... )
|
|
761
|
+
>>> result.status
|
|
762
|
+
'succeeded'
|
|
763
|
+
>>> result.execution_duration
|
|
764
|
+
5000
|
|
765
|
+
|
|
766
|
+
>>> # Failed external run
|
|
767
|
+
>>> failed_result = ExternalRunResult(
|
|
768
|
+
... error_upload_id="error-67890",
|
|
769
|
+
... status="failed",
|
|
770
|
+
... error_message="Optimization failed due to invalid constraints",
|
|
771
|
+
... execution_duration=2000
|
|
772
|
+
... )
|
|
773
|
+
>>> failed_result.status
|
|
774
|
+
'failed'
|
|
775
|
+
>>> failed_result.error_message
|
|
776
|
+
'Optimization failed due to invalid constraints'
|
|
581
777
|
"""
|
|
582
778
|
|
|
583
779
|
output_upload_id: Optional[str] = None
|
|
@@ -610,10 +806,10 @@ class TrackedRunStatus(str, Enum):
|
|
|
610
806
|
"""
|
|
611
807
|
The status of a tracked run.
|
|
612
808
|
|
|
613
|
-
You can import the `TrackedRunStatus` class directly from `
|
|
809
|
+
You can import the `TrackedRunStatus` class directly from `nextmv`:
|
|
614
810
|
|
|
615
811
|
```python
|
|
616
|
-
from nextmv
|
|
812
|
+
from nextmv import TrackedRunStatus
|
|
617
813
|
```
|
|
618
814
|
|
|
619
815
|
Parameters
|
|
@@ -622,6 +818,24 @@ class TrackedRunStatus(str, Enum):
|
|
|
622
818
|
The run succeeded.
|
|
623
819
|
FAILED : str
|
|
624
820
|
The run failed.
|
|
821
|
+
|
|
822
|
+
Examples
|
|
823
|
+
--------
|
|
824
|
+
>>> from nextmv import TrackedRunStatus
|
|
825
|
+
>>> status = TrackedRunStatus.SUCCEEDED
|
|
826
|
+
>>> status
|
|
827
|
+
<TrackedRunStatus.SUCCEEDED: 'succeeded'>
|
|
828
|
+
>>> status.value
|
|
829
|
+
'succeeded'
|
|
830
|
+
|
|
831
|
+
>>> # Creating from string
|
|
832
|
+
>>> failed_status = TrackedRunStatus("failed")
|
|
833
|
+
>>> failed_status
|
|
834
|
+
<TrackedRunStatus.FAILED: 'failed'>
|
|
835
|
+
|
|
836
|
+
>>> # All available statuses
|
|
837
|
+
>>> list(TrackedRunStatus)
|
|
838
|
+
[<TrackedRunStatus.SUCCEEDED: 'succeeded'>, <TrackedRunStatus.FAILED: 'failed'>]
|
|
625
839
|
"""
|
|
626
840
|
|
|
627
841
|
SUCCEEDED = "succeeded"
|
|
@@ -635,24 +849,26 @@ class TrackedRun:
|
|
|
635
849
|
"""
|
|
636
850
|
An external run that is tracked in the Nextmv platform.
|
|
637
851
|
|
|
638
|
-
You can import the `TrackedRun` class directly from `
|
|
852
|
+
You can import the `TrackedRun` class directly from `nextmv`:
|
|
639
853
|
|
|
640
854
|
```python
|
|
641
|
-
from nextmv
|
|
855
|
+
from nextmv import TrackedRun
|
|
642
856
|
```
|
|
643
857
|
|
|
644
858
|
Parameters
|
|
645
859
|
----------
|
|
646
|
-
input : Input or dict[str, Any] or str
|
|
647
|
-
The input of the run being tracked. Please note that if the input
|
|
648
|
-
format is JSON, then the input data must be JSON serializable. This
|
|
649
|
-
field is required.
|
|
650
|
-
output : Output or dict[str, Any] or str
|
|
651
|
-
The output of the run being tracked. Please note that if the output
|
|
652
|
-
format is JSON, then the output data must be JSON serializable. This
|
|
653
|
-
field is required. Only JSON output_format is supported.
|
|
654
860
|
status : TrackedRunStatus
|
|
655
861
|
The status of the run being tracked. This field is required.
|
|
862
|
+
input : Input or dict[str, Any] or str, optional
|
|
863
|
+
The input of the run being tracked. Please note that if the input
|
|
864
|
+
format is JSON, then the input data must be JSON serializable. If both
|
|
865
|
+
`input` and `input_dir_path` are specified, the `input` is ignored, and
|
|
866
|
+
the files in the directory are used instead. Defaults to None.
|
|
867
|
+
output : Output or dict[str, Any] or str, optional
|
|
868
|
+
The output of the run being tracked. Please note that if the output
|
|
869
|
+
format is JSON, then the output data must be JSON serializable. If both
|
|
870
|
+
`output` and `output_dir_path` are specified, the `output` is ignored, and
|
|
871
|
+
the files in the directory are used instead. Defaults to None.
|
|
656
872
|
duration : int, optional
|
|
657
873
|
The duration of the run being tracked, in milliseconds. This field is
|
|
658
874
|
optional. Defaults to None.
|
|
@@ -663,6 +879,64 @@ class TrackedRun:
|
|
|
663
879
|
logs : list[str], optional
|
|
664
880
|
The logs of the run being tracked. Each element of the list is a line in
|
|
665
881
|
the log. This field is optional. Defaults to None.
|
|
882
|
+
name : str, optional
|
|
883
|
+
Optional name for the run being tracked. Defaults to None.
|
|
884
|
+
description : str, optional
|
|
885
|
+
Optional description for the run being tracked. Defaults to None.
|
|
886
|
+
input_dir_path : str, optional
|
|
887
|
+
Path to a directory containing input files. If specified, the calling
|
|
888
|
+
function will package the files in the directory into a tar file and upload
|
|
889
|
+
it as a large input. This is useful for non-JSON input formats, such as
|
|
890
|
+
when working with `CSV_ARCHIVE` or `MULTI_FILE`. If both `input` and
|
|
891
|
+
`input_dir_path` are specified, the `input` is ignored, and the files in
|
|
892
|
+
the directory are used instead. Defaults to None.
|
|
893
|
+
output_dir_path : str, optional
|
|
894
|
+
Path to a directory containing output files. If specified, the calling
|
|
895
|
+
function will package the files in the directory into a tar file and upload
|
|
896
|
+
it as a large output. This is useful for non-JSON output formats, such as
|
|
897
|
+
when working with `CSV_ARCHIVE` or `MULTI_FILE`. If both `output` and
|
|
898
|
+
`output_dir_path` are specified, the `output` is ignored, and the files
|
|
899
|
+
are saved in the directory instead. Defaults to None.
|
|
900
|
+
|
|
901
|
+
Examples
|
|
902
|
+
--------
|
|
903
|
+
>>> from nextmv import TrackedRun, TrackedRunStatus
|
|
904
|
+
>>> # Successful run
|
|
905
|
+
>>> run = TrackedRun(
|
|
906
|
+
... status=TrackedRunStatus.SUCCEEDED,
|
|
907
|
+
... input={"vehicles": 5, "locations": 10},
|
|
908
|
+
... output={"routes": [{"stops": [1, 2, 3]}]},
|
|
909
|
+
... duration=5000,
|
|
910
|
+
... name="test-run",
|
|
911
|
+
... description="A test optimization run"
|
|
912
|
+
... )
|
|
913
|
+
>>> run.status
|
|
914
|
+
<TrackedRunStatus.SUCCEEDED: 'succeeded'>
|
|
915
|
+
>>> run.duration
|
|
916
|
+
5000
|
|
917
|
+
|
|
918
|
+
>>> # Failed run with error
|
|
919
|
+
>>> failed_run = TrackedRun(
|
|
920
|
+
... status=TrackedRunStatus.FAILED,
|
|
921
|
+
... input={"vehicles": 0},
|
|
922
|
+
... error="No vehicles available for routing",
|
|
923
|
+
... duration=1000,
|
|
924
|
+
... logs=["Starting optimization", "Error: No vehicles found"]
|
|
925
|
+
... )
|
|
926
|
+
>>> failed_run.status
|
|
927
|
+
<TrackedRunStatus.FAILED: 'failed'>
|
|
928
|
+
>>> failed_run.error
|
|
929
|
+
'No vehicles available for routing'
|
|
930
|
+
|
|
931
|
+
>>> # Run with directory-based input/output
|
|
932
|
+
>>> dir_run = TrackedRun(
|
|
933
|
+
... status=TrackedRunStatus.SUCCEEDED,
|
|
934
|
+
... input_dir_path="/path/to/input/files",
|
|
935
|
+
... output_dir_path="/path/to/output/files",
|
|
936
|
+
... duration=10000
|
|
937
|
+
... )
|
|
938
|
+
>>> dir_run.input_dir_path
|
|
939
|
+
'/path/to/input/files'
|
|
666
940
|
|
|
667
941
|
Raises
|
|
668
942
|
------
|
|
@@ -672,13 +946,23 @@ class TrackedRun:
|
|
|
672
946
|
input/output dicts are not JSON serializable.
|
|
673
947
|
"""
|
|
674
948
|
|
|
675
|
-
input: Union[Input, dict[str, Any], str]
|
|
676
|
-
"""The input of the run being tracked."""
|
|
677
|
-
output: Union[Output, dict[str, Any], str]
|
|
678
|
-
"""The output of the run being tracked. Only JSON output_format is supported."""
|
|
679
949
|
status: TrackedRunStatus
|
|
680
950
|
"""The status of the run being tracked"""
|
|
681
951
|
|
|
952
|
+
input: Optional[Union[Input, dict[str, Any], str]] = None
|
|
953
|
+
"""
|
|
954
|
+
The input of the run being tracked. Please note that if the input
|
|
955
|
+
format is JSON, then the input data must be JSON serializable. If both
|
|
956
|
+
`input` and `input_dir_path` are specified, the `input` is ignored, and
|
|
957
|
+
the files in the directory are used instead.
|
|
958
|
+
"""
|
|
959
|
+
output: Optional[Union[Output, dict[str, Any], str]] = None
|
|
960
|
+
"""
|
|
961
|
+
The output of the run being tracked. Please note that if the output
|
|
962
|
+
format is JSON, then the output data must be JSON serializable. If both
|
|
963
|
+
`output` and `output_dir_path` are specified, the `output` is ignored, and
|
|
964
|
+
the files in the directory are used instead.
|
|
965
|
+
"""
|
|
682
966
|
duration: Optional[int] = None
|
|
683
967
|
"""The duration of the run being tracked, in milliseconds."""
|
|
684
968
|
error: Optional[str] = None
|
|
@@ -687,6 +971,32 @@ class TrackedRun:
|
|
|
687
971
|
logs: Optional[list[str]] = None
|
|
688
972
|
"""The logs of the run being tracked. Each element of the list is a line in
|
|
689
973
|
the log."""
|
|
974
|
+
name: Optional[str] = None
|
|
975
|
+
"""
|
|
976
|
+
Optional name for the run being tracked.
|
|
977
|
+
"""
|
|
978
|
+
description: Optional[str] = None
|
|
979
|
+
"""
|
|
980
|
+
Optional description for the run being tracked.
|
|
981
|
+
"""
|
|
982
|
+
input_dir_path: Optional[str] = None
|
|
983
|
+
"""
|
|
984
|
+
Path to a directory containing input files. If specified, the calling
|
|
985
|
+
function will package the files in the directory into a tar file and upload
|
|
986
|
+
it as a large input. This is useful for non-JSON input formats, such as
|
|
987
|
+
when working with `CSV_ARCHIVE` or `MULTI_FILE`. If both `input` and
|
|
988
|
+
`input_dir_path` are specified, the `input` is ignored, and the files in
|
|
989
|
+
the directory are used instead.
|
|
990
|
+
"""
|
|
991
|
+
output_dir_path: Optional[str] = None
|
|
992
|
+
"""
|
|
993
|
+
Path to a directory containing output files. If specified, the calling
|
|
994
|
+
function will package the files in the directory into a tar file and upload
|
|
995
|
+
it as a large output. This is useful for non-JSON output formats, such as
|
|
996
|
+
when working with `CSV_ARCHIVE` or `MULTI_FILE`. If both `output` and
|
|
997
|
+
`output_dir_path` are specified, the `output` is ignored, and the files
|
|
998
|
+
are saved in the directory instead.
|
|
999
|
+
"""
|
|
690
1000
|
|
|
691
1001
|
def __post_init__(self): # noqa: C901
|
|
692
1002
|
"""
|
|
@@ -708,8 +1018,10 @@ class TrackedRun:
|
|
|
708
1018
|
raise ValueError("Error message must be empty if the run succeeded.")
|
|
709
1019
|
|
|
710
1020
|
if isinstance(self.input, Input):
|
|
711
|
-
|
|
712
|
-
|
|
1021
|
+
try:
|
|
1022
|
+
_ = serialize_json(self.input.data)
|
|
1023
|
+
except (TypeError, OverflowError) as e:
|
|
1024
|
+
raise ValueError("Input.data is not JSON serializable") from e
|
|
713
1025
|
elif isinstance(self.input, dict):
|
|
714
1026
|
try:
|
|
715
1027
|
_ = serialize_json(self.input)
|
|
@@ -717,8 +1029,10 @@ class TrackedRun:
|
|
|
717
1029
|
raise ValueError("Input is dict[str, Any] but it is not JSON serializable") from e
|
|
718
1030
|
|
|
719
1031
|
if isinstance(self.output, Output):
|
|
720
|
-
|
|
721
|
-
|
|
1032
|
+
try:
|
|
1033
|
+
_ = serialize_json(self.output.data)
|
|
1034
|
+
except (TypeError, OverflowError) as e:
|
|
1035
|
+
raise ValueError("Output.data is not JSON serializable") from e
|
|
722
1036
|
elif isinstance(self.output, dict):
|
|
723
1037
|
try:
|
|
724
1038
|
_ = serialize_json(self.output)
|
|
@@ -737,6 +1051,29 @@ class TrackedRun:
|
|
|
737
1051
|
The logs as a single string. If no logs are present, an empty
|
|
738
1052
|
string is returned.
|
|
739
1053
|
|
|
1054
|
+
Examples
|
|
1055
|
+
--------
|
|
1056
|
+
>>> from nextmv import TrackedRun, TrackedRunStatus
|
|
1057
|
+
>>> run = TrackedRun(
|
|
1058
|
+
... status=TrackedRunStatus.SUCCEEDED,
|
|
1059
|
+
... logs=["Starting optimization", "Processing data", "Optimization complete"]
|
|
1060
|
+
... )
|
|
1061
|
+
>>> run.logs_text()
|
|
1062
|
+
'Starting optimization\\nProcessing data\\nOptimization complete'
|
|
1063
|
+
|
|
1064
|
+
>>> # Single string log
|
|
1065
|
+
>>> run_with_string_log = TrackedRun(
|
|
1066
|
+
... status=TrackedRunStatus.SUCCEEDED,
|
|
1067
|
+
... logs="Single log entry"
|
|
1068
|
+
... )
|
|
1069
|
+
>>> run_with_string_log.logs_text()
|
|
1070
|
+
'Single log entry'
|
|
1071
|
+
|
|
1072
|
+
>>> # No logs
|
|
1073
|
+
>>> run_no_logs = TrackedRun(status=TrackedRunStatus.SUCCEEDED)
|
|
1074
|
+
>>> run_no_logs.logs_text()
|
|
1075
|
+
''
|
|
1076
|
+
|
|
740
1077
|
Raises
|
|
741
1078
|
------
|
|
742
1079
|
TypeError
|