nextmv 0.18.0__py3-none-any.whl → 1.0.0.dev2__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.
Files changed (175) hide show
  1. nextmv/__about__.py +1 -1
  2. nextmv/__entrypoint__.py +8 -13
  3. nextmv/__init__.py +53 -0
  4. nextmv/_serialization.py +96 -0
  5. nextmv/base_model.py +54 -9
  6. nextmv/cli/CONTRIBUTING.md +511 -0
  7. nextmv/cli/__init__.py +0 -0
  8. nextmv/cli/cloud/__init__.py +47 -0
  9. nextmv/cli/cloud/acceptance/__init__.py +27 -0
  10. nextmv/cli/cloud/acceptance/create.py +393 -0
  11. nextmv/cli/cloud/acceptance/delete.py +68 -0
  12. nextmv/cli/cloud/acceptance/get.py +104 -0
  13. nextmv/cli/cloud/acceptance/list.py +62 -0
  14. nextmv/cli/cloud/acceptance/update.py +95 -0
  15. nextmv/cli/cloud/account/__init__.py +28 -0
  16. nextmv/cli/cloud/account/create.py +83 -0
  17. nextmv/cli/cloud/account/delete.py +60 -0
  18. nextmv/cli/cloud/account/get.py +66 -0
  19. nextmv/cli/cloud/account/update.py +70 -0
  20. nextmv/cli/cloud/app/__init__.py +35 -0
  21. nextmv/cli/cloud/app/create.py +141 -0
  22. nextmv/cli/cloud/app/delete.py +58 -0
  23. nextmv/cli/cloud/app/exists.py +44 -0
  24. nextmv/cli/cloud/app/get.py +66 -0
  25. nextmv/cli/cloud/app/list.py +61 -0
  26. nextmv/cli/cloud/app/push.py +137 -0
  27. nextmv/cli/cloud/app/update.py +124 -0
  28. nextmv/cli/cloud/batch/__init__.py +29 -0
  29. nextmv/cli/cloud/batch/create.py +454 -0
  30. nextmv/cli/cloud/batch/delete.py +68 -0
  31. nextmv/cli/cloud/batch/get.py +104 -0
  32. nextmv/cli/cloud/batch/list.py +63 -0
  33. nextmv/cli/cloud/batch/metadata.py +66 -0
  34. nextmv/cli/cloud/batch/update.py +95 -0
  35. nextmv/cli/cloud/data/__init__.py +26 -0
  36. nextmv/cli/cloud/data/upload.py +162 -0
  37. nextmv/cli/cloud/ensemble/__init__.py +31 -0
  38. nextmv/cli/cloud/ensemble/create.py +414 -0
  39. nextmv/cli/cloud/ensemble/delete.py +67 -0
  40. nextmv/cli/cloud/ensemble/get.py +65 -0
  41. nextmv/cli/cloud/ensemble/update.py +103 -0
  42. nextmv/cli/cloud/input_set/__init__.py +30 -0
  43. nextmv/cli/cloud/input_set/create.py +170 -0
  44. nextmv/cli/cloud/input_set/get.py +63 -0
  45. nextmv/cli/cloud/input_set/list.py +63 -0
  46. nextmv/cli/cloud/input_set/update.py +123 -0
  47. nextmv/cli/cloud/instance/__init__.py +35 -0
  48. nextmv/cli/cloud/instance/create.py +290 -0
  49. nextmv/cli/cloud/instance/delete.py +62 -0
  50. nextmv/cli/cloud/instance/exists.py +39 -0
  51. nextmv/cli/cloud/instance/get.py +62 -0
  52. nextmv/cli/cloud/instance/list.py +60 -0
  53. nextmv/cli/cloud/instance/update.py +216 -0
  54. nextmv/cli/cloud/managed_input/__init__.py +31 -0
  55. nextmv/cli/cloud/managed_input/create.py +146 -0
  56. nextmv/cli/cloud/managed_input/delete.py +65 -0
  57. nextmv/cli/cloud/managed_input/get.py +63 -0
  58. nextmv/cli/cloud/managed_input/list.py +60 -0
  59. nextmv/cli/cloud/managed_input/update.py +97 -0
  60. nextmv/cli/cloud/run/__init__.py +37 -0
  61. nextmv/cli/cloud/run/cancel.py +37 -0
  62. nextmv/cli/cloud/run/create.py +530 -0
  63. nextmv/cli/cloud/run/get.py +199 -0
  64. nextmv/cli/cloud/run/input.py +86 -0
  65. nextmv/cli/cloud/run/list.py +80 -0
  66. nextmv/cli/cloud/run/logs.py +167 -0
  67. nextmv/cli/cloud/run/metadata.py +67 -0
  68. nextmv/cli/cloud/run/track.py +501 -0
  69. nextmv/cli/cloud/scenario/__init__.py +29 -0
  70. nextmv/cli/cloud/scenario/create.py +451 -0
  71. nextmv/cli/cloud/scenario/delete.py +65 -0
  72. nextmv/cli/cloud/scenario/get.py +102 -0
  73. nextmv/cli/cloud/scenario/list.py +63 -0
  74. nextmv/cli/cloud/scenario/metadata.py +67 -0
  75. nextmv/cli/cloud/scenario/update.py +93 -0
  76. nextmv/cli/cloud/secrets/__init__.py +33 -0
  77. nextmv/cli/cloud/secrets/create.py +206 -0
  78. nextmv/cli/cloud/secrets/delete.py +67 -0
  79. nextmv/cli/cloud/secrets/get.py +66 -0
  80. nextmv/cli/cloud/secrets/list.py +60 -0
  81. nextmv/cli/cloud/secrets/update.py +147 -0
  82. nextmv/cli/cloud/shadow/__init__.py +33 -0
  83. nextmv/cli/cloud/shadow/create.py +184 -0
  84. nextmv/cli/cloud/shadow/delete.py +68 -0
  85. nextmv/cli/cloud/shadow/get.py +61 -0
  86. nextmv/cli/cloud/shadow/list.py +63 -0
  87. nextmv/cli/cloud/shadow/metadata.py +66 -0
  88. nextmv/cli/cloud/shadow/start.py +43 -0
  89. nextmv/cli/cloud/shadow/stop.py +43 -0
  90. nextmv/cli/cloud/shadow/update.py +95 -0
  91. nextmv/cli/cloud/upload/__init__.py +22 -0
  92. nextmv/cli/cloud/upload/create.py +39 -0
  93. nextmv/cli/cloud/version/__init__.py +33 -0
  94. nextmv/cli/cloud/version/create.py +97 -0
  95. nextmv/cli/cloud/version/delete.py +62 -0
  96. nextmv/cli/cloud/version/exists.py +39 -0
  97. nextmv/cli/cloud/version/get.py +62 -0
  98. nextmv/cli/cloud/version/list.py +60 -0
  99. nextmv/cli/cloud/version/update.py +92 -0
  100. nextmv/cli/community/__init__.py +24 -0
  101. nextmv/cli/community/clone.py +270 -0
  102. nextmv/cli/community/list.py +265 -0
  103. nextmv/cli/configuration/__init__.py +23 -0
  104. nextmv/cli/configuration/config.py +195 -0
  105. nextmv/cli/configuration/create.py +94 -0
  106. nextmv/cli/configuration/delete.py +67 -0
  107. nextmv/cli/configuration/list.py +77 -0
  108. nextmv/cli/main.py +188 -0
  109. nextmv/cli/message.py +153 -0
  110. nextmv/cli/options.py +206 -0
  111. nextmv/cli/version.py +38 -0
  112. nextmv/cloud/__init__.py +71 -17
  113. nextmv/cloud/acceptance_test.py +757 -51
  114. nextmv/cloud/account.py +406 -17
  115. nextmv/cloud/application/__init__.py +957 -0
  116. nextmv/cloud/application/_acceptance.py +419 -0
  117. nextmv/cloud/application/_batch_scenario.py +860 -0
  118. nextmv/cloud/application/_ensemble.py +251 -0
  119. nextmv/cloud/application/_input_set.py +227 -0
  120. nextmv/cloud/application/_instance.py +289 -0
  121. nextmv/cloud/application/_managed_input.py +227 -0
  122. nextmv/cloud/application/_run.py +1393 -0
  123. nextmv/cloud/application/_secrets.py +294 -0
  124. nextmv/cloud/application/_shadow.py +314 -0
  125. nextmv/cloud/application/_utils.py +54 -0
  126. nextmv/cloud/application/_version.py +303 -0
  127. nextmv/cloud/assets.py +48 -0
  128. nextmv/cloud/batch_experiment.py +294 -33
  129. nextmv/cloud/client.py +307 -66
  130. nextmv/cloud/ensemble.py +247 -0
  131. nextmv/cloud/input_set.py +120 -2
  132. nextmv/cloud/instance.py +133 -8
  133. nextmv/cloud/integration.py +533 -0
  134. nextmv/cloud/package.py +168 -53
  135. nextmv/cloud/scenario.py +410 -0
  136. nextmv/cloud/secrets.py +234 -0
  137. nextmv/cloud/shadow.py +190 -0
  138. nextmv/cloud/url.py +73 -0
  139. nextmv/cloud/version.py +132 -4
  140. nextmv/default_app/.gitignore +1 -0
  141. nextmv/default_app/README.md +32 -0
  142. nextmv/default_app/app.yaml +12 -0
  143. nextmv/default_app/input.json +5 -0
  144. nextmv/default_app/main.py +37 -0
  145. nextmv/default_app/requirements.txt +2 -0
  146. nextmv/default_app/src/__init__.py +0 -0
  147. nextmv/default_app/src/visuals.py +36 -0
  148. nextmv/deprecated.py +47 -0
  149. nextmv/input.py +861 -90
  150. nextmv/local/__init__.py +5 -0
  151. nextmv/local/application.py +1251 -0
  152. nextmv/local/executor.py +1042 -0
  153. nextmv/local/geojson_handler.py +323 -0
  154. nextmv/local/local.py +97 -0
  155. nextmv/local/plotly_handler.py +61 -0
  156. nextmv/local/runner.py +274 -0
  157. nextmv/logger.py +80 -9
  158. nextmv/manifest.py +1466 -0
  159. nextmv/model.py +241 -66
  160. nextmv/options.py +708 -115
  161. nextmv/output.py +1301 -274
  162. nextmv/polling.py +325 -0
  163. nextmv/run.py +1702 -0
  164. nextmv/safe.py +145 -0
  165. nextmv/status.py +122 -0
  166. nextmv-1.0.0.dev2.dist-info/METADATA +311 -0
  167. nextmv-1.0.0.dev2.dist-info/RECORD +170 -0
  168. {nextmv-0.18.0.dist-info → nextmv-1.0.0.dev2.dist-info}/WHEEL +1 -1
  169. nextmv-1.0.0.dev2.dist-info/entry_points.txt +2 -0
  170. nextmv/cloud/application.py +0 -1405
  171. nextmv/cloud/manifest.py +0 -234
  172. nextmv/cloud/status.py +0 -29
  173. nextmv-0.18.0.dist-info/METADATA +0 -770
  174. nextmv-0.18.0.dist-info/RECORD +0 -25
  175. {nextmv-0.18.0.dist-info → nextmv-1.0.0.dev2.dist-info}/licenses/LICENSE +0 -0
nextmv/__about__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "v0.18.0"
1
+ __version__ = "v1.0.0.dev2"
nextmv/__entrypoint__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- When working in a notebook environment, we dont really create a `main.py` file
2
+ When working in a notebook environment, we don't really create a `main.py` file
3
3
  with the main entrypoint of the program. Because the logic is mostly encoded
4
4
  inside the `Model` class, we need to create a `main.py` file that we can run in
5
5
  Nextmv Cloud. This file is used as that entrypoint. It is not intended for a
@@ -9,22 +9,17 @@ human to use it during local development. It is the standard way in which a
9
9
 
10
10
  from mlflow.pyfunc import load_model
11
11
 
12
- from nextmv.cloud.manifest import Manifest
13
- from nextmv.input import load_local
14
- from nextmv.options import Options
15
- from nextmv.output import write_local
12
+ import nextmv
13
+ from nextmv import cloud
16
14
 
17
15
 
18
16
  def main() -> None:
19
17
  """Entry point for the program."""
20
18
 
21
- manifest = Manifest.from_yaml(".")
19
+ manifest = cloud.Manifest.from_yaml(".")
22
20
 
23
21
  # Load the options from the manifest.
24
- options = None
25
- parameters_dict = manifest.python.model.options
26
- if parameters_dict is not None:
27
- options = Options.from_parameters_dict(parameters_dict)
22
+ options = manifest.extract_options()
28
23
 
29
24
  # Load the model.
30
25
  loaded_model = load_model(
@@ -32,12 +27,12 @@ def main() -> None:
32
27
  suppress_warnings=True,
33
28
  )
34
29
 
35
- # Load the input and solve the model by using mlflows inference API.
36
- input = load_local(options=options)
30
+ # Load the input and solve the model by using mlflow's inference API.
31
+ input = nextmv.load(options=options)
37
32
  output = loaded_model.predict(input)
38
33
 
39
34
  # Write the output.
40
- write_local(output)
35
+ nextmv.write(output)
41
36
 
42
37
 
43
38
  if __name__ == "__main__":
nextmv/__init__.py CHANGED
@@ -1,17 +1,35 @@
1
1
  """Nextmv Python SDK."""
2
2
 
3
3
  from .__about__ import __version__
4
+ from .base_model import BaseModel as BaseModel
4
5
  from .base_model import from_dict as from_dict
6
+ from .input import DataFile as DataFile
5
7
  from .input import Input as Input
6
8
  from .input import InputFormat as InputFormat
7
9
  from .input import InputLoader as InputLoader
8
10
  from .input import LocalInputLoader as LocalInputLoader
11
+ from .input import csv_data_file as csv_data_file
12
+ from .input import json_data_file as json_data_file
13
+ from .input import load as load
9
14
  from .input import load_local as load_local
15
+ from .input import text_data_file as text_data_file
10
16
  from .logger import log as log
11
17
  from .logger import redirect_stdout as redirect_stdout
12
18
  from .logger import reset_stdout as reset_stdout
19
+ from .manifest import MANIFEST_FILE_NAME as MANIFEST_FILE_NAME
20
+ from .manifest import Manifest as Manifest
21
+ from .manifest import ManifestBuild as ManifestBuild
22
+ from .manifest import ManifestExecution as ManifestExecution
23
+ from .manifest import ManifestOption as ManifestOption
24
+ from .manifest import ManifestPython as ManifestPython
25
+ from .manifest import ManifestPythonArch as ManifestPythonArch
26
+ from .manifest import ManifestPythonModel as ManifestPythonModel
27
+ from .manifest import ManifestRuntime as ManifestRuntime
28
+ from .manifest import ManifestType as ManifestType
29
+ from .manifest import default_python_manifest as default_python_manifest
13
30
  from .model import Model as Model
14
31
  from .model import ModelConfiguration as ModelConfiguration
32
+ from .options import Option as Option
15
33
  from .options import Options as Options
16
34
  from .options import Parameter as Parameter
17
35
  from .output import Asset as Asset
@@ -24,10 +42,45 @@ from .output import ResultStatistics as ResultStatistics
24
42
  from .output import RunStatistics as RunStatistics
25
43
  from .output import Series as Series
26
44
  from .output import SeriesData as SeriesData
45
+ from .output import SolutionFile as SolutionFile
27
46
  from .output import Statistics as Statistics
28
47
  from .output import Visual as Visual
29
48
  from .output import VisualSchema as VisualSchema
49
+ from .output import csv_solution_file as csv_solution_file
50
+ from .output import json_solution_file as json_solution_file
51
+ from .output import text_solution_file as text_solution_file
52
+ from .output import write as write
30
53
  from .output import write_local as write_local
54
+ from .polling import DEFAULT_POLLING_OPTIONS as DEFAULT_POLLING_OPTIONS
55
+ from .polling import PollingOptions as PollingOptions
56
+ from .polling import default_polling_options as default_polling_options
57
+ from .polling import poll as poll
58
+ from .run import ErrorLog as ErrorLog
59
+ from .run import ExternalRunResult as ExternalRunResult
60
+ from .run import Format as Format
61
+ from .run import FormatInput as FormatInput
62
+ from .run import FormatOutput as FormatOutput
63
+ from .run import Metadata as Metadata
64
+ from .run import OptionsSummaryItem as OptionsSummaryItem
65
+ from .run import Run as Run
66
+ from .run import RunConfiguration as RunConfiguration
67
+ from .run import RunInformation as RunInformation
68
+ from .run import RunInfoStatistics as RunInfoStatistics
69
+ from .run import RunLog as RunLog
70
+ from .run import RunQueuing as RunQueuing
71
+ from .run import RunResult as RunResult
72
+ from .run import RunType as RunType
73
+ from .run import RunTypeConfiguration as RunTypeConfiguration
74
+ from .run import StatisticsIndicator as StatisticsIndicator
75
+ from .run import SyncedRun as SyncedRun
76
+ from .run import TimestampedRunLog as TimestampedRunLog
77
+ from .run import TrackedRun as TrackedRun
78
+ from .run import TrackedRunStatus as TrackedRunStatus
79
+ from .run import run_duration as run_duration
80
+ from .safe import safe_id as safe_id
81
+ from .safe import safe_name_and_id as safe_name_and_id
82
+ from .status import Status as Status
83
+ from .status import StatusV2 as StatusV2
31
84
 
32
85
  VERSION = __version__
33
86
  """The version of the Nextmv Python SDK."""
@@ -0,0 +1,96 @@
1
+ import datetime
2
+ import json
3
+ from typing import Any
4
+
5
+
6
+ def deflated_serialize_json(obj: dict | list, json_configurations: dict[str, Any] = None) -> str:
7
+ """
8
+ Serialize a Python object (dict or list) to a JSON string with default configuration for a deflated format.
9
+
10
+ Parameters
11
+ ----------
12
+ obj : Union[dict, list]
13
+ The Python object to serialize.
14
+ json_configurations : dict, optional
15
+ Additional configurations for JSON serialization. This allows customization
16
+ of the Python `json.dumps` function. You can specify parameters like `indent`
17
+ for pretty printing or `default` for custom serialization functions.
18
+
19
+ Returns
20
+ -------
21
+ str
22
+ A JSON string representation of the object.
23
+ """
24
+
25
+ # Apply a default configuration if not provided targeting a deflated format
26
+ json_configurations = json_configurations or {}
27
+ if "default" not in json_configurations:
28
+ json_configurations["default"] = _custom_serial
29
+ if "separators" not in json_configurations:
30
+ json_configurations["separators"] = (",", ":")
31
+
32
+ return json.dumps(
33
+ obj,
34
+ **json_configurations,
35
+ )
36
+
37
+
38
+ def serialize_json(obj: dict | list, json_configurations: dict[str, Any] = None) -> str:
39
+ """
40
+ Serialize a Python object (dict or list) to a JSON string.
41
+
42
+ Parameters
43
+ ----------
44
+ obj : Union[dict, list]
45
+ The Python object to serialize.
46
+ json_configurations : dict, optional
47
+ Additional configurations for JSON serialization. This allows customization
48
+ of the Python `json.dumps` function. You can specify parameters like `indent`
49
+ for pretty printing or `default` for custom serialization functions.
50
+
51
+ Returns
52
+ -------
53
+ str
54
+ A JSON string representation of the object.
55
+ """
56
+
57
+ # Apply some default configuration if not provided
58
+ json_configurations = json_configurations or {}
59
+ if "default" not in json_configurations:
60
+ json_configurations["default"] = _custom_serial
61
+ if "indent" not in json_configurations:
62
+ json_configurations["indent"] = 2
63
+
64
+ return json.dumps(
65
+ obj,
66
+ **json_configurations,
67
+ )
68
+
69
+
70
+ def _custom_serial(obj: Any) -> str:
71
+ """
72
+ JSON serializer for objects not serializable by default json serializer.
73
+
74
+ This function provides custom serialization for datetime objects, converting
75
+ them to ISO format strings.
76
+
77
+ Parameters
78
+ ----------
79
+ obj : Any
80
+ The object to serialize.
81
+
82
+ Returns
83
+ -------
84
+ str
85
+ The serialized representation of the object.
86
+
87
+ Raises
88
+ ------
89
+ TypeError
90
+ If the object type is not supported for serialization.
91
+ """
92
+
93
+ if isinstance(obj, (datetime.datetime, datetime.date)):
94
+ return obj.isoformat()
95
+
96
+ raise TypeError(f"Type {type(obj)} not serializable")
nextmv/base_model.py CHANGED
@@ -1,17 +1,52 @@
1
- """JSON class for data wrangling JSON objects."""
1
+ """
2
+ Provides base functionality for handling JSON data in models.
3
+
4
+ This module contains utilities for converting between dictionaries and model
5
+ instances, facilitating data serialization and deserialization.
6
+
7
+ Classes
8
+ -------
9
+ BaseModel:
10
+ A base class extending Pydantic's BaseModel with additional methods for
11
+ JSON data serialization and deserialization.
12
+
13
+ Functions
14
+ ---------
15
+ from_dict:
16
+ Load a data model instance from a dictionary containing class information
17
+ and attributes.
18
+ """
2
19
 
3
20
  from importlib import import_module
4
- from typing import Any, Optional
21
+ from typing import Any
5
22
 
6
- from pydantic import BaseModel
23
+ from pydantic import BaseModel as PydanticBaseModel
7
24
 
8
25
 
9
- class BaseModel(BaseModel):
10
- """Base class for data wrangling tasks with JSON."""
26
+ class BaseModel(PydanticBaseModel):
27
+ """
28
+ Base class for data wrangling tasks with JSON.
29
+
30
+ This class extends Pydantic's `BaseModel` to provide additional methods
31
+ for converting between Python objects and JSON/dictionary representations.
32
+ """
11
33
 
12
34
  @classmethod
13
- def from_dict(cls, data: Optional[dict[str, Any]] = None):
14
- """Instantiates the class from a dict."""
35
+ def from_dict(cls, data: dict[str, Any] | None = None):
36
+ """
37
+ Instantiate the class from a dictionary.
38
+
39
+ Parameters
40
+ ----------
41
+ data : dict[str, Any], optional
42
+ The dictionary containing the data to instantiate the class.
43
+ If None, returns None.
44
+
45
+ Returns
46
+ -------
47
+ cls or None
48
+ An instance of the class with the given data or None if data is None.
49
+ """
15
50
 
16
51
  if data is None:
17
52
  return None
@@ -19,14 +54,24 @@ class BaseModel(BaseModel):
19
54
  return cls(**data)
20
55
 
21
56
  def to_dict(self) -> dict[str, Any]:
22
- """Converts the class to a dict."""
57
+ """
58
+ Convert the class instance to a dictionary.
59
+
60
+ The conversion uses Pydantic's model_dump method, excluding None values
61
+ and using field aliases if defined.
62
+
63
+ Returns
64
+ -------
65
+ dict[str, Any]
66
+ Dictionary representation of the class instance.
67
+ """
23
68
 
24
69
  return self.model_dump(mode="json", exclude_none=True, by_alias=True)
25
70
 
26
71
 
27
72
  def from_dict(data: dict[str, Any]) -> Any:
28
73
  """
29
- Load a data model instance from a dict with associated class info.
74
+ Load a data model instance from a `dict` with associated class info.
30
75
 
31
76
  Parameters
32
77
  ----------