nextmv 0.34.0.dev0__tar.gz → 0.34.0.dev2__tar.gz
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-0.34.0.dev0 → nextmv-0.34.0.dev2}/PKG-INFO +1 -1
- nextmv-0.34.0.dev2/nextmv/__about__.py +1 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/__init__.py +1 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/application.py +65 -46
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/executor.py +43 -1
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/manifest.py +35 -5
- nextmv-0.34.0.dev0/nextmv/__about__.py +0 -1
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/.gitignore +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/LICENSE +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/README.md +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/__entrypoint__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/_serialization.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/base_model.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/acceptance_test.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/account.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/application.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/batch_experiment.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/client.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/ensemble.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/input_set.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/instance.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/package.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/scenario.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/secrets.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/url.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/cloud/version.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/.gitignore +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/README.md +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/app.yaml +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/input.json +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/main.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/requirements.txt +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/src/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/src/main.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/default_app/src/visuals.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/deprecated.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/input.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/geojson_handler.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/local.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/plotly_handler.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/local/runner.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/logger.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/model.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/options.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/output.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/polling.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/run.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/safe.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/nextmv/status.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/pyproject.toml +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/cloud/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/cloud/app.yaml +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/cloud/test_client.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/cloud/test_package.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/cloud/test_scenario.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/local/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/local/test_application.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/local/test_executor.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/local/test_runner.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options1.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options2.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options3.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options4.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options5.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options6.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options7.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/scripts/options_deprecated.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_base_model.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_entrypoint/__init__.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_entrypoint/test_entrypoint.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_input.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_inputs/test_data.csv +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_inputs/test_data.json +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_inputs/test_data.txt +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_logger.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_manifest.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_model.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_options.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_output.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_polling.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_run.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_safe.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_serialization.py +0 -0
- {nextmv-0.34.0.dev0 → nextmv-0.34.0.dev2}/tests/test_version.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "v0.34.0.dev2"
|
|
@@ -25,6 +25,7 @@ from .manifest import ManifestPythonArch as ManifestPythonArch
|
|
|
25
25
|
from .manifest import ManifestPythonModel as ManifestPythonModel
|
|
26
26
|
from .manifest import ManifestRuntime as ManifestRuntime
|
|
27
27
|
from .manifest import ManifestType as ManifestType
|
|
28
|
+
from .manifest import default_python_manifest as default_python_manifest
|
|
28
29
|
from .model import Model as Model
|
|
29
30
|
from .model import ModelConfiguration as ModelConfiguration
|
|
30
31
|
from .options import Option as Option
|
|
@@ -33,13 +33,14 @@ from nextmv.local.local import (
|
|
|
33
33
|
)
|
|
34
34
|
from nextmv.local.runner import run
|
|
35
35
|
from nextmv.logger import log
|
|
36
|
-
from nextmv.manifest import Manifest
|
|
36
|
+
from nextmv.manifest import Manifest, default_python_manifest
|
|
37
37
|
from nextmv.options import Options
|
|
38
38
|
from nextmv.output import ASSETS_KEY, OUTPUTS_KEY, SOLUTIONS_KEY, STATISTICS_KEY, OutputFormat
|
|
39
39
|
from nextmv.polling import DEFAULT_POLLING_OPTIONS, PollingOptions, poll
|
|
40
40
|
from nextmv.run import (
|
|
41
41
|
ErrorLog,
|
|
42
42
|
Format,
|
|
43
|
+
FormatInput,
|
|
43
44
|
Run,
|
|
44
45
|
RunConfiguration,
|
|
45
46
|
RunInformation,
|
|
@@ -93,6 +94,39 @@ class Application:
|
|
|
93
94
|
|
|
94
95
|
description: Optional[str] = None
|
|
95
96
|
"""Description of the application."""
|
|
97
|
+
manifest: Optional[Manifest] = None
|
|
98
|
+
"""
|
|
99
|
+
Manifest of the application. A manifest is a file named `app.yaml` that
|
|
100
|
+
must be present at the root of the application's `src` directory. If the
|
|
101
|
+
app is initialized, and a manifest is not present, a default Python
|
|
102
|
+
manifest will be created, using the `nextmv.default_python_manifest`
|
|
103
|
+
function. If you specify this argument, and a manifest file is already
|
|
104
|
+
present in the `src` directory, the provided manifest will override the
|
|
105
|
+
existing one.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def __post_init__(self):
|
|
109
|
+
"""
|
|
110
|
+
Validate the presence of the manifest in the application.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
if self.manifest is not None:
|
|
114
|
+
self.manifest.to_yaml(self.src)
|
|
115
|
+
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
manifest = Manifest.from_yaml(self.src)
|
|
120
|
+
self.manifest = manifest
|
|
121
|
+
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
except Exception:
|
|
125
|
+
manifest = default_python_manifest()
|
|
126
|
+
self.manifest = manifest
|
|
127
|
+
manifest.to_yaml(self.src)
|
|
128
|
+
|
|
129
|
+
return
|
|
96
130
|
|
|
97
131
|
@classmethod
|
|
98
132
|
def initialize(
|
|
@@ -293,7 +327,7 @@ class Application:
|
|
|
293
327
|
>>> print(f"Local run completed with ID: {run_id}")
|
|
294
328
|
"""
|
|
295
329
|
|
|
296
|
-
self.__validate_input_dir_path_and_configuration(input_dir_path, configuration)
|
|
330
|
+
configuration = self.__validate_input_dir_path_and_configuration(input_dir_path, configuration)
|
|
297
331
|
|
|
298
332
|
if self.src is None:
|
|
299
333
|
raise ValueError("`src` property for the `Application` must be specified to run the application locally")
|
|
@@ -853,7 +887,7 @@ class Application:
|
|
|
853
887
|
self,
|
|
854
888
|
input_dir_path: Optional[str],
|
|
855
889
|
configuration: Optional[Union[RunConfiguration, dict[str, Any]]],
|
|
856
|
-
) ->
|
|
890
|
+
) -> RunConfiguration:
|
|
857
891
|
"""
|
|
858
892
|
Auxiliary function to validate the directory path and configuration.
|
|
859
893
|
"""
|
|
@@ -862,60 +896,45 @@ class Application:
|
|
|
862
896
|
return
|
|
863
897
|
|
|
864
898
|
if configuration is None:
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
899
|
+
if self.manifest.configuration is not None and self.manifest.configuration.content is not None:
|
|
900
|
+
configuration = RunConfiguration(
|
|
901
|
+
format=Format(
|
|
902
|
+
format_input=FormatInput(
|
|
903
|
+
input_type=self.manifest.configuration.content.format,
|
|
904
|
+
),
|
|
905
|
+
),
|
|
906
|
+
)
|
|
907
|
+
else:
|
|
908
|
+
raise ValueError(
|
|
909
|
+
"If `dir_path` is provided, either a `RunConfiguration` must also be provided or "
|
|
910
|
+
"the application's manifest (app.yaml) must include the format under "
|
|
911
|
+
"`configuration.content.format`.",
|
|
912
|
+
)
|
|
868
913
|
|
|
869
|
-
|
|
914
|
+
# Forcefully turn the configuration into a RunConfiguration object to
|
|
915
|
+
# make it easier to deal with in the other functions.
|
|
916
|
+
if isinstance(configuration, dict):
|
|
917
|
+
configuration = RunConfiguration.from_dict(configuration)
|
|
870
918
|
|
|
919
|
+
config_format = configuration.format
|
|
871
920
|
if config_format is None:
|
|
872
921
|
raise ValueError(
|
|
873
|
-
"If dir_path is provided, RunConfiguration.format must also be provided.",
|
|
922
|
+
"If `dir_path` is provided, `RunConfiguration.format` must also be provided.",
|
|
874
923
|
)
|
|
875
924
|
|
|
876
|
-
input_type =
|
|
877
|
-
|
|
878
|
-
if input_type is None or input_type in (InputFormat.JSON, InputFormat.TEXT):
|
|
925
|
+
input_type = config_format.format_input
|
|
926
|
+
if input_type is None:
|
|
879
927
|
raise ValueError(
|
|
880
|
-
"If dir_path is provided, RunConfiguration.format.format_input
|
|
881
|
-
f"Valid types are: {[InputFormat.CSV_ARCHIVE, InputFormat.MULTI_FILE]}",
|
|
928
|
+
"If `dir_path` is provided, `RunConfiguration.format.format_input` must also be provided.",
|
|
882
929
|
)
|
|
883
930
|
|
|
884
|
-
|
|
885
|
-
"""Extract format from configuration, handling both RunConfiguration objects and dicts."""
|
|
886
|
-
if isinstance(configuration, RunConfiguration):
|
|
887
|
-
return configuration.format
|
|
888
|
-
|
|
889
|
-
if isinstance(configuration, dict):
|
|
890
|
-
config_format = configuration.get("format")
|
|
891
|
-
if config_format is not None and isinstance(config_format, dict):
|
|
892
|
-
return Format.from_dict(config_format) if hasattr(Format, "from_dict") else config_format
|
|
893
|
-
|
|
894
|
-
return config_format
|
|
895
|
-
|
|
896
|
-
raise ValueError("Configuration must be a RunConfiguration object or a dict.")
|
|
897
|
-
|
|
898
|
-
def __extract_input_type(self, config_format: Any) -> Any:
|
|
899
|
-
"""Extract input type from config format."""
|
|
900
|
-
if isinstance(config_format, dict):
|
|
901
|
-
format_input = config_format.get("format_input") or config_format.get("input")
|
|
902
|
-
if format_input is None:
|
|
903
|
-
raise ValueError(
|
|
904
|
-
"If dir_path is provided, RunConfiguration.format.format_input must also be provided.",
|
|
905
|
-
)
|
|
906
|
-
|
|
907
|
-
if isinstance(format_input, dict):
|
|
908
|
-
return format_input.get("input_type") or format_input.get("type")
|
|
909
|
-
|
|
910
|
-
return getattr(format_input, "input_type", None)
|
|
911
|
-
|
|
912
|
-
# Handle Format object
|
|
913
|
-
if config_format.format_input is None:
|
|
931
|
+
if input_type is None or input_type in (InputFormat.JSON, InputFormat.TEXT):
|
|
914
932
|
raise ValueError(
|
|
915
|
-
"If dir_path is provided, RunConfiguration.format.format_input must
|
|
933
|
+
"If `dir_path` is provided, `RunConfiguration.format.format_input.input_type` must be set to "
|
|
934
|
+
f"a valid type. Valid types are: {[InputFormat.CSV_ARCHIVE, InputFormat.MULTI_FILE]}",
|
|
916
935
|
)
|
|
917
936
|
|
|
918
|
-
return
|
|
937
|
+
return configuration
|
|
919
938
|
|
|
920
939
|
def __extract_input_data(
|
|
921
940
|
self,
|
|
@@ -1026,7 +1045,7 @@ class Application:
|
|
|
1026
1045
|
# Read the logs of the run and place each line as an element in a list
|
|
1027
1046
|
run_dir = os.path.join(runs_dir, run_id)
|
|
1028
1047
|
with open(os.path.join(run_dir, LOGS_KEY, LOGS_FILE)) as f:
|
|
1029
|
-
stderr_logs =
|
|
1048
|
+
stderr_logs = f.read()
|
|
1030
1049
|
|
|
1031
1050
|
# Create the tracked run object and start configuring it.
|
|
1032
1051
|
tracked_run = TrackedRun(
|
|
@@ -907,6 +907,9 @@ def _copy_new_or_modified_files(
|
|
|
907
907
|
3. Files that are NOT present in the original source directory (if provided)
|
|
908
908
|
4. Files that are NOT present in any of the exclusion directories (if provided)
|
|
909
909
|
|
|
910
|
+
Empty directories are not created or are removed after copying to avoid
|
|
911
|
+
cluttering the output with empty folders.
|
|
912
|
+
|
|
910
913
|
Parameters
|
|
911
914
|
----------
|
|
912
915
|
src_dir : str
|
|
@@ -927,11 +930,12 @@ def _copy_new_or_modified_files(
|
|
|
927
930
|
if exclusion_dirs is not None:
|
|
928
931
|
exclusion_directories.extend(exclusion_dirs)
|
|
929
932
|
|
|
933
|
+
files_copied = False
|
|
930
934
|
for root, _dirs, files in os.walk(src_dir):
|
|
931
935
|
rel_root = os.path.relpath(root, src_dir)
|
|
932
936
|
dst_root = dst_dir if rel_root == "." else os.path.join(dst_dir, rel_root)
|
|
933
|
-
os.makedirs(dst_root, exist_ok=True)
|
|
934
937
|
|
|
938
|
+
files_to_copy = []
|
|
935
939
|
for file in files:
|
|
936
940
|
# Skip if file exists in any exclusion directory
|
|
937
941
|
if exclusion_directories and _file_exists_in_exclusion_dirs(file, rel_root, exclusion_directories):
|
|
@@ -941,7 +945,45 @@ def _copy_new_or_modified_files(
|
|
|
941
945
|
dst_file = os.path.join(dst_root, file)
|
|
942
946
|
|
|
943
947
|
if _should_copy_file(src_file, dst_file):
|
|
948
|
+
files_to_copy.append((src_file, dst_file))
|
|
949
|
+
|
|
950
|
+
# Only create directory if there are files to copy
|
|
951
|
+
if files_to_copy:
|
|
952
|
+
os.makedirs(dst_root, exist_ok=True)
|
|
953
|
+
for src_file, dst_file in files_to_copy:
|
|
944
954
|
shutil.copy2(src_file, dst_file)
|
|
955
|
+
files_copied = True
|
|
956
|
+
|
|
957
|
+
# Clean up empty directories after copying
|
|
958
|
+
if files_copied:
|
|
959
|
+
_remove_empty_directories(dst_dir)
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
def _remove_empty_directories(directory: str) -> None:
|
|
963
|
+
"""
|
|
964
|
+
Recursively remove empty directories starting from the given directory.
|
|
965
|
+
|
|
966
|
+
This function walks the directory tree bottom-up and removes any directories
|
|
967
|
+
that are empty after all files have been processed. It preserves the root
|
|
968
|
+
directory even if it's empty.
|
|
969
|
+
|
|
970
|
+
Parameters
|
|
971
|
+
----------
|
|
972
|
+
directory : str
|
|
973
|
+
The root directory path to start cleaning from.
|
|
974
|
+
"""
|
|
975
|
+
for root, dirs, files in os.walk(directory, topdown=False):
|
|
976
|
+
# Skip the root directory itself
|
|
977
|
+
if root == directory:
|
|
978
|
+
continue
|
|
979
|
+
|
|
980
|
+
# If directory is empty (no files and no subdirectories), remove it
|
|
981
|
+
if not files and not dirs:
|
|
982
|
+
try:
|
|
983
|
+
os.rmdir(root)
|
|
984
|
+
except OSError:
|
|
985
|
+
# Directory might not be empty due to hidden files or permissions
|
|
986
|
+
pass
|
|
945
987
|
|
|
946
988
|
|
|
947
989
|
def _should_copy_file(src_file: str, dst_file: str) -> bool:
|
|
@@ -357,19 +357,24 @@ class ManifestPython(BaseModel):
|
|
|
357
357
|
validation_alias=AliasChoices("pip-requirements", "pip_requirements"),
|
|
358
358
|
default=None,
|
|
359
359
|
)
|
|
360
|
-
"""
|
|
360
|
+
"""
|
|
361
|
+
Path to a requirements.txt file.
|
|
361
362
|
|
|
362
363
|
Contains (additional) Python dependencies that will be bundled with the
|
|
363
364
|
app.
|
|
364
365
|
"""
|
|
365
366
|
arch: Optional[ManifestPythonArch] = None
|
|
366
|
-
"""
|
|
367
|
-
"arm64"
|
|
367
|
+
"""
|
|
368
|
+
The architecture this model is meant to run on. One of "arm64" or "amd64". Uses
|
|
369
|
+
"arm64" if not specified.
|
|
370
|
+
"""
|
|
368
371
|
version: Optional[Union[str, float]] = None
|
|
369
|
-
"""
|
|
372
|
+
"""
|
|
373
|
+
The Python version this model is meant to run with. Uses "3.11" if not specified.
|
|
370
374
|
"""
|
|
371
375
|
model: Optional[ManifestPythonModel] = None
|
|
372
|
-
"""
|
|
376
|
+
"""
|
|
377
|
+
Information about an encoded decision model.
|
|
373
378
|
|
|
374
379
|
As handled via mlflow. This information is used to load the decision model
|
|
375
380
|
from the app bundle.
|
|
@@ -1352,3 +1357,28 @@ class Manifest(BaseModel):
|
|
|
1352
1357
|
)
|
|
1353
1358
|
|
|
1354
1359
|
return manifest
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
def default_python_manifest() -> Manifest:
|
|
1363
|
+
"""
|
|
1364
|
+
Creates a default Python manifest as a starting point for applications
|
|
1365
|
+
being executed on the Nextmv Platform.
|
|
1366
|
+
|
|
1367
|
+
You can import the `default_python_manifest` function directly from `nextmv`:
|
|
1368
|
+
|
|
1369
|
+
```python
|
|
1370
|
+
from nextmv import default_python_manifest
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
Returns
|
|
1374
|
+
-------
|
|
1375
|
+
Manifest
|
|
1376
|
+
A default Python manifest with common settings.
|
|
1377
|
+
"""
|
|
1378
|
+
|
|
1379
|
+
return Manifest(
|
|
1380
|
+
files=["main.py"],
|
|
1381
|
+
runtime=ManifestRuntime.PYTHON,
|
|
1382
|
+
type=ManifestType.PYTHON,
|
|
1383
|
+
python=ManifestPython(pip_requirements="requirements.txt"),
|
|
1384
|
+
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "v0.34.0.dev0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|