nextmv 0.35.0__py3-none-any.whl → 0.35.0.dev1__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/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.
nextmv/manifest.py CHANGED
@@ -53,7 +53,7 @@ MANIFEST_FILE_NAME
53
53
 
54
54
  import os
55
55
  from enum import Enum
56
- from typing import Any
56
+ from typing import Any, Optional, Union
57
57
 
58
58
  import yaml
59
59
  from pydantic import AliasChoices, Field, field_validator
@@ -244,14 +244,14 @@ class ManifestBuild(BaseModel):
244
244
  'make build'
245
245
  """
246
246
 
247
- command: str | None = None
247
+ command: Optional[str] = None
248
248
  """The command to run to build the app.
249
249
 
250
250
  This command will be executed without a shell, i.e., directly. The command
251
251
  must exit with a status of 0 to continue the push process of the app to
252
252
  Nextmv Cloud. This command is executed prior to the pre-push command.
253
253
  """
254
- environment: dict[str, Any] | None = None
254
+ environment: Optional[dict[str, Any]] = None
255
255
  """Environment variables to set when running the build command.
256
256
 
257
257
  Given as key-value pairs.
@@ -317,7 +317,7 @@ class ManifestPythonModel(BaseModel):
317
317
 
318
318
  name: str
319
319
  """The name of the decision model."""
320
- options: list[dict[str, Any]] | None = None
320
+ options: Optional[list[dict[str, Any]]] = None
321
321
  """
322
322
  Options for the decision model. This is a data representation of the
323
323
  `nextmv.Options` class. It consists of a list of dicts. Each dict
@@ -359,7 +359,7 @@ class ManifestPython(BaseModel):
359
359
  'requirements.txt'
360
360
  """
361
361
 
362
- pip_requirements: str | list[str] | None = Field(
362
+ pip_requirements: Optional[Union[str, list[str]]] = Field(
363
363
  serialization_alias="pip-requirements",
364
364
  validation_alias=AliasChoices("pip-requirements", "pip_requirements"),
365
365
  default=None,
@@ -371,16 +371,16 @@ class ManifestPython(BaseModel):
371
371
  app. Can be either a string path to a requirements.txt file or a list
372
372
  of package specifications.
373
373
  """
374
- arch: ManifestPythonArch | None = None
374
+ arch: Optional[ManifestPythonArch] = None
375
375
  """
376
376
  The architecture this model is meant to run on. One of "arm64" or "amd64". Uses
377
377
  "arm64" if not specified.
378
378
  """
379
- version: str | float | None = None
379
+ version: Optional[Union[str, float]] = None
380
380
  """
381
381
  The Python version this model is meant to run with. Uses "3.11" if not specified.
382
382
  """
383
- model: ManifestPythonModel | None = None
383
+ model: Optional[ManifestPythonModel] = None
384
384
  """
385
385
  Information about an encoded decision model.
386
386
 
@@ -390,7 +390,7 @@ class ManifestPython(BaseModel):
390
390
 
391
391
  @field_validator("version", mode="before")
392
392
  @classmethod
393
- def validate_version(cls, v: str | float | None) -> str | None:
393
+ def validate_version(cls, v: Optional[Union[str, float]]) -> Optional[str]:
394
394
  """
395
395
  Validate and convert the Python version field to a string.
396
396
 
@@ -461,11 +461,11 @@ class ManifestOptionUI(BaseModel):
461
461
  'input'
462
462
  """
463
463
 
464
- control_type: str | None = None
464
+ control_type: Optional[str] = None
465
465
  """The type of control to use for the option in the Nextmv Cloud UI."""
466
- hidden_from: list[str] | None = None
466
+ hidden_from: Optional[list[str]] = None
467
467
  """A list of team roles for which this option will be hidden in the UI."""
468
- display_name: str | None = None
468
+ display_name: Optional[str] = None
469
469
  """An optional display name for the option. This is useful for making
470
470
  the option more user-friendly in the UI.
471
471
  """
@@ -529,15 +529,15 @@ class ManifestOption(BaseModel):
529
529
  )
530
530
  """The type of the option (e.g., "string", "int", "bool", "float)."""
531
531
 
532
- default: Any | None = None
532
+ default: Optional[Any] = None
533
533
  """The default value of the option"""
534
- description: str | None = ""
534
+ description: Optional[str] = ""
535
535
  """The description of the option"""
536
536
  required: bool = False
537
537
  """Whether the option is required or not"""
538
- additional_attributes: dict[str, Any] | None = None
538
+ additional_attributes: Optional[dict[str, Any]] = None
539
539
  """Optional additional attributes for the option."""
540
- ui: ManifestOptionUI | None = None
540
+ ui: Optional[ManifestOptionUI] = None
541
541
  """Optional UI attributes for the option."""
542
542
 
543
543
  @classmethod
@@ -727,16 +727,16 @@ class ManifestOptions(BaseModel):
727
727
  2
728
728
  """
729
729
 
730
- strict: bool | None = False
730
+ strict: Optional[bool] = False
731
731
  """If strict is set to `True`, only the listed options will be allowed."""
732
- validation: ManifestValidation | None = None
732
+ validation: Optional[ManifestValidation] = None
733
733
  """Optional validation rules for all options."""
734
- items: list[ManifestOption] | None = None
734
+ items: Optional[list[ManifestOption]] = None
735
735
  """The actual list of options for the decision model.
736
736
 
737
737
  An option is a parameter that configures the decision model.
738
738
  """
739
- format: list[str] | None = None
739
+ format: Optional[list[str]] = None
740
740
  """A list of strings that define how options are transformed into command line arguments.
741
741
 
742
742
  Use `{{name}}` to refer to the option name and `{{value}}` to refer to the option value.
@@ -749,7 +749,7 @@ class ManifestOptions(BaseModel):
749
749
  cls,
750
750
  options: Options,
751
751
  validation: OptionsEnforcement = None,
752
- format: list[str] | None = None,
752
+ format: Optional[list[str]] = None,
753
753
  ) -> "ManifestOptions":
754
754
  """
755
755
  Create a `ManifestOptions` from a `nextmv.Options`.
@@ -853,11 +853,11 @@ class ManifestContentMultiFileOutput(BaseModel):
853
853
  'my-outputs/statistics.json'
854
854
  """
855
855
 
856
- statistics: str | None = ""
856
+ statistics: Optional[str] = ""
857
857
  """The path to the statistics file."""
858
- assets: str | None = ""
858
+ assets: Optional[str] = ""
859
859
  """The path to the assets file."""
860
- solutions: str | None = ""
860
+ solutions: Optional[str] = ""
861
861
  """The path to the solutions directory."""
862
862
 
863
863
 
@@ -942,7 +942,7 @@ class ManifestContent(BaseModel):
942
942
  The format of the content. Can only be `InputFormat.JSON`,
943
943
  `InputFormat.MULTI_FILE`, or `InputFormat.CSV_ARCHIVE`.
944
944
  """
945
- multi_file: ManifestContentMultiFile | None = Field(
945
+ multi_file: Optional[ManifestContentMultiFile] = Field(
946
946
  serialization_alias="multi-file",
947
947
  validation_alias=AliasChoices("multi-file", "multi_file"),
948
948
  default=None,
@@ -1001,46 +1001,12 @@ class ManifestConfiguration(BaseModel):
1001
1001
  'debug_mode'
1002
1002
  """
1003
1003
 
1004
- options: ManifestOptions | None = None
1004
+ options: Optional[ManifestOptions] = None
1005
1005
  """Options for the decision model."""
1006
- content: ManifestContent | None = None
1006
+ content: Optional[ManifestContent] = None
1007
1007
  """Content configuration for specifying how the app input/output is handled."""
1008
1008
 
1009
1009
 
1010
- class ManifestExecution(BaseModel):
1011
- """
1012
- Execution configuration for the decision model.
1013
-
1014
- You can import the `ManifestExecution` class directly from `nextmv`:
1015
-
1016
- ```python
1017
- from nextmv import ManifestExecution
1018
- ```
1019
-
1020
- Parameters
1021
- ----------
1022
- entrypoint : Optional[str], default=None
1023
- The entrypoint for the decision model, e.g.: `./app.py`.
1024
- cwd : Optional[str], default=None
1025
- The working directory to set when running the app, e.g.: `./src/`.
1026
-
1027
- Examples
1028
- --------
1029
- >>> from nextmv import ManifestExecution
1030
- >>> exec_config = ManifestExecution(
1031
- ... entrypoint="./app.py",
1032
- ... cwd="./src/"
1033
- ... )
1034
- >>> exec_config.entrypoint
1035
- './app.py'
1036
- """
1037
-
1038
- entrypoint: str | None = None
1039
- """The entrypoint for the decision model, e.g.: `./app.py`."""
1040
- cwd: str | None = None
1041
- """The working directory to set when running the app, e.g.: `./src/`."""
1042
-
1043
-
1044
1010
  class Manifest(BaseModel):
1045
1011
  """
1046
1012
  Represents an app manifest (`app.yaml`) for Nextmv Cloud.
@@ -1118,7 +1084,7 @@ class Manifest(BaseModel):
1118
1084
  The runtime to use for the app. It provides the environment in which the
1119
1085
  app runs. This is mandatory.
1120
1086
  """
1121
- python: ManifestPython | None = None
1087
+ python: Optional[ManifestPython] = None
1122
1088
  """
1123
1089
  Python-specific attributes. Only for Python apps. Contains further
1124
1090
  Python-specific attributes.
@@ -1127,12 +1093,12 @@ class Manifest(BaseModel):
1127
1093
  default_factory=list,
1128
1094
  )
1129
1095
  """The files to include (or exclude) in the app. This is mandatory."""
1130
- configuration: ManifestConfiguration | None = None
1096
+ configuration: Optional[ManifestConfiguration] = None
1131
1097
  """
1132
1098
  Configuration for the decision model. A list of options for the decision
1133
1099
  model. An option is a parameter that configures the decision model.
1134
1100
  """
1135
- build: ManifestBuild | None = None
1101
+ build: Optional[ManifestBuild] = None
1136
1102
  """
1137
1103
  Build-specific attributes.
1138
1104
 
@@ -1143,7 +1109,7 @@ class Manifest(BaseModel):
1143
1109
  set environment variables when running the build command given as key-value
1144
1110
  pairs.
1145
1111
  """
1146
- pre_push: str | None = Field(
1112
+ pre_push: Optional[str] = Field(
1147
1113
  serialization_alias="pre-push",
1148
1114
  validation_alias=AliasChoices("pre-push", "pre_push"),
1149
1115
  default=None,
@@ -1158,12 +1124,55 @@ class Manifest(BaseModel):
1158
1124
  process. This command is executed just before the app gets bundled and
1159
1125
  pushed (after the build command).
1160
1126
  """
1161
- execution: ManifestExecution | None = None
1127
+ entrypoint: Optional[str] = None
1162
1128
  """
1163
- Optional execution configuration for the decision model. Allows configuration of
1164
- entrypoint and more.
1129
+ Optional entrypoint for the decision model. When not specified, the
1130
+ following default entrypoints are used, according to the `.runtime`:
1131
+
1132
+ - `ManifestRuntime.PYTHON`, `ManifestRuntime.HEXALY`, `ManifestRuntime.PYOMO`: `./main.py`
1133
+ - `ManifestRuntime.DEFAULT`: `./main`
1134
+ - Java: `./main.jar`
1165
1135
  """
1166
1136
 
1137
+ def model_post_init(self, __context) -> None:
1138
+ """
1139
+ Post-initialization to set default entrypoint based on runtime if not specified.
1140
+
1141
+ This method is automatically called by Pydantic after the model is initialized.
1142
+ If no entrypoint is provided, it sets a default entrypoint based on the runtime:
1143
+ - Python runtimes (PYTHON, HEXALY, PYOMO, CUOPT): "./main.py"
1144
+ - DEFAULT runtime: "./main"
1145
+ - JAVA runtime: "./main.jar"
1146
+
1147
+ Parameters
1148
+ ----------
1149
+ __context : Any
1150
+ Pydantic context (unused in this implementation).
1151
+
1152
+ Raises
1153
+ ------
1154
+ ValueError
1155
+ If no entrypoint is provided and the runtime cannot be resolved to
1156
+ establish a default entrypoint.
1157
+ """
1158
+ if self.entrypoint is None:
1159
+ if self.runtime in (
1160
+ ManifestRuntime.PYTHON,
1161
+ ManifestRuntime.HEXALY,
1162
+ ManifestRuntime.PYOMO,
1163
+ ManifestRuntime.CUOPT,
1164
+ ):
1165
+ self.entrypoint = "./main.py"
1166
+ elif self.runtime == ManifestRuntime.DEFAULT:
1167
+ self.entrypoint = "./main"
1168
+ elif self.runtime == ManifestRuntime.JAVA:
1169
+ self.entrypoint = "./main.jar"
1170
+ else:
1171
+ raise ValueError(
1172
+ f'entrypoint is not provided but the runtime "{self.runtime}" could not '
1173
+ "be resolved to establish a default entrypoint"
1174
+ )
1175
+
1167
1176
  @classmethod
1168
1177
  def from_yaml(cls, dirpath: str) -> "Manifest":
1169
1178
  """
@@ -1247,7 +1256,7 @@ class Manifest(BaseModel):
1247
1256
  width=120,
1248
1257
  )
1249
1258
 
1250
- def extract_options(self, should_parse: bool = True) -> Options | None:
1259
+ def extract_options(self, should_parse: bool = True) -> Optional[Options]:
1251
1260
  """
1252
1261
  Convert the manifest options to a `nextmv.Options` object.
1253
1262
 
@@ -1468,5 +1477,6 @@ def default_python_manifest() -> Manifest:
1468
1477
  type=ManifestType.PYTHON,
1469
1478
  python=ManifestPython(pip_requirements="requirements.txt"),
1470
1479
  )
1480
+ m.entrypoint = None # TODO: change this when we are ready for the entrypoint.
1471
1481
 
1472
1482
  return m
nextmv/model.py CHANGED
@@ -20,7 +20,7 @@ import os
20
20
  import shutil
21
21
  import warnings
22
22
  from dataclasses import dataclass
23
- from typing import Any
23
+ from typing import Any, Optional
24
24
 
25
25
  from nextmv.input import Input
26
26
  from nextmv.logger import log
@@ -152,11 +152,11 @@ class ModelConfiguration:
152
152
 
153
153
  name: str
154
154
  """The name of the decision model."""
155
- requirements: list[str] | None = None
155
+ requirements: Optional[list[str]] = None
156
156
  """A list of Python dependencies that the decision model requires."""
157
- options: Options | None = None
157
+ options: Optional[Options] = None
158
158
  """Options that the decision model requires."""
159
- options_enforcement: OptionsEnforcement | None = None
159
+ options_enforcement: Optional[OptionsEnforcement] = None
160
160
  """Enforcement of options for the model."""
161
161
 
162
162
 
@@ -308,7 +308,7 @@ class Model:
308
308
  self,
309
309
  context,
310
310
  model_input,
311
- params: dict[str, Any] | None = None,
311
+ params: Optional[dict[str, Any]] = None,
312
312
  ) -> Any:
313
313
  """
314
314
  MLflow-compliant prediction method that calls the Nextmv model's solve method.
@@ -376,7 +376,7 @@ class Model:
376
376
 
377
377
  def _cleanup_python_model(
378
378
  model_dir: str,
379
- model_configuration: ModelConfiguration | None = None,
379
+ model_configuration: Optional[ModelConfiguration] = None,
380
380
  verbose: bool = False,
381
381
  ) -> None:
382
382
  """
nextmv/options.py CHANGED
@@ -21,7 +21,7 @@ import copy
21
21
  import json
22
22
  import os
23
23
  from dataclasses import dataclass
24
- from typing import Any
24
+ from typing import Any, Optional, Union
25
25
 
26
26
  from nextmv.base_model import BaseModel
27
27
  from nextmv.deprecated import deprecated
@@ -74,17 +74,17 @@ class Parameter:
74
74
  param_type: type
75
75
  """The type of the parameter."""
76
76
 
77
- default: Any | None = None
77
+ default: Optional[Any] = None
78
78
  """The default value of the parameter. Even though this is optional, it is
79
79
  recommended to provide a default value for all parameters."""
80
- description: str | None = None
80
+ description: Optional[str] = None
81
81
  """An optional description of the parameter. This is useful for generating
82
82
  help messages for the configuration."""
83
83
  required: bool = False
84
84
  """Whether the parameter is required. If a parameter is required, it will
85
85
  be an error to not provide a value for it, either trough a command-line
86
86
  argument, an environment variable or a default value."""
87
- choices: list[Any | None] = None
87
+ choices: list[Optional[Any]] = None
88
88
  """Limits values to a specific set of choices."""
89
89
 
90
90
  def __post_init__(self):
@@ -246,12 +246,12 @@ class Option:
246
246
  option_type: type
247
247
  """The type of the option."""
248
248
 
249
- default: Any | None = None
249
+ default: Optional[Any] = None
250
250
  """
251
251
  The default value of the option. Even though this is optional, it is
252
252
  recommended to provide a default value for all options.
253
253
  """
254
- description: str | None = None
254
+ description: Optional[str] = None
255
255
  """
256
256
  An optional description of the option. This is useful for generating help
257
257
  messages for the `Options`.
@@ -262,16 +262,16 @@ class Option:
262
262
  error to not provide a value for it, either trough a command-line argument,
263
263
  an environment variable or a default value.
264
264
  """
265
- choices: list[Any] | None = None
265
+ choices: Optional[list[Any]] = None
266
266
  """Limits values to a specific set of choices."""
267
- additional_attributes: dict[str, Any] | None = None
267
+ additional_attributes: Optional[dict[str, Any]] = None
268
268
  """
269
269
  Optional additional attributes for the option. The Nextmv Cloud may
270
270
  perform validation on these attributes. For example, the maximum length of
271
271
  a string or the maximum value of an integer. These additional attributes
272
272
  will be shown in the help message of the `Options`.
273
273
  """
274
- control_type: str | None = None
274
+ control_type: Optional[str] = None
275
275
  """
276
276
  The type of control to use for the option in the Nextmv Cloud UI. This is
277
277
  useful for defining how the option should be presented in the Nextmv
@@ -281,13 +281,13 @@ class Option:
281
281
  the option. This will be validated by the Nextmv Cloud, and availability
282
282
  is based on options_type.
283
283
  """
284
- hidden_from: list[str] | None = None
284
+ hidden_from: Optional[list[str]] = None
285
285
  """
286
286
  A list of team roles for which this option will be hidden in the UI. For
287
287
  example, if you want to hide an option from the "operator" role, you can
288
288
  pass `hidden_from=["operator"]`.
289
289
  """
290
- display_name: str | None = None
290
+ display_name: Optional[str] = None
291
291
  """
292
292
  An optional display name for the option. This is useful for making
293
293
  the option more user-friendly in the UI.
@@ -1032,7 +1032,7 @@ class Options:
1032
1032
  return False
1033
1033
 
1034
1034
  @staticmethod
1035
- def _option_type(option: Option | Parameter) -> type:
1035
+ def _option_type(option: Union[Option, Parameter]) -> type:
1036
1036
  """
1037
1037
  Get the type of an option.
1038
1038