nextmv 0.39.0.dev1__py3-none-any.whl → 1.0.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.
- nextmv/__about__.py +1 -1
- nextmv/__entrypoint__.py +1 -2
- nextmv/__init__.py +2 -4
- nextmv/cli/CONTRIBUTING.md +583 -0
- nextmv/cli/cloud/__init__.py +49 -0
- nextmv/cli/cloud/acceptance/__init__.py +27 -0
- nextmv/cli/cloud/acceptance/create.py +391 -0
- nextmv/cli/cloud/acceptance/delete.py +64 -0
- nextmv/cli/cloud/acceptance/get.py +103 -0
- nextmv/cli/cloud/acceptance/list.py +62 -0
- nextmv/cli/cloud/acceptance/update.py +95 -0
- nextmv/cli/cloud/account/__init__.py +28 -0
- nextmv/cli/cloud/account/create.py +83 -0
- nextmv/cli/cloud/account/delete.py +59 -0
- nextmv/cli/cloud/account/get.py +66 -0
- nextmv/cli/cloud/account/update.py +70 -0
- nextmv/cli/cloud/app/__init__.py +35 -0
- nextmv/cli/cloud/app/create.py +140 -0
- nextmv/cli/cloud/app/delete.py +57 -0
- nextmv/cli/cloud/app/exists.py +44 -0
- nextmv/cli/cloud/app/get.py +66 -0
- nextmv/cli/cloud/app/list.py +61 -0
- nextmv/cli/cloud/app/push.py +432 -0
- nextmv/cli/cloud/app/update.py +124 -0
- nextmv/cli/cloud/batch/__init__.py +29 -0
- nextmv/cli/cloud/batch/create.py +452 -0
- nextmv/cli/cloud/batch/delete.py +64 -0
- nextmv/cli/cloud/batch/get.py +104 -0
- nextmv/cli/cloud/batch/list.py +63 -0
- nextmv/cli/cloud/batch/metadata.py +66 -0
- nextmv/cli/cloud/batch/update.py +95 -0
- nextmv/cli/cloud/data/__init__.py +26 -0
- nextmv/cli/cloud/data/upload.py +162 -0
- nextmv/cli/cloud/ensemble/__init__.py +33 -0
- nextmv/cli/cloud/ensemble/create.py +413 -0
- nextmv/cli/cloud/ensemble/delete.py +63 -0
- nextmv/cli/cloud/ensemble/get.py +65 -0
- nextmv/cli/cloud/ensemble/list.py +63 -0
- nextmv/cli/cloud/ensemble/update.py +103 -0
- nextmv/cli/cloud/input_set/__init__.py +32 -0
- nextmv/cli/cloud/input_set/create.py +168 -0
- nextmv/cli/cloud/input_set/delete.py +64 -0
- nextmv/cli/cloud/input_set/get.py +63 -0
- nextmv/cli/cloud/input_set/list.py +63 -0
- nextmv/cli/cloud/input_set/update.py +123 -0
- nextmv/cli/cloud/instance/__init__.py +35 -0
- nextmv/cli/cloud/instance/create.py +289 -0
- nextmv/cli/cloud/instance/delete.py +61 -0
- nextmv/cli/cloud/instance/exists.py +39 -0
- nextmv/cli/cloud/instance/get.py +62 -0
- nextmv/cli/cloud/instance/list.py +60 -0
- nextmv/cli/cloud/instance/update.py +216 -0
- nextmv/cli/cloud/managed_input/__init__.py +31 -0
- nextmv/cli/cloud/managed_input/create.py +144 -0
- nextmv/cli/cloud/managed_input/delete.py +64 -0
- nextmv/cli/cloud/managed_input/get.py +63 -0
- nextmv/cli/cloud/managed_input/list.py +60 -0
- nextmv/cli/cloud/managed_input/update.py +97 -0
- nextmv/cli/cloud/run/__init__.py +37 -0
- nextmv/cli/cloud/run/cancel.py +37 -0
- nextmv/cli/cloud/run/create.py +524 -0
- nextmv/cli/cloud/run/get.py +199 -0
- nextmv/cli/cloud/run/input.py +86 -0
- nextmv/cli/cloud/run/list.py +80 -0
- nextmv/cli/cloud/run/logs.py +166 -0
- nextmv/cli/cloud/run/metadata.py +67 -0
- nextmv/cli/cloud/run/track.py +500 -0
- nextmv/cli/cloud/scenario/__init__.py +29 -0
- nextmv/cli/cloud/scenario/create.py +451 -0
- nextmv/cli/cloud/scenario/delete.py +61 -0
- nextmv/cli/cloud/scenario/get.py +102 -0
- nextmv/cli/cloud/scenario/list.py +63 -0
- nextmv/cli/cloud/scenario/metadata.py +67 -0
- nextmv/cli/cloud/scenario/update.py +93 -0
- nextmv/cli/cloud/secrets/__init__.py +33 -0
- nextmv/cli/cloud/secrets/create.py +206 -0
- nextmv/cli/cloud/secrets/delete.py +63 -0
- nextmv/cli/cloud/secrets/get.py +66 -0
- nextmv/cli/cloud/secrets/list.py +60 -0
- nextmv/cli/cloud/secrets/update.py +144 -0
- nextmv/cli/cloud/shadow/__init__.py +33 -0
- nextmv/cli/cloud/shadow/create.py +184 -0
- nextmv/cli/cloud/shadow/delete.py +64 -0
- nextmv/cli/cloud/shadow/get.py +61 -0
- nextmv/cli/cloud/shadow/list.py +63 -0
- nextmv/cli/cloud/shadow/metadata.py +66 -0
- nextmv/cli/cloud/shadow/start.py +43 -0
- nextmv/cli/cloud/shadow/stop.py +53 -0
- nextmv/cli/cloud/shadow/update.py +96 -0
- nextmv/cli/cloud/switchback/__init__.py +33 -0
- nextmv/cli/cloud/switchback/create.py +151 -0
- nextmv/cli/cloud/switchback/delete.py +64 -0
- nextmv/cli/cloud/switchback/get.py +62 -0
- nextmv/cli/cloud/switchback/list.py +63 -0
- nextmv/cli/cloud/switchback/metadata.py +68 -0
- nextmv/cli/cloud/switchback/start.py +43 -0
- nextmv/cli/cloud/switchback/stop.py +53 -0
- nextmv/cli/cloud/switchback/update.py +96 -0
- nextmv/cli/cloud/upload/__init__.py +22 -0
- nextmv/cli/cloud/upload/create.py +39 -0
- nextmv/cli/cloud/version/__init__.py +33 -0
- nextmv/cli/cloud/version/create.py +96 -0
- nextmv/cli/cloud/version/delete.py +61 -0
- nextmv/cli/cloud/version/exists.py +39 -0
- nextmv/cli/cloud/version/get.py +62 -0
- nextmv/cli/cloud/version/list.py +60 -0
- nextmv/cli/cloud/version/update.py +92 -0
- nextmv/cli/community/__init__.py +24 -0
- nextmv/cli/community/clone.py +86 -0
- nextmv/cli/community/list.py +200 -0
- nextmv/cli/configuration/__init__.py +23 -0
- nextmv/cli/configuration/config.py +228 -0
- nextmv/cli/configuration/create.py +94 -0
- nextmv/cli/configuration/delete.py +67 -0
- nextmv/cli/configuration/list.py +77 -0
- nextmv/cli/confirm.py +34 -0
- nextmv/cli/main.py +161 -3
- nextmv/cli/message.py +170 -0
- nextmv/cli/options.py +220 -0
- nextmv/cli/version.py +22 -2
- nextmv/cloud/__init__.py +17 -38
- nextmv/cloud/acceptance_test.py +20 -83
- nextmv/cloud/account.py +269 -30
- nextmv/cloud/application/__init__.py +898 -0
- nextmv/cloud/application/_acceptance.py +424 -0
- nextmv/cloud/application/_batch_scenario.py +845 -0
- nextmv/cloud/application/_ensemble.py +251 -0
- nextmv/cloud/application/_input_set.py +263 -0
- nextmv/cloud/application/_instance.py +289 -0
- nextmv/cloud/application/_managed_input.py +227 -0
- nextmv/cloud/application/_run.py +1393 -0
- nextmv/cloud/application/_secrets.py +294 -0
- nextmv/cloud/application/_shadow.py +320 -0
- nextmv/cloud/application/_switchback.py +332 -0
- nextmv/cloud/application/_utils.py +54 -0
- nextmv/cloud/application/_version.py +304 -0
- nextmv/cloud/batch_experiment.py +6 -2
- nextmv/cloud/community.py +446 -0
- nextmv/cloud/instance.py +11 -1
- nextmv/cloud/integration.py +8 -5
- nextmv/cloud/package.py +50 -9
- nextmv/cloud/shadow.py +254 -0
- nextmv/cloud/switchback.py +228 -0
- nextmv/deprecated.py +5 -3
- nextmv/input.py +20 -88
- nextmv/local/application.py +3 -15
- nextmv/local/runner.py +1 -1
- nextmv/model.py +50 -11
- nextmv/options.py +11 -256
- nextmv/output.py +0 -62
- nextmv/polling.py +54 -16
- nextmv/run.py +84 -37
- nextmv/status.py +1 -51
- {nextmv-0.39.0.dev1.dist-info → nextmv-1.0.0.dist-info}/METADATA +37 -11
- nextmv-1.0.0.dist-info/RECORD +185 -0
- nextmv-1.0.0.dist-info/entry_points.txt +2 -0
- nextmv/cloud/application.py +0 -4204
- nextmv-0.39.0.dev1.dist-info/RECORD +0 -55
- nextmv-0.39.0.dev1.dist-info/entry_points.txt +0 -2
- {nextmv-0.39.0.dev1.dist-info → nextmv-1.0.0.dist-info}/WHEEL +0 -0
- {nextmv-0.39.0.dev1.dist-info → nextmv-1.0.0.dist-info}/licenses/LICENSE +0 -0
nextmv/options.py
CHANGED
|
@@ -24,155 +24,6 @@ from dataclasses import dataclass
|
|
|
24
24
|
from typing import Any
|
|
25
25
|
|
|
26
26
|
from nextmv.base_model import BaseModel
|
|
27
|
-
from nextmv.deprecated import deprecated
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@dataclass
|
|
31
|
-
class Parameter:
|
|
32
|
-
"""
|
|
33
|
-
!!! warning
|
|
34
|
-
`Parameter` is deprecated, use `Option` instead.
|
|
35
|
-
|
|
36
|
-
Parameter that is used in a `Configuration`. When a parameter is required,
|
|
37
|
-
it is a good practice to provide a default value for it. This is because
|
|
38
|
-
the configuration will raise an error if a required parameter is not
|
|
39
|
-
provided through a command-line argument, an environment variable or a
|
|
40
|
-
default value.
|
|
41
|
-
|
|
42
|
-
Parameters
|
|
43
|
-
----------
|
|
44
|
-
name : str
|
|
45
|
-
The name of the parameter.
|
|
46
|
-
|
|
47
|
-
param_type : type
|
|
48
|
-
The type of the parameter.
|
|
49
|
-
|
|
50
|
-
default : Any, optional
|
|
51
|
-
The default value of the parameter. Even though this is optional, it is
|
|
52
|
-
recommended to provide a default value for all parameters.
|
|
53
|
-
|
|
54
|
-
description : str, optional
|
|
55
|
-
An optional description of the parameter. This is useful for generating
|
|
56
|
-
help messages for the configuration.
|
|
57
|
-
|
|
58
|
-
required : bool, optional
|
|
59
|
-
Whether the parameter is required. If a parameter is required, it will
|
|
60
|
-
be an error to not provide a value for it, either through a command-line
|
|
61
|
-
argument, an environment variable or a default value.
|
|
62
|
-
|
|
63
|
-
choices : list[Optional[Any]], optional
|
|
64
|
-
Limits values to a specific set of choices.
|
|
65
|
-
|
|
66
|
-
Examples
|
|
67
|
-
--------
|
|
68
|
-
>>> from nextmv.options import Parameter
|
|
69
|
-
>>> parameter = Parameter("timeout", int, 60, "The maximum timeout in seconds", required=True)
|
|
70
|
-
"""
|
|
71
|
-
|
|
72
|
-
name: str
|
|
73
|
-
"""The name of the parameter."""
|
|
74
|
-
param_type: type
|
|
75
|
-
"""The type of the parameter."""
|
|
76
|
-
|
|
77
|
-
default: Any | None = None
|
|
78
|
-
"""The default value of the parameter. Even though this is optional, it is
|
|
79
|
-
recommended to provide a default value for all parameters."""
|
|
80
|
-
description: str | None = None
|
|
81
|
-
"""An optional description of the parameter. This is useful for generating
|
|
82
|
-
help messages for the configuration."""
|
|
83
|
-
required: bool = False
|
|
84
|
-
"""Whether the parameter is required. If a parameter is required, it will
|
|
85
|
-
be an error to not provide a value for it, either trough a command-line
|
|
86
|
-
argument, an environment variable or a default value."""
|
|
87
|
-
choices: list[Any | None] = None
|
|
88
|
-
"""Limits values to a specific set of choices."""
|
|
89
|
-
|
|
90
|
-
def __post_init__(self):
|
|
91
|
-
"""
|
|
92
|
-
Post-initialization hook that marks this class as deprecated.
|
|
93
|
-
|
|
94
|
-
This method is automatically called after the object is initialized.
|
|
95
|
-
It displays a deprecation warning to inform users to use the `Option` class instead.
|
|
96
|
-
"""
|
|
97
|
-
deprecated(
|
|
98
|
-
name="Parameter",
|
|
99
|
-
reason="`Parameter` is deprecated, use `Option` instead",
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
@classmethod
|
|
103
|
-
def from_dict(cls, data: dict[str, Any]) -> "Parameter":
|
|
104
|
-
"""
|
|
105
|
-
!!! warning
|
|
106
|
-
`Parameter` is deprecated, use `Option` instead.
|
|
107
|
-
`Parameter.from_dict` -> `Option.from_dict`
|
|
108
|
-
|
|
109
|
-
Creates an instance of `Parameter` from a dictionary.
|
|
110
|
-
|
|
111
|
-
Parameters
|
|
112
|
-
----------
|
|
113
|
-
data : dict[str, Any]
|
|
114
|
-
The dictionary representation of a parameter.
|
|
115
|
-
|
|
116
|
-
Returns
|
|
117
|
-
-------
|
|
118
|
-
Parameter
|
|
119
|
-
An instance of `Parameter`.
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
deprecated(
|
|
123
|
-
name="Parameter.from_dict",
|
|
124
|
-
reason="`Parameter` is deprecated, use `Option` instead. Parameter.from_dict -> Option.from_dict",
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
param_type_string = data["param_type"]
|
|
128
|
-
param_type = getattr(builtins, param_type_string.split("'")[1])
|
|
129
|
-
|
|
130
|
-
return Parameter(
|
|
131
|
-
name=data["name"],
|
|
132
|
-
param_type=param_type,
|
|
133
|
-
default=data.get("default"),
|
|
134
|
-
description=data.get("description"),
|
|
135
|
-
required=data.get("required", False),
|
|
136
|
-
choices=data.get("choices"),
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
def to_dict(self) -> dict[str, Any]:
|
|
140
|
-
"""
|
|
141
|
-
!!! warning
|
|
142
|
-
`Parameter` is deprecated, use `Option` instead.
|
|
143
|
-
`Parameter.to_dict` -> `Option.to_dict`
|
|
144
|
-
|
|
145
|
-
Converts the parameter to a dict.
|
|
146
|
-
|
|
147
|
-
Returns
|
|
148
|
-
-------
|
|
149
|
-
dict[str, Any]
|
|
150
|
-
The parameter as a dict with its name, type, default value,
|
|
151
|
-
description, required flag, and choices.
|
|
152
|
-
|
|
153
|
-
Examples
|
|
154
|
-
--------
|
|
155
|
-
>>> param = Parameter("timeout", int, 60, "Maximum time in seconds", True)
|
|
156
|
-
>>> param_dict = param.to_dict()
|
|
157
|
-
>>> param_dict["name"]
|
|
158
|
-
'timeout'
|
|
159
|
-
>>> param_dict["default"]
|
|
160
|
-
60
|
|
161
|
-
"""
|
|
162
|
-
|
|
163
|
-
deprecated(
|
|
164
|
-
name="Parameter.to_dict",
|
|
165
|
-
reason="`Parameter` is deprecated, use `Option` instead. Parameter.to_dict -> Option.to_dict",
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
"name": self.name,
|
|
170
|
-
"param_type": str(self.param_type),
|
|
171
|
-
"default": self.default,
|
|
172
|
-
"description": self.description,
|
|
173
|
-
"required": self.required,
|
|
174
|
-
"choices": self.choices,
|
|
175
|
-
}
|
|
176
27
|
|
|
177
28
|
|
|
178
29
|
@dataclass
|
|
@@ -425,8 +276,7 @@ class Options:
|
|
|
425
276
|
If a required option is not provided through a command-line
|
|
426
277
|
argument, an environment variable or a default value.
|
|
427
278
|
TypeError
|
|
428
|
-
If an option is not
|
|
429
|
-
object.
|
|
279
|
+
If an option is not an `Option`
|
|
430
280
|
ValueError
|
|
431
281
|
If an environment variable is not of the type of the corresponding
|
|
432
282
|
parameter.
|
|
@@ -522,27 +372,6 @@ class Options:
|
|
|
522
372
|
|
|
523
373
|
return cloud_dict
|
|
524
374
|
|
|
525
|
-
def parameters_dict(self) -> list[dict[str, Any]]:
|
|
526
|
-
"""
|
|
527
|
-
!!! warning
|
|
528
|
-
`Parameter` is deprecated, use `Option` instead. `Options.parameters_dict` -> `Options.options_dict`
|
|
529
|
-
|
|
530
|
-
Converts the options to a list of dicts. Each dict is the dict
|
|
531
|
-
representation of a `Parameter`.
|
|
532
|
-
|
|
533
|
-
Returns
|
|
534
|
-
-------
|
|
535
|
-
list[dict[str, Any]]
|
|
536
|
-
The list of dictionaries (parameter entries).
|
|
537
|
-
"""
|
|
538
|
-
|
|
539
|
-
deprecated(
|
|
540
|
-
name="Options.parameters_dict",
|
|
541
|
-
reason="`Parameter` is deprecated, use `Option` instead. Options.parameters_dict -> Options.options_dict",
|
|
542
|
-
)
|
|
543
|
-
|
|
544
|
-
return [param.to_dict() for param in self.options]
|
|
545
|
-
|
|
546
375
|
def options_dict(self) -> list[dict[str, Any]]:
|
|
547
376
|
"""
|
|
548
377
|
Converts the `Options` to a list of dicts. Each dict is the dict
|
|
@@ -606,7 +435,7 @@ class Options:
|
|
|
606
435
|
If a required option is not provided through a command-line
|
|
607
436
|
argument, an environment variable or a default value.
|
|
608
437
|
TypeError
|
|
609
|
-
If an option is not an `Option`
|
|
438
|
+
If an option is not an `Option` object.
|
|
610
439
|
ValueError
|
|
611
440
|
If an environment variable is not of the type of the corresponding
|
|
612
441
|
parameter.
|
|
@@ -728,41 +557,6 @@ class Options:
|
|
|
728
557
|
|
|
729
558
|
return cls(*options)
|
|
730
559
|
|
|
731
|
-
@classmethod
|
|
732
|
-
def from_parameters_dict(cls, parameters_dict: list[dict[str, Any]]) -> "Options":
|
|
733
|
-
"""
|
|
734
|
-
!!! warning
|
|
735
|
-
|
|
736
|
-
`Parameter` is deprecated, use `Option` instead.
|
|
737
|
-
`Options.from_parameters_dict` -> `Options.from_options_dict`
|
|
738
|
-
|
|
739
|
-
Creates an instance of `Options` from parameters in dict form. Each
|
|
740
|
-
entry is the dict representation of a `Parameter`.
|
|
741
|
-
|
|
742
|
-
Parameters
|
|
743
|
-
----------
|
|
744
|
-
parameters_dict : list[dict[str, Any]]
|
|
745
|
-
The list of dictionaries (parameter entries).
|
|
746
|
-
|
|
747
|
-
Returns
|
|
748
|
-
-------
|
|
749
|
-
Options
|
|
750
|
-
An instance of `Options`.
|
|
751
|
-
"""
|
|
752
|
-
|
|
753
|
-
deprecated(
|
|
754
|
-
name="Options.from_parameters_dict",
|
|
755
|
-
reason="`Parameter` is deprecated, use `Option` instead. "
|
|
756
|
-
"Options.from_parameters_dict -> Options.from_options_dict",
|
|
757
|
-
)
|
|
758
|
-
|
|
759
|
-
parameters = []
|
|
760
|
-
for parameter_dict in parameters_dict:
|
|
761
|
-
parameter = Parameter.from_dict(parameter_dict)
|
|
762
|
-
parameters.append(parameter)
|
|
763
|
-
|
|
764
|
-
return cls(*parameters)
|
|
765
|
-
|
|
766
560
|
@classmethod
|
|
767
561
|
def from_options_dict(cls, options_dict: list[dict[str, Any]]) -> "Options":
|
|
768
562
|
"""
|
|
@@ -837,7 +631,7 @@ class Options:
|
|
|
837
631
|
If a required option is not provided through a command-line
|
|
838
632
|
argument, an environment variable or a default value.
|
|
839
633
|
TypeError
|
|
840
|
-
If an option is not an `Option`
|
|
634
|
+
If an option is not an `Option` object.
|
|
841
635
|
ValueError
|
|
842
636
|
If an environment variable is not of the type of the corresponding
|
|
843
637
|
parameter.
|
|
@@ -858,10 +652,8 @@ class Options:
|
|
|
858
652
|
options_by_field_name: dict[str, Option] = {}
|
|
859
653
|
|
|
860
654
|
for ix, option in enumerate(self.options):
|
|
861
|
-
if not isinstance(option, Option)
|
|
862
|
-
raise TypeError(
|
|
863
|
-
f"expected an <Option> (or deprecated <Parameter>) object, but got {type(option)} in index {ix}"
|
|
864
|
-
)
|
|
655
|
+
if not isinstance(option, Option):
|
|
656
|
+
raise TypeError(f"expected an <Option> object, but got {type(option)} in index {ix}")
|
|
865
657
|
|
|
866
658
|
# See comment below about ipykernel adding a `-f` argument. We
|
|
867
659
|
# restrict options from having the name 'f' or 'fff' for that
|
|
@@ -876,7 +668,7 @@ class Options:
|
|
|
876
668
|
option.name = option.name.lstrip("-")
|
|
877
669
|
|
|
878
670
|
kwargs = {
|
|
879
|
-
"type":
|
|
671
|
+
"type": option.option_type if option.option_type is not bool else str,
|
|
880
672
|
"help": self._description(option),
|
|
881
673
|
}
|
|
882
674
|
|
|
@@ -903,7 +695,7 @@ class Options:
|
|
|
903
695
|
help=argparse.SUPPRESS,
|
|
904
696
|
default="1",
|
|
905
697
|
)
|
|
906
|
-
args = parser.
|
|
698
|
+
args, _ = parser.parse_known_args()
|
|
907
699
|
|
|
908
700
|
for arg in vars(args):
|
|
909
701
|
if arg == "fff" or arg == "f":
|
|
@@ -925,12 +717,10 @@ class Options:
|
|
|
925
717
|
env_value = os.getenv(upper_name)
|
|
926
718
|
if env_value is not None:
|
|
927
719
|
try:
|
|
928
|
-
typed_env_value = (
|
|
929
|
-
self._option_type(option)(env_value) if self._option_type(option) is not bool else env_value
|
|
930
|
-
)
|
|
720
|
+
typed_env_value = option.option_type(env_value) if option.option_type is not bool else env_value
|
|
931
721
|
except ValueError:
|
|
932
722
|
raise ValueError(
|
|
933
|
-
f'environment variable "{upper_name}" is not of type {
|
|
723
|
+
f'environment variable "{upper_name}" is not of type {option.option_type}'
|
|
934
724
|
) from None
|
|
935
725
|
|
|
936
726
|
value = self._option_value(option, typed_env_value)
|
|
@@ -968,8 +758,6 @@ class Options:
|
|
|
968
758
|
"""
|
|
969
759
|
|
|
970
760
|
description = ""
|
|
971
|
-
if isinstance(option, Parameter):
|
|
972
|
-
description = "DEPRECATED (initialized with <Parameter>, use <Option> instead) "
|
|
973
761
|
|
|
974
762
|
description += f"[env var: {option.name.upper()}]"
|
|
975
763
|
|
|
@@ -979,7 +767,7 @@ class Options:
|
|
|
979
767
|
if option.default is not None:
|
|
980
768
|
description += f" (default: {option.default})"
|
|
981
769
|
|
|
982
|
-
description += f" (type: {
|
|
770
|
+
description += f" (type: {option.option_type.__name__})"
|
|
983
771
|
|
|
984
772
|
if isinstance(option, Option) and option.additional_attributes is not None:
|
|
985
773
|
description += f" (additional attributes: {option.additional_attributes})"
|
|
@@ -1020,7 +808,7 @@ class Options:
|
|
|
1020
808
|
other values are converted to False.
|
|
1021
809
|
"""
|
|
1022
810
|
|
|
1023
|
-
opt_type =
|
|
811
|
+
opt_type = option.option_type
|
|
1024
812
|
if opt_type is not bool:
|
|
1025
813
|
return value
|
|
1026
814
|
|
|
@@ -1031,39 +819,6 @@ class Options:
|
|
|
1031
819
|
|
|
1032
820
|
return False
|
|
1033
821
|
|
|
1034
|
-
@staticmethod
|
|
1035
|
-
def _option_type(option: Option | Parameter) -> type:
|
|
1036
|
-
"""
|
|
1037
|
-
Get the type of an option.
|
|
1038
|
-
|
|
1039
|
-
This auxiliary function was introduced for backwards compatibility with
|
|
1040
|
-
the deprecated `Parameter` class. Once `Parameter` is removed, this function
|
|
1041
|
-
can be removed as well. When the function is removed, use the
|
|
1042
|
-
`option.option_type` attribute directly, instead of calling this function.
|
|
1043
|
-
|
|
1044
|
-
Parameters
|
|
1045
|
-
----------
|
|
1046
|
-
option : Union[Option, Parameter]
|
|
1047
|
-
The option to get the type for.
|
|
1048
|
-
|
|
1049
|
-
Returns
|
|
1050
|
-
-------
|
|
1051
|
-
type
|
|
1052
|
-
The type of the option.
|
|
1053
|
-
|
|
1054
|
-
Raises
|
|
1055
|
-
------
|
|
1056
|
-
TypeError
|
|
1057
|
-
If the option is not an `Option` or `Parameter` object.
|
|
1058
|
-
"""
|
|
1059
|
-
|
|
1060
|
-
if isinstance(option, Option):
|
|
1061
|
-
return option.option_type
|
|
1062
|
-
elif isinstance(option, Parameter):
|
|
1063
|
-
return option.param_type
|
|
1064
|
-
else:
|
|
1065
|
-
raise TypeError(f"expected an <Option> (or deprecated <Parameter>) object, but got {type(option)}")
|
|
1066
|
-
|
|
1067
822
|
|
|
1068
823
|
class OptionsEnforcement:
|
|
1069
824
|
"""
|
nextmv/output.py
CHANGED
|
@@ -66,7 +66,6 @@ from pydantic import AliasChoices, Field
|
|
|
66
66
|
|
|
67
67
|
from nextmv._serialization import serialize_json
|
|
68
68
|
from nextmv.base_model import BaseModel
|
|
69
|
-
from nextmv.deprecated import deprecated
|
|
70
69
|
from nextmv.logger import reset_stdout
|
|
71
70
|
from nextmv.options import Options
|
|
72
71
|
|
|
@@ -1518,67 +1517,6 @@ class LocalOutputWriter(OutputWriter):
|
|
|
1518
1517
|
)
|
|
1519
1518
|
|
|
1520
1519
|
|
|
1521
|
-
def write_local(
|
|
1522
|
-
output: Output | dict[str, Any],
|
|
1523
|
-
path: str | None = None,
|
|
1524
|
-
skip_stdout_reset: bool = False,
|
|
1525
|
-
) -> None:
|
|
1526
|
-
"""
|
|
1527
|
-
!!! warning
|
|
1528
|
-
`write_local` is deprecated, use `write` instead.
|
|
1529
|
-
|
|
1530
|
-
Write the output to the local filesystem or stdout.
|
|
1531
|
-
|
|
1532
|
-
This is a convenience function for instantiating a `LocalOutputWriter` and
|
|
1533
|
-
calling its `write` method.
|
|
1534
|
-
|
|
1535
|
-
Parameters
|
|
1536
|
-
----------
|
|
1537
|
-
output : Union[Output, dict[str, Any]]
|
|
1538
|
-
Output data to write. Can be an Output object or a dictionary.
|
|
1539
|
-
path : str, optional
|
|
1540
|
-
Path to write the output data to. The interpretation depends on the
|
|
1541
|
-
output format:
|
|
1542
|
-
|
|
1543
|
-
- For `OutputFormat.JSON`: File path for the JSON output. If None or
|
|
1544
|
-
empty, writes to stdout.
|
|
1545
|
-
- For `OutputFormat.CSV_ARCHIVE`: Directory path for CSV files. If None
|
|
1546
|
-
or empty, writes to a directory named "output" in the current working
|
|
1547
|
-
directory.
|
|
1548
|
-
skip_stdout_reset : bool, optional
|
|
1549
|
-
Skip resetting stdout before writing the output data. Default is False.
|
|
1550
|
-
|
|
1551
|
-
Raises
|
|
1552
|
-
------
|
|
1553
|
-
ValueError
|
|
1554
|
-
If the Output.output_format is not supported.
|
|
1555
|
-
TypeError
|
|
1556
|
-
If the output is of an unsupported type.
|
|
1557
|
-
|
|
1558
|
-
Notes
|
|
1559
|
-
-----
|
|
1560
|
-
This function detects if stdout was redirected and resets it to avoid
|
|
1561
|
-
unexpected behavior. If you want to skip this behavior, set the
|
|
1562
|
-
skip_stdout_reset parameter to True.
|
|
1563
|
-
|
|
1564
|
-
Examples
|
|
1565
|
-
--------
|
|
1566
|
-
>>> from nextmv.output import write_local, Output
|
|
1567
|
-
>>> # Write JSON to a file
|
|
1568
|
-
>>> write_local(Output(solution={"result": 42}), path="result.json")
|
|
1569
|
-
>>> # Write JSON to stdout
|
|
1570
|
-
>>> write_local({"simple": "data"})
|
|
1571
|
-
"""
|
|
1572
|
-
|
|
1573
|
-
deprecated(
|
|
1574
|
-
name="write_local",
|
|
1575
|
-
reason="`write_local` is deprecated, use `write` instead",
|
|
1576
|
-
)
|
|
1577
|
-
|
|
1578
|
-
writer = LocalOutputWriter()
|
|
1579
|
-
writer.write(output, path, skip_stdout_reset)
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
1520
|
_LOCAL_OUTPUT_WRITER = LocalOutputWriter()
|
|
1583
1521
|
"""Default LocalOutputWriter instance used by the write function."""
|
|
1584
1522
|
|
nextmv/polling.py
CHANGED
|
@@ -128,17 +128,49 @@ class PollingOptions:
|
|
|
128
128
|
return True to stop the polling and False to continue. The function does
|
|
129
129
|
not receive any arguments. The function is called before each poll.
|
|
130
130
|
"""
|
|
131
|
+
sleep_duration_func: Callable[[], float] | None = None
|
|
132
|
+
"""
|
|
133
|
+
Optional function to calculate the sleep duration between polls. If provided,
|
|
134
|
+
this function will be called to determine how long to sleep instead of using
|
|
135
|
+
the default exponential backoff calculation. The function should return a
|
|
136
|
+
float representing the sleep duration in seconds. The function does not
|
|
137
|
+
receive any arguments and is called before each sleep.
|
|
138
|
+
"""
|
|
131
139
|
|
|
132
140
|
|
|
133
141
|
DEFAULT_POLLING_OPTIONS: PollingOptions = PollingOptions()
|
|
134
142
|
"""
|
|
143
|
+
!!! warning
|
|
144
|
+
`DEFAULT_POLLING_OPTIONS` is a mutable global variable. Use the `default_polling_options`
|
|
145
|
+
function to obtain a fresh instance of `PollingOptions` with default settings.
|
|
146
|
+
|
|
135
147
|
Default polling options to use when polling for a run result. This constant
|
|
136
148
|
provides the default values for `PollingOptions` used across the module.
|
|
137
|
-
Using these defaults is recommended for most use cases unless specific timing
|
|
138
|
-
needs are required.
|
|
139
149
|
"""
|
|
140
150
|
|
|
141
151
|
|
|
152
|
+
def default_polling_options() -> PollingOptions:
|
|
153
|
+
"""
|
|
154
|
+
Returns a new instance of PollingOptions with default settings.
|
|
155
|
+
|
|
156
|
+
This function can be used to obtain a fresh set of default polling options
|
|
157
|
+
that can be modified as needed without affecting the global defaults.
|
|
158
|
+
|
|
159
|
+
You can import the `default_polling_options` function directly from `nextmv`:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from nextmv import default_polling_options
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Returns
|
|
166
|
+
-------
|
|
167
|
+
PollingOptions
|
|
168
|
+
A new instance of PollingOptions with default values.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
return PollingOptions()
|
|
172
|
+
|
|
173
|
+
|
|
142
174
|
def poll( # noqa: C901
|
|
143
175
|
polling_options: PollingOptions,
|
|
144
176
|
polling_func: Callable[[], tuple[Any, bool]],
|
|
@@ -255,23 +287,29 @@ def poll( # noqa: C901
|
|
|
255
287
|
)
|
|
256
288
|
|
|
257
289
|
# Calculate the delay.
|
|
258
|
-
if
|
|
259
|
-
#
|
|
260
|
-
|
|
261
|
-
delay = polling_options.max_delay
|
|
262
|
-
delay += random.uniform(0, polling_options.jitter) # Add jitter.
|
|
290
|
+
if polling_options.sleep_duration_func is not None:
|
|
291
|
+
# Use the custom sleep duration function if provided.
|
|
292
|
+
sleep_duration = polling_options.sleep_duration_func()
|
|
263
293
|
else:
|
|
264
|
-
delay
|
|
265
|
-
|
|
266
|
-
|
|
294
|
+
# Calculate delay using exponential backoff with jitter.
|
|
295
|
+
if max_reached:
|
|
296
|
+
# If we already reached the maximum, we don't want to further calculate the
|
|
297
|
+
# delay to avoid overflows.
|
|
298
|
+
delay = polling_options.max_delay
|
|
299
|
+
else:
|
|
300
|
+
delay = polling_options.delay # Base
|
|
301
|
+
delay += polling_options.backoff * (2**ix) # Add exponential backoff.
|
|
302
|
+
|
|
303
|
+
# We cannot exceed the max delay.
|
|
304
|
+
if delay >= polling_options.max_delay:
|
|
305
|
+
max_reached = True
|
|
306
|
+
delay = polling_options.max_delay
|
|
307
|
+
|
|
308
|
+
# Add jitter.
|
|
309
|
+
delay += random.uniform(0, polling_options.jitter)
|
|
267
310
|
|
|
268
|
-
|
|
269
|
-
if delay >= polling_options.max_delay:
|
|
270
|
-
max_reached = True
|
|
271
|
-
delay = polling_options.max_delay
|
|
311
|
+
sleep_duration = delay
|
|
272
312
|
|
|
273
|
-
# Sleep for the calculated delay.
|
|
274
|
-
sleep_duration = delay
|
|
275
313
|
if polling_options.verbose:
|
|
276
314
|
log(f"polling | sleeping for duration: {sleep_duration}")
|
|
277
315
|
|