nextmv 0.10.3.dev0__py3-none-any.whl → 0.35.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/__entrypoint__.py +39 -0
- nextmv/__init__.py +57 -0
- nextmv/_serialization.py +96 -0
- nextmv/base_model.py +79 -9
- nextmv/cloud/__init__.py +71 -10
- nextmv/cloud/acceptance_test.py +888 -17
- nextmv/cloud/account.py +154 -10
- nextmv/cloud/application.py +3644 -437
- nextmv/cloud/batch_experiment.py +292 -33
- nextmv/cloud/client.py +354 -53
- nextmv/cloud/ensemble.py +247 -0
- nextmv/cloud/input_set.py +121 -4
- nextmv/cloud/instance.py +125 -0
- nextmv/cloud/package.py +474 -0
- nextmv/cloud/scenario.py +410 -0
- nextmv/cloud/secrets.py +234 -0
- nextmv/cloud/url.py +73 -0
- nextmv/cloud/version.py +174 -0
- nextmv/default_app/.gitignore +1 -0
- nextmv/default_app/README.md +32 -0
- nextmv/default_app/app.yaml +12 -0
- nextmv/default_app/input.json +5 -0
- nextmv/default_app/main.py +37 -0
- nextmv/default_app/requirements.txt +2 -0
- nextmv/default_app/src/__init__.py +0 -0
- nextmv/default_app/src/main.py +37 -0
- nextmv/default_app/src/visuals.py +36 -0
- nextmv/deprecated.py +47 -0
- nextmv/input.py +883 -78
- nextmv/local/__init__.py +5 -0
- nextmv/local/application.py +1263 -0
- nextmv/local/executor.py +1040 -0
- nextmv/local/geojson_handler.py +323 -0
- nextmv/local/local.py +97 -0
- nextmv/local/plotly_handler.py +61 -0
- nextmv/local/runner.py +274 -0
- nextmv/logger.py +80 -9
- nextmv/manifest.py +1472 -0
- nextmv/model.py +431 -0
- nextmv/options.py +968 -78
- nextmv/output.py +1363 -231
- nextmv/polling.py +287 -0
- nextmv/run.py +1623 -0
- nextmv/safe.py +145 -0
- nextmv/status.py +122 -0
- {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/METADATA +51 -288
- nextmv-0.35.0.dist-info/RECORD +50 -0
- {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/WHEEL +1 -1
- nextmv/cloud/status.py +0 -29
- nextmv/nextroute/__init__.py +0 -2
- nextmv/nextroute/check/__init__.py +0 -26
- nextmv/nextroute/check/schema.py +0 -141
- nextmv/nextroute/schema/__init__.py +0 -19
- nextmv/nextroute/schema/input.py +0 -52
- nextmv/nextroute/schema/location.py +0 -13
- nextmv/nextroute/schema/output.py +0 -136
- nextmv/nextroute/schema/stop.py +0 -61
- nextmv/nextroute/schema/vehicle.py +0 -68
- nextmv-0.10.3.dev0.dist-info/RECORD +0 -28
- {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/licenses/LICENSE +0 -0
nextmv/safe.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
The safe module contains utilities for generating “safe” IDs and human-readable
|
|
4
|
+
names.
|
|
5
|
+
|
|
6
|
+
Functions
|
|
7
|
+
---------
|
|
8
|
+
safe_name_and_id
|
|
9
|
+
Generate a safe ID and human-readable name from a prefix and user-supplied
|
|
10
|
+
identifier.
|
|
11
|
+
safe_id
|
|
12
|
+
Generate a safe ID from a prefix.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import re
|
|
16
|
+
import secrets
|
|
17
|
+
import string
|
|
18
|
+
|
|
19
|
+
ENTITY_ID_CHAR_COUNT_MAX: int = 40
|
|
20
|
+
INDEX_TAG_CHAR_COUNT: int = 3 # room reserved for “-001”, “-xyz”, etc.
|
|
21
|
+
RE_NON_ALNUM = re.compile(r"[^A-Za-z0-9]+")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _kebab_case(value: str) -> str:
|
|
25
|
+
"""Convert arbitrary text to `kebab-case` (lower-case, hyphen-separated)."""
|
|
26
|
+
|
|
27
|
+
cleaned = RE_NON_ALNUM.sub(" ", value).strip()
|
|
28
|
+
return "-".join(word.lower() for word in cleaned.split())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _start_case(value: str) -> str:
|
|
32
|
+
"""Convert `kebab-case` (or any hyphen/underscore string) to `Start Case`."""
|
|
33
|
+
|
|
34
|
+
cleaned = re.sub(r"[-_]+", " ", value)
|
|
35
|
+
return " ".join(word.capitalize() for word in cleaned.split())
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _nanoid(size: int = 8, alphabet: str = string.ascii_lowercase + string.digits) -> str:
|
|
39
|
+
"""Simple nanoid clone using the std-lib `secrets` module."""
|
|
40
|
+
|
|
41
|
+
return "".join(secrets.choice(alphabet) for _ in range(size))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def safe_name_and_id(prefix: str, entity_id: str) -> tuple[str, str]:
|
|
45
|
+
"""
|
|
46
|
+
Generate a safe ID and human-readable name from a prefix and user-supplied
|
|
47
|
+
identifier.
|
|
48
|
+
|
|
49
|
+
You can import the `safe_name_and_id` function directly from `nextmv`:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from nextmv import safe_name_and_id
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
prefix : str
|
|
58
|
+
Prefix to use for the ID.
|
|
59
|
+
entity_id : str
|
|
60
|
+
User-supplied identifier. This will be converted to `kebab-case` and
|
|
61
|
+
truncated to fit within the safe ID length.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
tuple[str, str]
|
|
66
|
+
A tuple containing the human-readable name and the safe ID.
|
|
67
|
+
|
|
68
|
+
Examples
|
|
69
|
+
--------
|
|
70
|
+
>>> safe_name_and_id("app", "My Application 123!")
|
|
71
|
+
('App My Application 123', 'app-my-application-123-4f5g6h7j')
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
if not prefix or not entity_id:
|
|
75
|
+
return "", ""
|
|
76
|
+
|
|
77
|
+
safe_user_defined_id = _kebab_case(entity_id)
|
|
78
|
+
random_slug = _nanoid(8)
|
|
79
|
+
|
|
80
|
+
# Space available for user text once prefix, random slug and separator "-"
|
|
81
|
+
# are accounted for
|
|
82
|
+
safe_id_max = (
|
|
83
|
+
ENTITY_ID_CHAR_COUNT_MAX
|
|
84
|
+
- INDEX_TAG_CHAR_COUNT
|
|
85
|
+
- len(prefix)
|
|
86
|
+
- (len(random_slug) + 1) # +1 for the hyphen before the slug
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
safe_id_parts: list[str] = [prefix]
|
|
90
|
+
|
|
91
|
+
for word in safe_user_defined_id.split("-"):
|
|
92
|
+
# Trim individual word if it alone would overflow
|
|
93
|
+
safe_slug = word[: safe_id_max - 1] if len(word) > safe_id_max else word
|
|
94
|
+
|
|
95
|
+
# Will the combined ID (so far) overflow if we add this slug?
|
|
96
|
+
prospective_len = len("-".join(safe_id_parts + [safe_slug]))
|
|
97
|
+
if prospective_len >= safe_id_max:
|
|
98
|
+
break
|
|
99
|
+
safe_id_parts.append(safe_slug)
|
|
100
|
+
|
|
101
|
+
safe_id = "-".join(filter(None, safe_id_parts)) + f"-{random_slug}"
|
|
102
|
+
safe_name = _start_case(safe_id)
|
|
103
|
+
|
|
104
|
+
return safe_name, safe_id
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def safe_id(prefix: str) -> str:
|
|
108
|
+
"""
|
|
109
|
+
Generate a safe ID from a prefix.
|
|
110
|
+
|
|
111
|
+
You can import the `safe_id` function directly from `nextmv`:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from nextmv import safe_id
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
prefix : str
|
|
120
|
+
Prefix to use for the ID.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
str
|
|
125
|
+
A safe ID.
|
|
126
|
+
|
|
127
|
+
Examples
|
|
128
|
+
--------
|
|
129
|
+
>>> safe_id("app")
|
|
130
|
+
'app-4f5g6h7j'
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
random_slug = _nanoid(8)
|
|
134
|
+
# Space available for user text once prefix, random slug and separator "-"
|
|
135
|
+
# are accounted for
|
|
136
|
+
safe_id_max = (
|
|
137
|
+
ENTITY_ID_CHAR_COUNT_MAX - INDEX_TAG_CHAR_COUNT - (len(random_slug) + 1) # +1 for the hyphen before the slug
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if len(prefix) > safe_id_max:
|
|
141
|
+
return prefix[: safe_id_max - 1] + f"-{random_slug}"
|
|
142
|
+
|
|
143
|
+
safe_id = f"{prefix}-{random_slug}"
|
|
144
|
+
|
|
145
|
+
return safe_id
|
nextmv/status.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provides status enums for Nextmv application runs.
|
|
3
|
+
|
|
4
|
+
This module defines enumerations for representing the status of a run in a
|
|
5
|
+
Nextmv application. It includes a deprecated `Status` enum and the current
|
|
6
|
+
`StatusV2` enum.
|
|
7
|
+
|
|
8
|
+
Classes
|
|
9
|
+
-------
|
|
10
|
+
Status
|
|
11
|
+
Deprecated status of a run.
|
|
12
|
+
StatusV2
|
|
13
|
+
Represents the status of a run.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from enum import Enum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Status(str, Enum):
|
|
20
|
+
"""
|
|
21
|
+
!!! warning
|
|
22
|
+
`Status` is deprecated, use `StatusV2` instead.
|
|
23
|
+
|
|
24
|
+
Status of a run.
|
|
25
|
+
|
|
26
|
+
You can import the `Status` class directly from `nextmv`:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from nextmv import Status
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This enum represents the possible states of a run. It is deprecated and
|
|
33
|
+
`StatusV2` should be used for new implementations.
|
|
34
|
+
|
|
35
|
+
Attributes
|
|
36
|
+
----------
|
|
37
|
+
failed : str
|
|
38
|
+
Run failed.
|
|
39
|
+
running : str
|
|
40
|
+
Run is running.
|
|
41
|
+
succeeded : str
|
|
42
|
+
Run succeeded.
|
|
43
|
+
|
|
44
|
+
Examples
|
|
45
|
+
--------
|
|
46
|
+
>>> from nextmv.cloud import Status
|
|
47
|
+
>>> current_status = Status.running
|
|
48
|
+
>>> if current_status == Status.succeeded:
|
|
49
|
+
... print("Run completed successfully.")
|
|
50
|
+
... elif current_status == Status.failed:
|
|
51
|
+
... print("Run failed.")
|
|
52
|
+
... else:
|
|
53
|
+
... print(f"Run is currently {current_status.value}.")
|
|
54
|
+
Run is currently running.
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
failed = "failed"
|
|
59
|
+
"""Run failed."""
|
|
60
|
+
running = "running"
|
|
61
|
+
"""Run is running."""
|
|
62
|
+
succeeded = "succeeded"
|
|
63
|
+
"""Run succeeded."""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class StatusV2(str, Enum):
|
|
67
|
+
"""
|
|
68
|
+
Status of a run.
|
|
69
|
+
|
|
70
|
+
You can import the `StatusV2` class directly from `nextmv`:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from nextmv import StatusV2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This enum represents the comprehensive set of possible states for a run
|
|
77
|
+
in Nextmv.
|
|
78
|
+
|
|
79
|
+
Attributes
|
|
80
|
+
----------
|
|
81
|
+
canceled : str
|
|
82
|
+
Run was canceled.
|
|
83
|
+
failed : str
|
|
84
|
+
Run failed.
|
|
85
|
+
none : str
|
|
86
|
+
Run has no status.
|
|
87
|
+
queued : str
|
|
88
|
+
Run is queued.
|
|
89
|
+
running : str
|
|
90
|
+
Run is running.
|
|
91
|
+
succeeded : str
|
|
92
|
+
Run succeeded.
|
|
93
|
+
|
|
94
|
+
Examples
|
|
95
|
+
--------
|
|
96
|
+
>>> from nextmv.cloud import StatusV2
|
|
97
|
+
>>> run_status = StatusV2.queued
|
|
98
|
+
>>> print(f"The run status is: {run_status.value}")
|
|
99
|
+
The run status is: queued
|
|
100
|
+
|
|
101
|
+
>>> if run_status == StatusV2.succeeded:
|
|
102
|
+
... print("Processing complete.")
|
|
103
|
+
... elif run_status in [StatusV2.queued, StatusV2.running]:
|
|
104
|
+
... print("Processing in progress.")
|
|
105
|
+
... else:
|
|
106
|
+
... print("Processing has not started or has ended with issues.")
|
|
107
|
+
Processing in progress.
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
canceled = "canceled"
|
|
112
|
+
"""Run was canceled."""
|
|
113
|
+
failed = "failed"
|
|
114
|
+
"""Run failed."""
|
|
115
|
+
none = "none"
|
|
116
|
+
"""Run has no status."""
|
|
117
|
+
queued = "queued"
|
|
118
|
+
"""Run is queued."""
|
|
119
|
+
running = "running"
|
|
120
|
+
"""Run is running."""
|
|
121
|
+
succeeded = "succeeded"
|
|
122
|
+
"""Run succeeded."""
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: nextmv
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: The Python SDK for Nextmv
|
|
3
|
+
Version: 0.35.0
|
|
4
|
+
Summary: The all-purpose Python SDK for Nextmv
|
|
5
5
|
Project-URL: Homepage, https://www.nextmv.io
|
|
6
|
-
Project-URL: Documentation, https://
|
|
6
|
+
Project-URL: Documentation, https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
|
|
7
7
|
Project-URL: Repository, https://github.com/nextmv-io/nextmv-py
|
|
8
8
|
Author-email: Nextmv <tech@nextmv.io>
|
|
9
9
|
Maintainer-email: Nextmv <tech@nextmv.io>
|
|
@@ -213,309 +213,72 @@ Keywords: decision engineering,decision science,decisions,nextmv,operations rese
|
|
|
213
213
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
214
214
|
Classifier: Operating System :: OS Independent
|
|
215
215
|
Classifier: Programming Language :: Python :: 3
|
|
216
|
-
|
|
216
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
217
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
218
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
219
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
220
|
+
Requires-Python: >=3.10
|
|
217
221
|
Requires-Dist: pydantic>=2.5.2
|
|
218
222
|
Requires-Dist: pyyaml>=6.0.1
|
|
219
223
|
Requires-Dist: requests>=2.31.0
|
|
220
224
|
Requires-Dist: urllib3>=2.1.0
|
|
225
|
+
Provides-Extra: all
|
|
226
|
+
Requires-Dist: folium>=0.20.0; extra == 'all'
|
|
227
|
+
Requires-Dist: mlflow>=2.17.2; extra == 'all'
|
|
228
|
+
Requires-Dist: plotly>=6.0.1; extra == 'all'
|
|
229
|
+
Provides-Extra: dev
|
|
230
|
+
Requires-Dist: build>=1.0.3; extra == 'dev'
|
|
231
|
+
Requires-Dist: folium>=0.20.0; extra == 'dev'
|
|
232
|
+
Requires-Dist: mlflow>=2.19.0; extra == 'dev'
|
|
233
|
+
Requires-Dist: nextroute>=1.11.1; extra == 'dev'
|
|
234
|
+
Requires-Dist: openpyxl>=3.1.5; extra == 'dev'
|
|
235
|
+
Requires-Dist: pandas>=2.2.3; extra == 'dev'
|
|
236
|
+
Requires-Dist: plotly>=6.0.1; extra == 'dev'
|
|
237
|
+
Requires-Dist: pydantic>=2.5.2; extra == 'dev'
|
|
238
|
+
Requires-Dist: pyyaml>=6.0.1; extra == 'dev'
|
|
239
|
+
Requires-Dist: requests>=2.31.0; extra == 'dev'
|
|
240
|
+
Requires-Dist: ruff>=0.1.7; extra == 'dev'
|
|
241
|
+
Requires-Dist: twine>=4.0.2; extra == 'dev'
|
|
242
|
+
Requires-Dist: urllib3>=2.1.0; extra == 'dev'
|
|
221
243
|
Description-Content-Type: text/markdown
|
|
222
244
|
|
|
223
245
|
# Nextmv Python SDK
|
|
224
246
|
|
|
225
|
-
|
|
247
|
+
<!-- markdownlint-disable MD033 MD013 -->
|
|
226
248
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
the functionality for running decision models. These API functions work
|
|
242
|
-
the same way in any machine (local or hosted).
|
|
243
|
-
- [Cloud][cloud]: Interact with the Nextmv Cloud API.
|
|
244
|
-
|
|
245
|
-
### Working with a Decision Model
|
|
249
|
+
<p align="center">
|
|
250
|
+
<a href="https://nextmv.io"><img src="https://cdn.prod.website-files.com/60dee0fad10d14c8ab66dd74/674628a824bc14307c1727aa_blog-prototype-p-2000.png" alt="Nextmv" width="45%"></a>
|
|
251
|
+
</p>
|
|
252
|
+
<p align="center">
|
|
253
|
+
<em>Nextmv: The home for all your optimization work</em>
|
|
254
|
+
</p>
|
|
255
|
+
<p align="center">
|
|
256
|
+
<a href="https://pypi.org/project/nextmv" target="_blank">
|
|
257
|
+
<img src="https://img.shields.io/pypi/pyversions/nextmv.svg?color=%2334D058" alt="Supported Python versions">
|
|
258
|
+
</a>
|
|
259
|
+
<a href="https://pypi.org/project/nextmv" target="_blank">
|
|
260
|
+
<img src="https://img.shields.io/pypi/v/nextmv?color=%2334D058&label=nextmv" alt="Package version">
|
|
261
|
+
</a>
|
|
262
|
+
</p>
|
|
246
263
|
|
|
247
|
-
|
|
248
|
-
SDK. Note that when you create an app that runs locally in your machine, it
|
|
249
|
-
will run in the same way in a Nextmv Cloud-hosted machine.
|
|
264
|
+
<!-- markdownlint-enable MD033 MD013 -->
|
|
250
265
|
|
|
251
|
-
|
|
266
|
+
Welcome to `nextmv`, the general Python SDK for the Nextmv Platform.
|
|
252
267
|
|
|
253
|
-
|
|
268
|
+
📖 To learn more about the `nextmv`, visit the [docs][docs].
|
|
254
269
|
|
|
255
|
-
|
|
256
|
-
import nextmv
|
|
257
|
-
|
|
258
|
-
options = nextmv.Options(
|
|
259
|
-
nextmv.Parameter("str_option", str, "default value", "A string option", required=True),
|
|
260
|
-
nextmv.Parameter("int_option", int, 1, "An int option", required=False),
|
|
261
|
-
nextmv.Parameter("float_option", float, 1.0, "A float option", required=False),
|
|
262
|
-
nextmv.Parameter("bool_option", bool, True, "A bool option", required=True),
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
print(options.str_option)
|
|
266
|
-
print(options.int_option)
|
|
267
|
-
print(options.float_option)
|
|
268
|
-
print(options.bool_option)
|
|
269
|
-
print(options.to_dict())
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
By using options, you are able to pass in the values of the parameters with CLI
|
|
273
|
-
arguments or environment variables.
|
|
270
|
+
## Installation
|
|
274
271
|
|
|
275
|
-
|
|
272
|
+
Requires Python `>=3.10`. Install using `pip`:
|
|
276
273
|
|
|
277
274
|
```bash
|
|
278
|
-
|
|
279
|
-
usage: main.py [options]
|
|
280
|
-
|
|
281
|
-
Options for main.py. Use command-line arguments (highest precedence) or environment variables.
|
|
282
|
-
|
|
283
|
-
optiTo exclude the `markdownlint` rule start and end block, you can use the
|
|
284
|
-
following syntax in your markdown file:STR_OPTION
|
|
285
|
-
[env var: STR_OPTION] (required) (default: default value) (type: str): A string option
|
|
286
|
-
-int_optRemember to replace `Your markdown content here` with your actual markdown
|
|
287
|
-
content.(type: int): An int option
|
|
288
|
-
-float_option FLOAT_OPTION, --float_option FLOAT_OPTION
|
|
289
|
-
[env var: FLOAT_OPTION] (default: 1.0) (type: float): A float option
|
|
290
|
-
-bool_option BOOL_OPTION, --bool_option BOOL_OPTION
|
|
291
|
-
[env var: BOOL_OPTION] (required) (default: True) (type: bool): A bool option
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
<!-- markdownlint-enable -->
|
|
295
|
-
|
|
296
|
-
#### Input
|
|
297
|
-
|
|
298
|
-
Capture the input data for the run.
|
|
299
|
-
|
|
300
|
-
- Work with `JSON`inputs.
|
|
301
|
-
|
|
302
|
-
```python
|
|
303
|
-
import nextmv
|
|
304
|
-
|
|
305
|
-
# Read JSON from stdin.
|
|
306
|
-
json_input_1 = nextmv.load_local()
|
|
307
|
-
print(json_input_1.data)
|
|
308
|
-
|
|
309
|
-
# Can also specify JSON format directly, and read from a file.
|
|
310
|
-
json_input_2 = nextmv.load_local(input_format=nextmv.InputFormat.JSON, path="input.json")
|
|
311
|
-
print(json_input_2.data)
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
- Work with plain, `utf-8` encoded, text inputs.
|
|
315
|
-
|
|
316
|
-
```python
|
|
317
|
-
import nextmv
|
|
318
|
-
|
|
319
|
-
# Read text from stdin.
|
|
320
|
-
text_input_1 = nextmv.load_local(input_format=nextmv.InputFormat.TEXT)
|
|
321
|
-
print(text_input_1.data)
|
|
322
|
-
|
|
323
|
-
# Can also read from a file.
|
|
324
|
-
text_input_2 = nextmv.load_local(input_format=nextmv.InputFormat.TEXT, path="input.txt")
|
|
325
|
-
print(text_input_2.data)
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
<!-- markdownlint-disable -->
|
|
329
|
-
|
|
330
|
-
- Work with multiple `CSV` files.
|
|
331
|
-
|
|
332
|
-
```python
|
|
333
|
-
import nextmv
|
|
334
|
-
|
|
335
|
-
# Read multiple CSV files from a dir named "input".
|
|
336
|
-
csv_archive_input_1 = nextmv.load_local(input_format=nextmv.InputFormat.CSV_ARCHIVE)
|
|
337
|
-
print(csv_archive_input_1.data)
|
|
338
|
-
|
|
339
|
-
# Read multiple CSV files from a custom dir.
|
|
340
|
-
csv_archive_input_2 = nextmv.load_local(input_format=nextmv.InputFormat.CSV_ARCHIVE, path="custom_dir")
|
|
341
|
-
print(csv_archive_input_2.data)
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
<!-- markdownlint-enable -->
|
|
345
|
-
|
|
346
|
-
#### Logging
|
|
347
|
-
|
|
348
|
-
The Nextmv platform captures logs via `stderr`. Use the provided functionality
|
|
349
|
-
to record logs.
|
|
350
|
-
|
|
351
|
-
```python
|
|
352
|
-
import sys
|
|
353
|
-
|
|
354
|
-
import nextmv
|
|
355
|
-
|
|
356
|
-
print("0. I do nothing")
|
|
357
|
-
|
|
358
|
-
nextmv.redirect_stdout()
|
|
359
|
-
|
|
360
|
-
nextmv.log("1. I log a message to stderr")
|
|
361
|
-
|
|
362
|
-
print("2. I print a message to stdout")
|
|
363
|
-
|
|
364
|
-
nextmv.reset_stdout()
|
|
365
|
-
|
|
366
|
-
print("3. I print another message to stdout")
|
|
367
|
-
|
|
368
|
-
print("4. I print yet another message to stderr without the logger", file=sys.stderr)
|
|
369
|
-
|
|
370
|
-
nextmv.log("5. I log a message to stderr using the nextmv module directly")
|
|
371
|
-
|
|
372
|
-
print("6. I print a message to stdout, again")
|
|
275
|
+
pip install nextmv
|
|
373
276
|
```
|
|
374
277
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
- `stdout`
|
|
378
|
-
|
|
379
|
-
```txt
|
|
380
|
-
1. I do nothing
|
|
381
|
-
2. I print another message to stdout
|
|
382
|
-
3. I print a message to stdout, again
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
- `stderr`
|
|
386
|
-
|
|
387
|
-
```txt
|
|
388
|
-
1. I log a message to stderr
|
|
389
|
-
2. I print a message to stdout
|
|
390
|
-
3. I print yet another message to stderr without the logger
|
|
391
|
-
4. I log a message to stderr using the nextmv module directly
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
#### Output
|
|
395
|
-
|
|
396
|
-
Write the output data after a run is completed.
|
|
397
|
-
|
|
398
|
-
- Work with `JSON` outputs.
|
|
399
|
-
|
|
400
|
-
```python
|
|
401
|
-
import nextmv
|
|
402
|
-
|
|
403
|
-
output = nextmv.Output(
|
|
404
|
-
solution={"foo": "bar"},
|
|
405
|
-
statistics=nextmv.Statistics(
|
|
406
|
-
result=nextmv.ResultStatistics(
|
|
407
|
-
duration=1.0,
|
|
408
|
-
value=2.0,
|
|
409
|
-
custom={"custom": "result_value"},
|
|
410
|
-
),
|
|
411
|
-
run=nextmv.RunStatistics(
|
|
412
|
-
duration=3.0,
|
|
413
|
-
iterations=4,
|
|
414
|
-
custom={"custom": "run_value"},
|
|
415
|
-
),
|
|
416
|
-
),
|
|
417
|
-
)
|
|
418
|
-
|
|
419
|
-
# Write to stdout.
|
|
420
|
-
nextmv.write_local(output)
|
|
421
|
-
|
|
422
|
-
# Write to a file.
|
|
423
|
-
nextmv.write_local(output, path="output.json")
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
- Work with multple `CSV` files.
|
|
427
|
-
|
|
428
|
-
```python
|
|
429
|
-
import nextmv
|
|
430
|
-
|
|
431
|
-
output = nextmv.Output(
|
|
432
|
-
output_format=nextmv.OutputFormat.CSV_ARCHIVE,
|
|
433
|
-
solution={
|
|
434
|
-
"output": [
|
|
435
|
-
{"name": "Alice", "age": 30},
|
|
436
|
-
{"name": "Bob", "age": 40},
|
|
437
|
-
],
|
|
438
|
-
},
|
|
439
|
-
statistics=nextmv.Statistics(
|
|
440
|
-
result=nextmv.ResultStatistics(
|
|
441
|
-
duration=1.0,
|
|
442
|
-
value=2.0,
|
|
443
|
-
custom={"custom": "result_value"},
|
|
444
|
-
),
|
|
445
|
-
run=nextmv.RunStatistics(
|
|
446
|
-
duration=3.0,
|
|
447
|
-
iterations=4,
|
|
448
|
-
custom={"custom": "run_value"},
|
|
449
|
-
),
|
|
450
|
-
),
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
# Write multiple CSV fiules to a dir named "output".
|
|
454
|
-
nextmv.write_local(output)
|
|
455
|
-
|
|
456
|
-
# Write multiple CSV files to a custom dir.
|
|
457
|
-
nextmv.write_local(output, "custom_dir")
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
### Cloud
|
|
461
|
-
|
|
462
|
-
Before starting:
|
|
463
|
-
|
|
464
|
-
1. [Sign up][signup] for a Nextmv account.
|
|
465
|
-
2. Get your API key. Go to [Team > API Key][api-key].
|
|
466
|
-
|
|
467
|
-
Visit the [docs][docs] for more information. Make sure that you have your API
|
|
468
|
-
key set as an environment variable:
|
|
278
|
+
Install all optional dependencies (recommended):
|
|
469
279
|
|
|
470
280
|
```bash
|
|
471
|
-
|
|
281
|
+
pip install "nextmv[all]"
|
|
472
282
|
```
|
|
473
283
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
- Make a run and get the results.
|
|
477
|
-
|
|
478
|
-
```python
|
|
479
|
-
import os
|
|
480
|
-
|
|
481
|
-
from nextmv.cloud import Application, Client, PollingOptions
|
|
482
|
-
|
|
483
|
-
input = {
|
|
484
|
-
"defaults": {"vehicles": {"speed": 20}},
|
|
485
|
-
"stops": [
|
|
486
|
-
{
|
|
487
|
-
"id": "Nijō Castle",
|
|
488
|
-
"location": {"lon": 135.748134, "lat": 35.014239},
|
|
489
|
-
"quantity": -1,
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
"id": "Kyoto Imperial Palace",
|
|
493
|
-
"location": {"lon": 135.762057, "lat": 35.025431},
|
|
494
|
-
"quantity": -1,
|
|
495
|
-
},
|
|
496
|
-
],
|
|
497
|
-
"vehicles": [
|
|
498
|
-
{
|
|
499
|
-
"id": "v2",
|
|
500
|
-
"capacity": 2,
|
|
501
|
-
"start_location": {"lon": 135.728898, "lat": 35.039705},
|
|
502
|
-
},
|
|
503
|
-
],
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
client = Client(api_key=os.getenv("NEXTMV_API_KEY"))
|
|
507
|
-
app = Application(client=client, id="<YOUR-APP-ID>")
|
|
508
|
-
result = app.new_run_with_result(
|
|
509
|
-
input=input,
|
|
510
|
-
instance_id="latest",
|
|
511
|
-
run_options={"solve.duration": "1s"},
|
|
512
|
-
polling_options=PollingOptions(), # Customize the polling options.
|
|
513
|
-
)
|
|
514
|
-
print(result.to_dict())
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
[signup]: https://cloud.nextmv.io
|
|
518
|
-
[docs]: https://nextmv.io/docs
|
|
519
|
-
[api-key]: https://cloud.nextmv.io/team/api-keys
|
|
520
|
-
[cloud]: #cloud
|
|
521
|
-
[working-with-a-decision-model]: #working-with-a-decision-model
|
|
284
|
+
[docs]: https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
nextmv/__about__.py,sha256=bQ5WltwnJ2DWtUa1Ur-mKSOXGWtA0PCrqR2GFguHyhw,24
|
|
2
|
+
nextmv/__entrypoint__.py,sha256=dA0iwwHtrq6Z9w9FxmxKLoBGLyhe7jWtUAU-Y3PEgHg,1094
|
|
3
|
+
nextmv/__init__.py,sha256=mC-gAzCdoZJ0BOVe2fDzKNdBtbXzx8XOxHP_7DdPMdQ,3857
|
|
4
|
+
nextmv/_serialization.py,sha256=jYitMS1MU8ldsmObT-K_8V8P2Wx69tnDiEHCCgPGun4,2834
|
|
5
|
+
nextmv/base_model.py,sha256=kPFqE-c_3LcEy8fY0qDrJk_gbPYgSKtetRMby71oxE8,2298
|
|
6
|
+
nextmv/deprecated.py,sha256=kEVfyQ-nT0v2ePXTNldjQG9uH5IlfQVy3L4tztIxwmU,1638
|
|
7
|
+
nextmv/input.py,sha256=XRjINb438rnjvQwjCXVOJ0UPa-xTnZc9xBYt0NLhjGw,39970
|
|
8
|
+
nextmv/logger.py,sha256=kNIbu46MisrzYe4T0hNMpWfRTKKacDVvbtQcNys_c_E,2513
|
|
9
|
+
nextmv/manifest.py,sha256=2c4DFO8tr9UftKJPocRBjg9z-LcpOZery5iTkX0u18Y,49103
|
|
10
|
+
nextmv/model.py,sha256=b323uAjr-eeChrIPLg4a8bnqOaoc12DQrQBnIPybd0k,14993
|
|
11
|
+
nextmv/options.py,sha256=rfQV0F5_it-L27wjqrs902wr4Q7sgSN7dw5o0c5sdEg,37842
|
|
12
|
+
nextmv/output.py,sha256=oqCnBvcYOZlvPSoX4trQ3EJR6GpE-4d0d7NDIq5hgL0,56008
|
|
13
|
+
nextmv/polling.py,sha256=Mka7tChVR7Ws-Hg9W-Yzo7wthhVg-Qp-FK54E70Fzdw,9711
|
|
14
|
+
nextmv/run.py,sha256=N5qbfEJ_p5rmIwhFkiWRtGMU_u209hJ4_b-xKrD70-k,52284
|
|
15
|
+
nextmv/safe.py,sha256=VAK4fGEurbLNji4Pg5Okga5XQSbI4aI9JJf95_68Z20,3867
|
|
16
|
+
nextmv/status.py,sha256=SCDLhh2om3yeO5FxO0x-_RShQsZNXEpjHNdCGdb3VUI,2787
|
|
17
|
+
nextmv/cloud/__init__.py,sha256=2wI72lhWq81BYv1OpS0OOTT5-3sivpX0H4z5ANPoLMc,5051
|
|
18
|
+
nextmv/cloud/acceptance_test.py,sha256=fZdp4O6pZrl7TaiUrTFPp7O4VJt-4R_W2yo4s8UAS5I,27691
|
|
19
|
+
nextmv/cloud/account.py,sha256=jIdGNyI3l3dVh2PuriAwAOrEuWRM150WgzxcBMVBNRw,6058
|
|
20
|
+
nextmv/cloud/application.py,sha256=29Tr7jWwa369ejkgFX3VXU_G3VK-2ATyL6Ma5tGXfAg,139592
|
|
21
|
+
nextmv/cloud/batch_experiment.py,sha256=IwvXjapauTkrYzmJhM5DeHBpxSA49MewQA4Pjk1KWzw,10339
|
|
22
|
+
nextmv/cloud/client.py,sha256=Yj4FE4GKsLHkYijAYXcotlyNfhAWANMuWetHXsYPg1M,18101
|
|
23
|
+
nextmv/cloud/ensemble.py,sha256=_hKPjSLtuGH1xGG70ZBsmY_IL5XinZqVHHwBxtX9Omw,8570
|
|
24
|
+
nextmv/cloud/input_set.py,sha256=wsLmMI1C7BslWDN5j1RnVUA8z54-Hq1eLG9bkzyqafo,4187
|
|
25
|
+
nextmv/cloud/instance.py,sha256=n68CGzv0vfTyM-IP3zoiSk6x5Kusn9taYpV-dSEhh6M,3987
|
|
26
|
+
nextmv/cloud/package.py,sha256=7qN09uJ8LyfDhPPo-eeScjuZHTp8mLY1LO1NVo1YNT4,15223
|
|
27
|
+
nextmv/cloud/scenario.py,sha256=1_4PI9ehYaSonEe_l59cFhZNmqQ_brXXP6-mVq9i8a8,14183
|
|
28
|
+
nextmv/cloud/secrets.py,sha256=fA5cX0jfTsPVZWV7433wzETGlXpWRLHGswuObx9e6FQ,6820
|
|
29
|
+
nextmv/cloud/url.py,sha256=Fz70ywkWdCLmP21ZBmJwZi5kDbjpmsX_VlwVF_xQeHg,1836
|
|
30
|
+
nextmv/cloud/version.py,sha256=5_S7_pWUVBFbvAArku20eK7S645GJcHtgE2OpXLdSzQ,5300
|
|
31
|
+
nextmv/default_app/.gitignore,sha256=gsfnfXMYNt-YTroh5hAzauwBZoPDJ6D_fB17rMSnIko,8
|
|
32
|
+
nextmv/default_app/README.md,sha256=SroGwvWiDTz12yctMfviFYw7z1EMU_72ESK2dyt-Ypg,664
|
|
33
|
+
nextmv/default_app/app.yaml,sha256=TKjKnuoK0SDpouB_AS7TQmE_8HZbQYjmwFvhzFL1xpc,382
|
|
34
|
+
nextmv/default_app/input.json,sha256=zgvbKL3boB0WIU6-9mEU3ZWBddQ5cQ0vhgmDwDyz4hE,63
|
|
35
|
+
nextmv/default_app/main.py,sha256=gG-1JIvKXPCkm4JV46PcXxsQTAefwPXQbdPxkSubhf0,888
|
|
36
|
+
nextmv/default_app/requirements.txt,sha256=wRE_HkYYWzCGnYZ2NuatHXul4gCHvU3iUAdsxtzpYiA,29
|
|
37
|
+
nextmv/default_app/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
nextmv/default_app/src/main.py,sha256=WWeN_xl_mcPhICl3rSCvdEjRkFXGmAnej88FhS-fAmc,884
|
|
39
|
+
nextmv/default_app/src/visuals.py,sha256=WYK_YBnLmYo3TpVev1CpoNCuW5R7hk9QIkeCmvMn1Fs,1014
|
|
40
|
+
nextmv/local/__init__.py,sha256=6BsoqlK4dw6X11_uKzz9gBPfxKpdiol2FYO8R3X73SE,116
|
|
41
|
+
nextmv/local/application.py,sha256=RtqKR3yRI2GFn_RLyaRZMWZW30BuYllLdAY2OsPL7Xc,48245
|
|
42
|
+
nextmv/local/executor.py,sha256=g9Bjjm8EzF2wOd0NSow1r_O_L7UBmuFYUYYCOdmapAw,36491
|
|
43
|
+
nextmv/local/geojson_handler.py,sha256=7FavJdkUonop-yskjis0x3qFGB8A5wZyoBUblw-bVhw,12540
|
|
44
|
+
nextmv/local/local.py,sha256=cp56UpI8h19Ob6Jvb_Ni0ceXH5Vv3ET_iPTDe6ftq3Y,2617
|
|
45
|
+
nextmv/local/plotly_handler.py,sha256=bLb50e3AkVr_W-F6S7lXfeRdN60mG2jk3UElNmhoMWU,1930
|
|
46
|
+
nextmv/local/runner.py,sha256=Fa-G4g5yaBgLeBfYU-ePs65Q3Ses_xYvXGhPtHpAkrU,8546
|
|
47
|
+
nextmv-0.35.0.dist-info/METADATA,sha256=2gDLgPS0t_kLacTwUmza1FKUTK_MIv8a5CTdP4soyAQ,15960
|
|
48
|
+
nextmv-0.35.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
49
|
+
nextmv-0.35.0.dist-info/licenses/LICENSE,sha256=ZIbK-sSWA-OZprjNbmJAglYRtl5_K4l9UwAV3PGJAPc,11349
|
|
50
|
+
nextmv-0.35.0.dist-info/RECORD,,
|