nextmv 0.35.0__py3-none-any.whl → 0.35.0.dev0__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.
@@ -17,7 +17,7 @@ import tempfile
17
17
  import webbrowser
18
18
  from dataclasses import dataclass
19
19
  from datetime import datetime, timezone
20
- from typing import Any
20
+ from typing import Any, Optional, Union
21
21
 
22
22
  from nextmv import cloud
23
23
  from nextmv._serialization import deflated_serialize_json
@@ -92,9 +92,9 @@ class Application:
92
92
  manifest.
93
93
  """
94
94
 
95
- description: str | None = None
95
+ description: Optional[str] = None
96
96
  """Description of the application."""
97
- manifest: Manifest | None = None
97
+ manifest: Optional[Manifest] = None
98
98
  """
99
99
  Manifest of the application. A manifest is a file named `app.yaml` that
100
100
  must be present at the root of the application's `src` directory. If the
@@ -131,9 +131,9 @@ class Application:
131
131
  @classmethod
132
132
  def initialize(
133
133
  cls,
134
- src: str | None = None,
135
- description: str | None = None,
136
- destination: str | None = None,
134
+ src: Optional[str] = None,
135
+ description: Optional[str] = None,
136
+ destination: Optional[str] = None,
137
137
  ) -> "Application":
138
138
  """
139
139
  Initialize a sample Nextmv application, locally.
@@ -224,13 +224,13 @@ class Application:
224
224
 
225
225
  def new_run(
226
226
  self,
227
- input: Input | dict[str, Any] | BaseModel | str = None,
228
- name: str | None = None,
229
- description: str | None = None,
230
- options: Options | dict[str, str] | None = None,
231
- configuration: RunConfiguration | dict[str, Any] | None = None,
232
- json_configurations: dict[str, Any] | None = None,
233
- input_dir_path: str | None = None,
227
+ input: Union[Input, dict[str, Any], BaseModel, str] = None,
228
+ name: Optional[str] = None,
229
+ description: Optional[str] = None,
230
+ options: Optional[Union[Options, dict[str, str]]] = None,
231
+ configuration: Optional[Union[RunConfiguration, dict[str, Any]]] = None,
232
+ json_configurations: Optional[dict[str, Any]] = None,
233
+ input_dir_path: Optional[str] = None,
234
234
  ) -> str:
235
235
  """
236
236
  Run the application locally with the provided input.
@@ -361,15 +361,15 @@ class Application:
361
361
 
362
362
  def new_run_with_result(
363
363
  self,
364
- input: Input | dict[str, Any] | BaseModel | str = None,
365
- name: str | None = None,
366
- description: str | None = None,
367
- run_options: Options | dict[str, str] | None = None,
364
+ input: Union[Input, dict[str, Any], BaseModel, str] = None,
365
+ name: Optional[str] = None,
366
+ description: Optional[str] = None,
367
+ run_options: Optional[Union[Options, dict[str, str]]] = None,
368
368
  polling_options: PollingOptions = DEFAULT_POLLING_OPTIONS,
369
- configuration: RunConfiguration | dict[str, Any] | None = None,
370
- json_configurations: dict[str, Any] | None = None,
371
- input_dir_path: str | None = None,
372
- output_dir_path: str | None = ".",
369
+ configuration: Optional[Union[RunConfiguration, dict[str, Any]]] = None,
370
+ json_configurations: Optional[dict[str, Any]] = None,
371
+ input_dir_path: Optional[str] = None,
372
+ output_dir_path: Optional[str] = ".",
373
373
  ) -> RunResult:
374
374
  """
375
375
  Submit an input to start a new local run of the application and poll
@@ -526,7 +526,7 @@ class Application:
526
526
  if not os.path.exists(run_dir):
527
527
  raise ValueError(f"`{run_id}` run dir does not exist at: {runs_dir}")
528
528
 
529
- logs_dir = os.path.join(run_dir, LOGS_KEY)
529
+ logs_dir = os.path.join(runs_dir, LOGS_KEY)
530
530
  if not os.path.exists(logs_dir):
531
531
  return ""
532
532
 
@@ -594,7 +594,7 @@ class Application:
594
594
 
595
595
  return info
596
596
 
597
- def run_result(self, run_id: str, output_dir_path: str | None = ".") -> RunResult:
597
+ def run_result(self, run_id: str, output_dir_path: Optional[str] = ".") -> RunResult:
598
598
  """
599
599
  Get the local result of a run.
600
600
 
@@ -644,7 +644,7 @@ class Application:
644
644
  self,
645
645
  run_id: str,
646
646
  polling_options: PollingOptions = DEFAULT_POLLING_OPTIONS,
647
- output_dir_path: str | None = ".",
647
+ output_dir_path: Optional[str] = ".",
648
648
  ) -> RunResult:
649
649
  """
650
650
  Get the result of a local run with polling.
@@ -761,9 +761,9 @@ class Application:
761
761
  def sync( # noqa: C901
762
762
  self,
763
763
  target: cloud.Application,
764
- run_ids: list[str] | None = None,
765
- instance_id: str | None = None,
766
- verbose: bool | None = False,
764
+ run_ids: Optional[list[str]] = None,
765
+ instance_id: Optional[str] = None,
766
+ verbose: Optional[bool] = False,
767
767
  ) -> None:
768
768
  """
769
769
  Sync the local application to a Nextmv Cloud application target.
@@ -867,7 +867,7 @@ class Application:
867
867
  self,
868
868
  run_id: str,
869
869
  run_information: RunInformation,
870
- output_dir_path: str | None = ".",
870
+ output_dir_path: Optional[str] = ".",
871
871
  ) -> RunResult:
872
872
  """
873
873
  Get the result of a local run.
@@ -931,8 +931,8 @@ class Application:
931
931
 
932
932
  def __validate_input_dir_path_and_configuration(
933
933
  self,
934
- input_dir_path: str | None,
935
- configuration: RunConfiguration | dict[str, Any] | None,
934
+ input_dir_path: Optional[str],
935
+ configuration: Optional[Union[RunConfiguration, dict[str, Any]]],
936
936
  ) -> RunConfiguration:
937
937
  """
938
938
  Auxiliary function to validate the directory path and configuration.
@@ -984,8 +984,8 @@ class Application:
984
984
 
985
985
  def __extract_input_data(
986
986
  self,
987
- input: Input | dict[str, Any] | BaseModel | str = None,
988
- ) -> dict[str, Any] | str | None:
987
+ input: Union[Input, dict[str, Any], BaseModel, str] = None,
988
+ ) -> Optional[Union[dict[str, Any], str]]:
989
989
  """
990
990
  Auxiliary function to extract the input data from the input, based on
991
991
  its type.
@@ -1003,8 +1003,8 @@ class Application:
1003
1003
 
1004
1004
  def __extract_options_dict(
1005
1005
  self,
1006
- options: Options | dict[str, str] | None = None,
1007
- json_configurations: dict[str, Any] | None = None,
1006
+ options: Optional[Union[Options, dict[str, str]]] = None,
1007
+ json_configurations: Optional[dict[str, Any]] = None,
1008
1008
  ) -> dict[str, str]:
1009
1009
  """
1010
1010
  Auxiliary function to extract the options that will be sent to the
@@ -1026,9 +1026,9 @@ class Application:
1026
1026
 
1027
1027
  def __extract_run_config(
1028
1028
  self,
1029
- input: Input | dict[str, Any] | BaseModel | str = None,
1030
- configuration: RunConfiguration | dict[str, Any] | None = None,
1031
- dir_path: str | None = None,
1029
+ input: Union[Input, dict[str, Any], BaseModel, str] = None,
1030
+ configuration: Optional[Union[RunConfiguration, dict[str, Any]]] = None,
1031
+ dir_path: Optional[str] = None,
1032
1032
  ) -> dict[str, Any]:
1033
1033
  """
1034
1034
  Auxiliary function to extract the run configuration that will be sent
@@ -1053,8 +1053,8 @@ class Application:
1053
1053
  run_id: str,
1054
1054
  runs_dir: str,
1055
1055
  temp_dir: str,
1056
- instance_id: str | None = None,
1057
- verbose: bool | None = False,
1056
+ instance_id: Optional[str] = None,
1057
+ verbose: Optional[bool] = False,
1058
1058
  ) -> bool:
1059
1059
  """
1060
1060
  Syncs a local run to a Nextmv Cloud target application. Returns True if
nextmv/local/executor.py CHANGED
@@ -43,7 +43,7 @@ import subprocess
43
43
  import sys
44
44
  import tempfile
45
45
  from datetime import datetime, timezone
46
- from typing import Any
46
+ from typing import Any, Optional, Union
47
47
 
48
48
  from nextmv.input import INPUTS_KEY, InputFormat, load
49
49
  from nextmv.local.geojson_handler import handle_geojson_visual
@@ -56,7 +56,7 @@ from nextmv.local.local import (
56
56
  calculate_files_size,
57
57
  )
58
58
  from nextmv.local.plotly_handler import handle_plotly_visual
59
- from nextmv.manifest import Manifest, ManifestType
59
+ from nextmv.manifest import Manifest
60
60
  from nextmv.output import ASSETS_KEY, OUTPUTS_KEY, SOLUTIONS_KEY, STATISTICS_KEY, Asset, OutputFormat, VisualSchema
61
61
  from nextmv.status import StatusV2
62
62
 
@@ -87,9 +87,9 @@ def execute_run(
87
87
  manifest_dict: dict[str, Any],
88
88
  run_dir: str,
89
89
  run_config: dict[str, Any],
90
- inputs_dir_path: str | None = None,
91
- options: dict[str, Any] | None = None,
92
- input_data: dict[str, Any] | str | None = None,
90
+ inputs_dir_path: Optional[str] = None,
91
+ options: Optional[dict[str, Any]] = None,
92
+ input_data: Optional[Union[dict[str, Any], str]] = None,
93
93
  ) -> None:
94
94
  """
95
95
  Executes the decision model run using a subprocess to call the entrypoint
@@ -152,8 +152,7 @@ def execute_run(
152
152
  # Start a Python subprocess to execute the entrypoint. For now, we are
153
153
  # supporting a Python-first experience, so we are not summoning
154
154
  # applications that are not Python-based.
155
- entrypoint = os.path.join(temp_src, __determine_entrypoint(manifest))
156
- cwd = __determine_cwd(manifest, default=temp_src)
155
+ entrypoint = os.path.join(temp_src, manifest.entrypoint)
157
156
  args = [sys.executable, entrypoint] + options_args(options)
158
157
 
159
158
  result = subprocess.run(
@@ -163,7 +162,7 @@ def execute_run(
163
162
  text=True,
164
163
  capture_output=True,
165
164
  input=stdin_input,
166
- cwd=cwd,
165
+ cwd=temp_src,
167
166
  )
168
167
 
169
168
  process_run_output(
@@ -191,7 +190,7 @@ def execute_run(
191
190
  f.truncate()
192
191
 
193
192
 
194
- def options_args(options: dict[str, Any] | None = None) -> list[str]:
193
+ def options_args(options: Optional[dict[str, Any]] = None) -> list[str]:
195
194
  """
196
195
  Converts options dictionary to a list of command-line arguments.
197
196
 
@@ -219,8 +218,8 @@ def process_run_input(
219
218
  temp_src: str,
220
219
  run_format: str,
221
220
  manifest: Manifest,
222
- input_data: dict[str, Any] | str | None = None,
223
- inputs_dir_path: str | None = None,
221
+ input_data: Optional[Union[dict[str, Any], str]] = None,
222
+ inputs_dir_path: Optional[str] = None,
224
223
  ) -> str:
225
224
  """
226
225
  In the temp source, writes the run input according to the run format. If
@@ -466,7 +465,7 @@ def process_run_logs(
466
465
  output_format: OutputFormat,
467
466
  run_dir: str,
468
467
  result: subprocess.CompletedProcess[str],
469
- stdout_output: str | dict[str, Any],
468
+ stdout_output: Union[str, dict[str, Any]],
470
469
  ) -> None:
471
470
  """
472
471
  Processes the logs of the run. Writes the logs to a logs directory.
@@ -503,7 +502,7 @@ def process_run_logs(
503
502
  def process_run_statistics(
504
503
  temp_run_outputs_dir: str,
505
504
  outputs_dir: str,
506
- stdout_output: str | dict[str, Any],
505
+ stdout_output: Union[str, dict[str, Any]],
507
506
  temp_src: str,
508
507
  manifest: Manifest,
509
508
  ) -> None:
@@ -564,7 +563,7 @@ def process_run_statistics(
564
563
  def process_run_assets(
565
564
  temp_run_outputs_dir: str,
566
565
  outputs_dir: str,
567
- stdout_output: str | dict[str, Any],
566
+ stdout_output: Union[str, dict[str, Any]],
568
567
  temp_src: str,
569
568
  manifest: Manifest,
570
569
  ) -> None:
@@ -628,7 +627,7 @@ def process_run_solutions(
628
627
  temp_run_outputs_dir: str,
629
628
  temp_src: str,
630
629
  outputs_dir: str,
631
- stdout_output: str | dict[str, Any],
630
+ stdout_output: Union[str, dict[str, Any]],
632
631
  output_format: OutputFormat,
633
632
  manifest: Manifest,
634
633
  src: str,
@@ -757,7 +756,7 @@ def process_run_visuals(run_dir: str, outputs_dir: str) -> None:
757
756
  # so we ignore it for now.
758
757
 
759
758
 
760
- def resolve_stdout(result: subprocess.CompletedProcess[str]) -> str | dict[str, Any]:
759
+ def resolve_stdout(result: subprocess.CompletedProcess[str]) -> Union[str, dict[str, Any]]:
761
760
  """
762
761
  Resolves the stdout output of the subprocess run. If the stdout is valid
763
762
  JSON, it returns the parsed dictionary. Otherwise, it returns the raw
@@ -839,8 +838,8 @@ def _ignore_patterns(dir_path: str, names: list[str]) -> list[str]:
839
838
  def _copy_new_or_modified_files( # noqa: C901
840
839
  runtime_dir: str,
841
840
  dst_dir: str,
842
- original_src_dir: str | None = None,
843
- exclusion_dirs: list[str] | None = None,
841
+ original_src_dir: Optional[str] = None,
842
+ exclusion_dirs: Optional[list[str]] = None,
844
843
  ) -> None:
845
844
  """
846
845
  Copy only new or modified files from runtime directory to destination directory.
@@ -1007,34 +1006,5 @@ def _calculate_file_checksum(file_path: str) -> str:
1007
1006
  return hash_md5.hexdigest()
1008
1007
 
1009
1008
 
1010
- def __determine_entrypoint(manifest: Manifest) -> str:
1011
- """Returns the default entrypoint based on the runtime if not explicitly set."""
1012
- if manifest.execution is not None and manifest.execution.entrypoint is not None:
1013
- return manifest.execution.entrypoint
1014
-
1015
- # Determine default entrypoint based on type
1016
- if manifest.type == ManifestType.PYTHON:
1017
- return "./main.py"
1018
- elif manifest.type == ManifestType.GO:
1019
- return "./main"
1020
- elif manifest.type == ManifestType.JAVA:
1021
- return "./main.jar"
1022
- else:
1023
- raise ValueError(
1024
- f'entrypoint is not provided but the app type "{manifest.type}" could not '
1025
- "be resolved to establish a default entrypoint"
1026
- )
1027
-
1028
-
1029
- def __determine_cwd(manifest: Manifest, default: str) -> str:
1030
- """
1031
- Returns the working directory based on the manifest if set, otherwise the default.
1032
- """
1033
- if manifest.execution is not None and manifest.execution.cwd is not None:
1034
- return manifest.execution.cwd
1035
-
1036
- return default
1037
-
1038
-
1039
1009
  if __name__ == "__main__":
1040
1010
  main()
nextmv/local/runner.py CHANGED
@@ -20,7 +20,7 @@ import shutil
20
20
  import subprocess
21
21
  import sys
22
22
  from datetime import datetime, timezone
23
- from typing import Any
23
+ from typing import Any, Optional, Union
24
24
 
25
25
  from nextmv.input import INPUTS_KEY
26
26
  from nextmv.local.local import DEFAULT_INPUT_JSON_FILE, NEXTMV_DIR, RUNS_KEY, calculate_files_size
@@ -34,11 +34,11 @@ def run(
34
34
  src: str,
35
35
  manifest: Manifest,
36
36
  run_config: dict[str, Any],
37
- name: str | None = None,
38
- description: str | None = None,
39
- input_data: dict[str, Any] | str | None = None,
40
- inputs_dir_path: str | None = None,
41
- options: dict[str, Any] | None = None,
37
+ name: Optional[str] = None,
38
+ description: Optional[str] = None,
39
+ input_data: Optional[Union[dict[str, Any], str]] = None,
40
+ inputs_dir_path: Optional[str] = None,
41
+ options: Optional[dict[str, Any]] = None,
42
42
  ) -> str:
43
43
  """
44
44
  Execute a local run.
@@ -145,8 +145,8 @@ def new_run(
145
145
  src: str,
146
146
  run_id: str,
147
147
  run_config: dict[str, Any],
148
- name: str | None = None,
149
- description: str | None = None,
148
+ name: Optional[str] = None,
149
+ description: Optional[str] = None,
150
150
  ) -> str:
151
151
  """
152
152
  Initializes a new run.
@@ -223,8 +223,8 @@ def new_run(
223
223
  def record_input(
224
224
  run_dir: str,
225
225
  run_id: str,
226
- input_data: dict[str, Any] | str | None = None,
227
- inputs_dir_path: str | None = None,
226
+ input_data: Optional[Union[dict[str, Any], str]] = None,
227
+ inputs_dir_path: Optional[str] = None,
228
228
  ) -> None:
229
229
  """
230
230
  Writes the input to the appropriate location.