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.
Files changed (61) hide show
  1. nextmv/__about__.py +1 -1
  2. nextmv/__entrypoint__.py +39 -0
  3. nextmv/__init__.py +57 -0
  4. nextmv/_serialization.py +96 -0
  5. nextmv/base_model.py +79 -9
  6. nextmv/cloud/__init__.py +71 -10
  7. nextmv/cloud/acceptance_test.py +888 -17
  8. nextmv/cloud/account.py +154 -10
  9. nextmv/cloud/application.py +3644 -437
  10. nextmv/cloud/batch_experiment.py +292 -33
  11. nextmv/cloud/client.py +354 -53
  12. nextmv/cloud/ensemble.py +247 -0
  13. nextmv/cloud/input_set.py +121 -4
  14. nextmv/cloud/instance.py +125 -0
  15. nextmv/cloud/package.py +474 -0
  16. nextmv/cloud/scenario.py +410 -0
  17. nextmv/cloud/secrets.py +234 -0
  18. nextmv/cloud/url.py +73 -0
  19. nextmv/cloud/version.py +174 -0
  20. nextmv/default_app/.gitignore +1 -0
  21. nextmv/default_app/README.md +32 -0
  22. nextmv/default_app/app.yaml +12 -0
  23. nextmv/default_app/input.json +5 -0
  24. nextmv/default_app/main.py +37 -0
  25. nextmv/default_app/requirements.txt +2 -0
  26. nextmv/default_app/src/__init__.py +0 -0
  27. nextmv/default_app/src/main.py +37 -0
  28. nextmv/default_app/src/visuals.py +36 -0
  29. nextmv/deprecated.py +47 -0
  30. nextmv/input.py +883 -78
  31. nextmv/local/__init__.py +5 -0
  32. nextmv/local/application.py +1263 -0
  33. nextmv/local/executor.py +1040 -0
  34. nextmv/local/geojson_handler.py +323 -0
  35. nextmv/local/local.py +97 -0
  36. nextmv/local/plotly_handler.py +61 -0
  37. nextmv/local/runner.py +274 -0
  38. nextmv/logger.py +80 -9
  39. nextmv/manifest.py +1472 -0
  40. nextmv/model.py +431 -0
  41. nextmv/options.py +968 -78
  42. nextmv/output.py +1363 -231
  43. nextmv/polling.py +287 -0
  44. nextmv/run.py +1623 -0
  45. nextmv/safe.py +145 -0
  46. nextmv/status.py +122 -0
  47. {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/METADATA +51 -288
  48. nextmv-0.35.0.dist-info/RECORD +50 -0
  49. {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/WHEEL +1 -1
  50. nextmv/cloud/status.py +0 -29
  51. nextmv/nextroute/__init__.py +0 -2
  52. nextmv/nextroute/check/__init__.py +0 -26
  53. nextmv/nextroute/check/schema.py +0 -141
  54. nextmv/nextroute/schema/__init__.py +0 -19
  55. nextmv/nextroute/schema/input.py +0 -52
  56. nextmv/nextroute/schema/location.py +0 -13
  57. nextmv/nextroute/schema/output.py +0 -136
  58. nextmv/nextroute/schema/stop.py +0 -61
  59. nextmv/nextroute/schema/vehicle.py +0 -68
  60. nextmv-0.10.3.dev0.dist-info/RECORD +0 -28
  61. {nextmv-0.10.3.dev0.dist-info → nextmv-0.35.0.dist-info}/licenses/LICENSE +0 -0
nextmv/__about__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "v0.10.3.dev0"
1
+ __version__ = "v0.35.0"
@@ -0,0 +1,39 @@
1
+ """
2
+ When working in a notebook environment, we don't really create a `main.py` file
3
+ with the main entrypoint of the program. Because the logic is mostly encoded
4
+ inside the `Model` class, we need to create a `main.py` file that we can run in
5
+ Nextmv Cloud. This file is used as that entrypoint. It is not intended for a
6
+ human to use it during local development. It is the standard way in which a
7
+ `nextmv.Model` is loaded by using mlflow.
8
+ """
9
+
10
+ from mlflow.pyfunc import load_model
11
+
12
+ import nextmv
13
+ from nextmv import cloud
14
+
15
+
16
+ def main() -> None:
17
+ """Entry point for the program."""
18
+
19
+ manifest = cloud.Manifest.from_yaml(".")
20
+
21
+ # Load the options from the manifest.
22
+ options = manifest.extract_options()
23
+
24
+ # Load the model.
25
+ loaded_model = load_model(
26
+ model_uri=manifest.python.model.name,
27
+ suppress_warnings=True,
28
+ )
29
+
30
+ # Load the input and solve the model by using mlflow's inference API.
31
+ input = nextmv.load(options=options)
32
+ output = loaded_model.predict(input)
33
+
34
+ # Write the output.
35
+ nextmv.write(output)
36
+
37
+
38
+ if __name__ == "__main__":
39
+ main()
nextmv/__init__.py CHANGED
@@ -1,16 +1,38 @@
1
1
  """Nextmv Python SDK."""
2
2
 
3
3
  from .__about__ import __version__
4
+ from .base_model import BaseModel as BaseModel
5
+ from .base_model import from_dict as from_dict
6
+ from .input import DataFile as DataFile
4
7
  from .input import Input as Input
5
8
  from .input import InputFormat as InputFormat
6
9
  from .input import InputLoader as InputLoader
7
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
8
14
  from .input import load_local as load_local
15
+ from .input import text_data_file as text_data_file
9
16
  from .logger import log as log
10
17
  from .logger import redirect_stdout as redirect_stdout
11
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
30
+ from .model import Model as Model
31
+ from .model import ModelConfiguration as ModelConfiguration
32
+ from .options import Option as Option
12
33
  from .options import Options as Options
13
34
  from .options import Parameter as Parameter
35
+ from .output import Asset as Asset
14
36
  from .output import DataPoint as DataPoint
15
37
  from .output import LocalOutputWriter as LocalOutputWriter
16
38
  from .output import Output as Output
@@ -20,8 +42,43 @@ from .output import ResultStatistics as ResultStatistics
20
42
  from .output import RunStatistics as RunStatistics
21
43
  from .output import Series as Series
22
44
  from .output import SeriesData as SeriesData
45
+ from .output import SolutionFile as SolutionFile
23
46
  from .output import Statistics as Statistics
47
+ from .output import Visual as Visual
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
24
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 poll as poll
57
+ from .run import ErrorLog as ErrorLog
58
+ from .run import ExternalRunResult as ExternalRunResult
59
+ from .run import Format as Format
60
+ from .run import FormatInput as FormatInput
61
+ from .run import FormatOutput as FormatOutput
62
+ from .run import Metadata as Metadata
63
+ from .run import OptionsSummaryItem as OptionsSummaryItem
64
+ from .run import Run as Run
65
+ from .run import RunConfiguration as RunConfiguration
66
+ from .run import RunInformation as RunInformation
67
+ from .run import RunInfoStatistics as RunInfoStatistics
68
+ from .run import RunLog as RunLog
69
+ from .run import RunQueuing as RunQueuing
70
+ from .run import RunResult as RunResult
71
+ from .run import RunType as RunType
72
+ from .run import RunTypeConfiguration as RunTypeConfiguration
73
+ from .run import StatisticsIndicator as StatisticsIndicator
74
+ from .run import SyncedRun as SyncedRun
75
+ from .run import TrackedRun as TrackedRun
76
+ from .run import TrackedRunStatus as TrackedRunStatus
77
+ from .run import run_duration as run_duration
78
+ from .safe import safe_id as safe_id
79
+ from .safe import safe_name_and_id as safe_name_and_id
80
+ from .status import Status as Status
81
+ from .status import StatusV2 as StatusV2
25
82
 
26
83
  VERSION = __version__
27
84
  """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,20 +1,90 @@
1
- """JSON class for data wrangling JSON objects."""
1
+ """
2
+ Provides base functionality for handling JSON data in models.
2
3
 
3
- from typing import Any, Dict
4
+ This module contains utilities for converting between dictionaries and model
5
+ instances, facilitating data serialization and deserialization.
4
6
 
5
- from pydantic import BaseModel
7
+ Classes
8
+ -------
9
+ BaseModel:
10
+ A base class extending Pydantic's BaseModel with additional methods for
11
+ JSON data serialization and deserialization.
6
12
 
13
+ Functions
14
+ ---------
15
+ from_dict:
16
+ Load a data model instance from a dictionary containing class information
17
+ and attributes.
18
+ """
7
19
 
8
- class BaseModel(BaseModel):
9
- """Base class for data wrangling tasks with JSON."""
20
+ from importlib import import_module
21
+ from typing import Any
22
+
23
+ from pydantic import BaseModel as PydanticBaseModel
24
+
25
+
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
+ """
10
33
 
11
34
  @classmethod
12
- def from_dict(cls, data: Dict[str, Any]):
13
- """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
+ """
50
+
51
+ if data is None:
52
+ return None
14
53
 
15
54
  return cls(**data)
16
55
 
17
- def to_dict(self) -> Dict[str, Any]:
18
- """Converts the class to a dict."""
56
+ def to_dict(self) -> dict[str, Any]:
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
+ """
19
68
 
20
69
  return self.model_dump(mode="json", exclude_none=True, by_alias=True)
70
+
71
+
72
+ def from_dict(data: dict[str, Any]) -> Any:
73
+ """
74
+ Load a data model instance from a `dict` with associated class info.
75
+
76
+ Parameters
77
+ ----------
78
+ data : dict[str, Any]
79
+ The data to load.
80
+
81
+ Returns
82
+ -------
83
+ Any
84
+ The loaded data model instance.
85
+ """
86
+
87
+ module = import_module(data["class"]["module"])
88
+ cls = getattr(module, data["class"]["name"])
89
+
90
+ return cls.from_dict(data["attributes"])
nextmv/cloud/__init__.py CHANGED
@@ -1,28 +1,89 @@
1
1
  """Functionality for interacting with the Nextmv Cloud."""
2
2
 
3
+ # These imports are kept for backwards compatibility but the preferred import path is
4
+ # from nextmv directly. These imports will be removed in a future release.
5
+ from nextmv.manifest import MANIFEST_FILE_NAME as MANIFEST_FILE_NAME
6
+ from nextmv.manifest import Manifest as Manifest
7
+ from nextmv.manifest import ManifestBuild as ManifestBuild
8
+ from nextmv.manifest import ManifestContent as ManifestContent
9
+ from nextmv.manifest import ManifestContentMultiFile as ManifestContentMultiFile
10
+ from nextmv.manifest import ManifestContentMultiFileInput as ManifestContentMultiFileInput
11
+ from nextmv.manifest import ManifestContentMultiFileOutput as ManifestContentMultiFileOutput
12
+ from nextmv.manifest import ManifestOption as ManifestOption
13
+ from nextmv.manifest import ManifestPython as ManifestPython
14
+ from nextmv.manifest import ManifestPythonModel as ManifestPythonModel
15
+ from nextmv.manifest import ManifestRuntime as ManifestRuntime
16
+ from nextmv.manifest import ManifestType as ManifestType
17
+ from nextmv.polling import PollingOptions as PollingOptions
18
+ from nextmv.run import ErrorLog as ErrorLog
19
+ from nextmv.run import ExternalRunResult as ExternalRunResult
20
+ from nextmv.run import Format as Format
21
+ from nextmv.run import FormatInput as FormatInput
22
+ from nextmv.run import FormatOutput as FormatOutput
23
+ from nextmv.run import Metadata as Metadata
24
+ from nextmv.run import RunConfiguration as RunConfiguration
25
+ from nextmv.run import RunInformation as RunInformation
26
+ from nextmv.run import RunLog as RunLog
27
+ from nextmv.run import RunQueuing as RunQueuing
28
+ from nextmv.run import RunResult as RunResult
29
+ from nextmv.run import RunType as RunType
30
+ from nextmv.run import RunTypeConfiguration as RunTypeConfiguration
31
+ from nextmv.run import TrackedRun as TrackedRun
32
+ from nextmv.run import TrackedRunStatus as TrackedRunStatus
33
+ from nextmv.run import run_duration as run_duration
34
+ from nextmv.safe import safe_id as safe_id
35
+ from nextmv.safe import safe_name_and_id as safe_name_and_id
36
+ from nextmv.status import Status as Status
37
+ from nextmv.status import StatusV2 as StatusV2
38
+
3
39
  from .acceptance_test import AcceptanceTest as AcceptanceTest
40
+ from .acceptance_test import AcceptanceTestResults as AcceptanceTestResults
4
41
  from .acceptance_test import Comparison as Comparison
5
42
  from .acceptance_test import ComparisonInstance as ComparisonInstance
43
+ from .acceptance_test import DistributionPercentiles as DistributionPercentiles
44
+ from .acceptance_test import DistributionSummaryStatistics as DistributionSummaryStatistics
6
45
  from .acceptance_test import Metric as Metric
7
46
  from .acceptance_test import MetricParams as MetricParams
47
+ from .acceptance_test import MetricResult as MetricResult
48
+ from .acceptance_test import MetricStatistics as MetricStatistics
49
+ from .acceptance_test import MetricTolerance as MetricTolerance
50
+ from .acceptance_test import MetricToleranceType as MetricToleranceType
8
51
  from .acceptance_test import MetricType as MetricType
52
+ from .acceptance_test import ResultStatistics as ResultStatistics
53
+ from .acceptance_test import StatisticType as StatisticType
54
+ from .acceptance_test import ToleranceType as ToleranceType
9
55
  from .account import Account as Account
10
56
  from .account import Queue as Queue
11
57
  from .account import QueuedRun as QueuedRun
12
58
  from .application import Application as Application
13
- from .application import Configuration as Configuration
14
- from .application import DownloadURL as DownloadURL
15
- from .application import ErrorLog as ErrorLog
16
- from .application import Metadata as Metadata
17
- from .application import PollingOptions as PollingOptions
18
- from .application import RunInformation as RunInformation
19
- from .application import RunResult as RunResult
20
- from .application import UploadURL as UploadURL
59
+ from .application import poll as poll
21
60
  from .batch_experiment import BatchExperiment as BatchExperiment
22
61
  from .batch_experiment import BatchExperimentInformation as BatchExperimentInformation
23
62
  from .batch_experiment import BatchExperimentMetadata as BatchExperimentMetadata
24
63
  from .batch_experiment import BatchExperimentRun as BatchExperimentRun
64
+ from .batch_experiment import ExperimentStatus as ExperimentStatus
25
65
  from .client import Client as Client
66
+ from .client import get_size as get_size
67
+ from .ensemble import EnsembleDefinition as EnsembleDefinition
68
+ from .ensemble import EvaluationRule as EvaluationRule
69
+ from .ensemble import RuleObjective as RuleObjective
70
+ from .ensemble import RuleTolerance as RuleTolerance
71
+ from .ensemble import RuleToleranceType as RuleToleranceType
72
+ from .ensemble import RunGroup as RunGroup
26
73
  from .input_set import InputSet as InputSet
27
- from .status import Status as Status
28
- from .status import StatusV2 as StatusV2
74
+ from .input_set import ManagedInput as ManagedInput
75
+ from .instance import Instance as Instance
76
+ from .instance import InstanceConfiguration as InstanceConfiguration
77
+ from .scenario import Scenario as Scenario
78
+ from .scenario import ScenarioConfiguration as ScenarioConfiguration
79
+ from .scenario import ScenarioInput as ScenarioInput
80
+ from .scenario import ScenarioInputType as ScenarioInputType
81
+ from .secrets import Secret as Secret
82
+ from .secrets import SecretsCollection as SecretsCollection
83
+ from .secrets import SecretsCollectionSummary as SecretsCollectionSummary
84
+ from .secrets import SecretType as SecretType
85
+ from .url import DownloadURL as DownloadURL
86
+ from .url import UploadURL as UploadURL
87
+ from .version import Version as Version
88
+ from .version import VersionExecutable as VersionExecutable
89
+ from .version import VersionExecutableRequirements as VersionExecutableRequirements