nextmv 0.27.0__py3-none-any.whl → 0.28.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/cloud/scenario.py CHANGED
@@ -1,4 +1,16 @@
1
- """This module contains definitions for scenario tests."""
1
+ """This module contains definitions for scenario tests.
2
+
3
+ Classes
4
+ -------
5
+ ScenarioConfiguration
6
+ Configuration for a scenario with multiple option values.
7
+ ScenarioInputType
8
+ Enumeration of input types for a scenario.
9
+ ScenarioInput
10
+ Input to be processed in a scenario.
11
+ Scenario
12
+ A test case for comparing a decision model with inputs and configurations.
13
+ """
2
14
 
3
15
  import itertools
4
16
  from dataclasses import dataclass
@@ -11,6 +23,12 @@ class ScenarioConfiguration:
11
23
  """
12
24
  Configuration for a scenario.
13
25
 
26
+ You can import the `ScenarioConfiguration` class directly from `cloud`:
27
+
28
+ ```python
29
+ from nextmv.cloud import ScenarioConfiguration
30
+ ```
31
+
14
32
  You can define multiple values for a single option, which will result in
15
33
  multiple runs being created. For example, if you have a configuration
16
34
  option "x" with values [1, 2], and a configuration option "y" with values
@@ -20,12 +38,17 @@ class ScenarioConfiguration:
20
38
  - x=2, y=3
21
39
  - x=2, y=4
22
40
 
23
- Attributes
41
+ Parameters
24
42
  ----------
25
43
  name : str
26
44
  Name of the configuration option.
27
45
  values : list[str]
28
46
  List of values for the configuration option.
47
+
48
+ Examples
49
+ --------
50
+ >>> from nextmv.cloud import ScenarioConfiguration
51
+ >>> config = ScenarioConfiguration(name="solver", values=["simplex", "interior-point"])
29
52
  """
30
53
 
31
54
  name: str
@@ -36,6 +59,11 @@ class ScenarioConfiguration:
36
59
  def __post_init__(self):
37
60
  """
38
61
  Post-initialization method to ensure that the values are unique.
62
+
63
+ Raises
64
+ ------
65
+ ValueError
66
+ If the configuration values list is empty.
39
67
  """
40
68
  if len(self.values) <= 0:
41
69
  raise ValueError("Configuration values must be non-empty.")
@@ -46,7 +74,13 @@ class ScenarioInputType(str, Enum):
46
74
  Type of input for a scenario. This is used to determine how the input
47
75
  should be processed.
48
76
 
49
- Attributes
77
+ You can import the `ScenarioInputType` class directly from `cloud`:
78
+
79
+ ```python
80
+ from nextmv.cloud import ScenarioInputType
81
+ ```
82
+
83
+ Parameters
50
84
  ----------
51
85
  INPUT_SET : str
52
86
  The data in the scenario is an input set.
@@ -54,6 +88,11 @@ class ScenarioInputType(str, Enum):
54
88
  The data in the scenario is an input.
55
89
  NEW : str
56
90
  The data in the scenario is new data.
91
+
92
+ Examples
93
+ --------
94
+ >>> from nextmv.cloud import ScenarioInputType
95
+ >>> input_type = ScenarioInputType.INPUT_SET
57
96
  """
58
97
 
59
98
  INPUT_SET = "input_set"
@@ -67,12 +106,20 @@ class ScenarioInputType(str, Enum):
67
106
  @dataclass
68
107
  class ScenarioInput:
69
108
  """
70
- Input to be processed in a scenario. The type of input is determined by
71
- the `scenario_input_type` attribute. The input can be a single input set
72
- ID, a list of input IDs, or raw data. The data itself of the scenario input
73
- is tracked by the `scenario_input_data` attribute.
109
+ Input to be processed in a scenario.
74
110
 
75
- Attributes
111
+ You can import the `ScenarioInput` class directly from `cloud`:
112
+
113
+ ```python
114
+ from nextmv.cloud import ScenarioInput
115
+ ```
116
+
117
+ The type of input is determined by the `scenario_input_type` attribute.
118
+ The input can be a single input set ID, a list of input IDs, or raw data.
119
+ The data itself of the scenario input is tracked by the `scenario_input_data`
120
+ attribute.
121
+
122
+ Parameters
76
123
  ----------
77
124
  scenario_input_type : ScenarioInputType
78
125
  Type of input for the scenario. This is used to determine how the input
@@ -85,6 +132,25 @@ class ScenarioInput:
85
132
  behavior occurs when providing raw data (`list[dict[str, Any]]`). All
86
133
  the entries in the list of raw dicts will be collected to create a new
87
134
  input set.
135
+
136
+ Examples
137
+ --------
138
+ >>> from nextmv.cloud import ScenarioInput, ScenarioInputType
139
+ >>> # Using an existing input set
140
+ >>> input_set = ScenarioInput(
141
+ ... scenario_input_type=ScenarioInputType.INPUT_SET,
142
+ ... scenario_input_data="input-set-id-123"
143
+ ... )
144
+ >>> # Using a list of inputs
145
+ >>> inputs = ScenarioInput(
146
+ ... scenario_input_type=ScenarioInputType.INPUT,
147
+ ... scenario_input_data=["input-id-1", "input-id-2"]
148
+ ... )
149
+ >>> # Using raw data
150
+ >>> raw_data = ScenarioInput(
151
+ ... scenario_input_type=ScenarioInputType.NEW,
152
+ ... scenario_input_data=[{"id": 1, "value": "data1"}, {"id": 2, "value": "data2"}]
153
+ ... )
88
154
  """
89
155
 
90
156
  scenario_input_type: ScenarioInputType
@@ -105,6 +171,13 @@ class ScenarioInput:
105
171
  def __post_init__(self):
106
172
  """
107
173
  Post-initialization method to ensure that the input data is valid.
174
+
175
+ Raises
176
+ ------
177
+ ValueError
178
+ If the scenario input type and data type don't match:
179
+ - When using INPUT_SET, scenario_input_data must be a string
180
+ - When using INPUT or NEW, scenario_input_data must be a list
108
181
  """
109
182
  if self.scenario_input_type == ScenarioInputType.INPUT_SET and not isinstance(self.scenario_input_data, str):
110
183
  raise ValueError("Scenario input type must be a string when using an input set.")
@@ -120,19 +193,55 @@ class Scenario:
120
193
  A scenario is a test case that is used to compare a decision model being
121
194
  executed with a set of inputs and configurations.
122
195
 
123
- Attributes
196
+ You can import the `Scenario` class directly from `cloud`:
197
+
198
+ ```python
199
+ from nextmv.cloud import Scenario
200
+ ```
201
+
202
+ A scenario encapsulates all the necessary information to run a test case
203
+ against a decision model. Each scenario includes input data, an instance ID,
204
+ and can optionally include configuration options that define different
205
+ variations of the run.
206
+
207
+ Parameters
124
208
  ----------
125
209
  scenario_input : ScenarioInput
126
210
  Input for the scenario. The input is composed of a type and data. Make
127
211
  sure you use the `ScenarioInput` class to create the input.
212
+ instance_id : str
213
+ ID of the instance to be used for the scenario.
128
214
  scenario_id : Optional[str]
129
215
  Optional ID of the scenario. The default value will be set as
130
216
  `scenario-<index>` if not set.
131
- instance_id : str
132
- ID of the instance to be used for the scenario.
133
- configuration : Optional[ScenarioConfiguration]
217
+ configuration : Optional[list[ScenarioConfiguration]]
134
218
  Optional configuration for the scenario. Use this attribute to
135
219
  configure variation of options for the scenario.
220
+
221
+ Examples
222
+ --------
223
+ >>> from nextmv.cloud import Scenario, ScenarioInput, ScenarioInputType, ScenarioConfiguration
224
+ >>> # Creating a simple scenario with an input set
225
+ >>> input_data = ScenarioInput(
226
+ ... scenario_input_type=ScenarioInputType.INPUT_SET,
227
+ ... scenario_input_data="input-set-id-123"
228
+ ... )
229
+ >>> scenario = Scenario(
230
+ ... scenario_input=input_data,
231
+ ... instance_id="instance-id-456",
232
+ ... scenario_id="my-test-scenario"
233
+ ... )
234
+ >>>
235
+ >>> # Creating a scenario with configuration options
236
+ >>> config_options = [
237
+ ... ScenarioConfiguration(name="solver", values=["simplex", "interior-point"]),
238
+ ... ScenarioConfiguration(name="timeout", values=["10", "30", "60"])
239
+ ... ]
240
+ >>> scenario_with_config = Scenario(
241
+ ... scenario_input=input_data,
242
+ ... instance_id="instance-id-456",
243
+ ... configuration=config_options
244
+ ... )
136
245
  """
137
246
 
138
247
  scenario_input: ScenarioInput
@@ -156,14 +265,36 @@ class Scenario:
156
265
  def option_combinations(self) -> list[dict[str, str]]:
157
266
  """
158
267
  Creates the combination of options that are derived from the
159
- `configuration` property. The cross-product of the configuration
160
- options is created to generate all possible combinations of options.
268
+ `configuration` property.
269
+
270
+ This method calculates the cross-product of all configuration
271
+ options to generate all possible combinations. If no configuration
272
+ is provided, it returns a list with an empty dictionary.
161
273
 
162
274
  Returns
163
275
  -------
164
276
  list[dict[str, str]]
165
277
  A list of dictionaries where each dictionary represents a set of
166
278
  options derived from the configuration.
279
+
280
+ Examples
281
+ --------
282
+ >>> from nextmv.cloud import Scenario, ScenarioInput, ScenarioInputType, ScenarioConfiguration
283
+ >>> input_data = ScenarioInput(
284
+ ... scenario_input_type=ScenarioInputType.INPUT_SET,
285
+ ... scenario_input_data="input-set-id"
286
+ ... )
287
+ >>> config = [
288
+ ... ScenarioConfiguration(name="x", values=["1", "2"]),
289
+ ... ScenarioConfiguration(name="y", values=["3", "4"])
290
+ ... ]
291
+ >>> scenario = Scenario(
292
+ ... scenario_input=input_data,
293
+ ... instance_id="instance-id",
294
+ ... configuration=config
295
+ ... )
296
+ >>> scenario.option_combinations()
297
+ [{'x': '1', 'y': '3'}, {'x': '1', 'y': '4'}, {'x': '2', 'y': '3'}, {'x': '2', 'y': '4'}]
167
298
  """
168
299
 
169
300
  if self.configuration is None or len(self.configuration) == 0:
@@ -177,9 +308,12 @@ class Scenario:
177
308
 
178
309
  def _option_sets(scenarios: list[Scenario]) -> dict[str, dict[str, dict[str, str]]]:
179
310
  """
180
- Creates options sets that are derived from `scenarios`. The options sets
181
- are grouped by scenario ID. The cross-product of the configuration
182
- options is created to generate all possible combinations of options.
311
+ Creates options sets that are derived from `scenarios`.
312
+
313
+ The options sets are grouped by scenario ID. The cross-product of the
314
+ configuration options is created to generate all possible combinations
315
+ of options. Each combination is given a unique key based on the scenario ID
316
+ and a combination index.
183
317
 
184
318
  Parameters
185
319
  ----------
@@ -193,6 +327,23 @@ def _option_sets(scenarios: list[Scenario]) -> dict[str, dict[str, dict[str, str
193
327
  dictionaries of option sets. Each option set is a dictionary where the
194
328
  keys are option names and the values are the corresponding option
195
329
  values.
330
+
331
+ Examples
332
+ --------
333
+ >>> from nextmv.cloud import Scenario, ScenarioInput, ScenarioInputType, ScenarioConfiguration
334
+ >>> input_data = ScenarioInput(
335
+ ... scenario_input_type=ScenarioInputType.INPUT_SET,
336
+ ... scenario_input_data="input-set-id"
337
+ ... )
338
+ >>> config = [ScenarioConfiguration(name="x", values=["1", "2"])]
339
+ >>> scenario = Scenario(
340
+ ... scenario_input=input_data,
341
+ ... instance_id="instance-id",
342
+ ... scenario_id="test-scenario",
343
+ ... configuration=config
344
+ ... )
345
+ >>> _option_sets([scenario])
346
+ {'test-scenario': {'test-scenario_0': {'x': '1'}, 'test-scenario_1': {'x': '2'}}}
196
347
  """
197
348
 
198
349
  sets_by_scenario = {}
@@ -210,9 +361,43 @@ def _option_sets(scenarios: list[Scenario]) -> dict[str, dict[str, dict[str, str
210
361
 
211
362
  def _scenarios_by_id(scenarios: list[Scenario]) -> dict[str, Scenario]:
212
363
  """
213
- This function maps a scenario to its ID. A scenario ID is created if it
214
- wasn't defined. This function also checks that there are no duplicate
215
- scenario IDs.
364
+ Maps scenarios to their IDs.
365
+
366
+ This function builds a dictionary that maps each scenario to its ID.
367
+ If a scenario doesn't have an ID defined, one is created using the format
368
+ "scenario-{index}". The function also checks that there are no duplicate
369
+ scenario IDs in the provided list.
370
+
371
+ Parameters
372
+ ----------
373
+ scenarios : list[Scenario]
374
+ List of scenarios to be mapped.
375
+
376
+ Returns
377
+ -------
378
+ dict[str, Scenario]
379
+ A dictionary where keys are scenario IDs and values are the corresponding
380
+ Scenario objects.
381
+
382
+ Raises
383
+ ------
384
+ ValueError
385
+ If duplicate scenario IDs are found in the list.
386
+
387
+ Examples
388
+ --------
389
+ >>> from nextmv.cloud import Scenario, ScenarioInput, ScenarioInputType
390
+ >>> input_data = ScenarioInput(
391
+ ... scenario_input_type=ScenarioInputType.INPUT_SET,
392
+ ... scenario_input_data="input-set-id"
393
+ ... )
394
+ >>> scenarios = [
395
+ ... Scenario(scenario_input=input_data, instance_id="instance-1", scenario_id="test-1"),
396
+ ... Scenario(scenario_input=input_data, instance_id="instance-2")
397
+ ... ]
398
+ >>> result = _scenarios_by_id(scenarios)
399
+ >>> sorted(list(result.keys()))
400
+ ['scenario-2', 'test-1']
216
401
  """
217
402
 
218
403
  scenario_by_id = {}
nextmv/cloud/secrets.py CHANGED
@@ -1,4 +1,17 @@
1
- """This module contains the declarations for secrets management."""
1
+ """This module contains the declarations for secrets management.
2
+
3
+ Classes
4
+ -------
5
+ SecretsCollectionSummary
6
+ Summary of a secrets collection in Nextmv Cloud.
7
+ SecretType
8
+ Enumeration of available secret types.
9
+ Secret
10
+ Representation of a sensitive piece of information.
11
+ SecretsCollection
12
+ Collection of secrets hosted in the Nextmv Cloud.
13
+
14
+ """
2
15
 
3
16
  from datetime import datetime
4
17
  from enum import Enum
@@ -9,8 +22,48 @@ from nextmv.base_model import BaseModel
9
22
 
10
23
 
11
24
  class SecretsCollectionSummary(BaseModel):
12
- """The summary of a secrets collection, which is a mechanism for hosting
13
- secrets securely in the Nextmv Cloud."""
25
+ """The summary of a secrets collection in the Nextmv Cloud.
26
+
27
+ You can import the `SecretsCollectionSummary` class directly from `cloud`:
28
+
29
+ ```python
30
+ from nextmv.cloud import SecretsCollectionSummary
31
+ ```
32
+
33
+ A secrets collection is a mechanism for hosting secrets securely in the
34
+ Nextmv Cloud. This class provides summary information about such a collection.
35
+
36
+ Parameters
37
+ ----------
38
+ collection_id : str
39
+ ID of the secrets collection. This is aliased from `id` for
40
+ serialization and validation.
41
+ application_id : str
42
+ ID of the application to which the secrets collection belongs.
43
+ name : str
44
+ Name of the secrets collection.
45
+ description : str
46
+ Description of the secrets collection.
47
+ created_at : datetime
48
+ Creation date of the secrets collection.
49
+ updated_at : datetime
50
+ Last update date of the secrets collection.
51
+
52
+ Examples
53
+ --------
54
+ >>> from datetime import datetime
55
+ >>> collection_summary = SecretsCollectionSummary(
56
+ ... collection_id="col_123",
57
+ ... application_id="app_456",
58
+ ... name="My API Credentials",
59
+ ... description="Collection of API keys for external services",
60
+ ... created_at=datetime.now(),
61
+ ... updated_at=datetime.now()
62
+ ... )
63
+ >>> print(collection_summary.name)
64
+ My API Credentials
65
+
66
+ """
14
67
 
15
68
  collection_id: str = Field(
16
69
  serialization_alias="id",
@@ -30,7 +83,37 @@ class SecretsCollectionSummary(BaseModel):
30
83
 
31
84
 
32
85
  class SecretType(str, Enum):
33
- """Type of the secret that is stored in the Nextmv Cloud."""
86
+ """Type of the secret that is stored in the Nextmv Cloud.
87
+
88
+ You can import the `SecretType` class directly from `cloud`:
89
+
90
+ ```python
91
+ from nextmv.cloud import SecretType
92
+ ```
93
+
94
+ This enumeration defines the types of secrets that can be managed.
95
+
96
+ Attributes
97
+ ----------
98
+ ENV : str
99
+ Represents an environment variable secret. The value of the secret
100
+ will be available as an environment variable in the execution
101
+ environment.
102
+ FILE : str
103
+ Represents a file-based secret. The value of the secret will be
104
+ written to a file, and the path to this file will be available
105
+ via the `location` attribute of the `Secret`.
106
+
107
+ Examples
108
+ --------
109
+ >>> secret_type_env = SecretType.ENV
110
+ >>> print(secret_type_env.value)
111
+ env
112
+ >>> secret_type_file = SecretType.FILE
113
+ >>> print(secret_type_file.value)
114
+ file
115
+
116
+ """
34
117
 
35
118
  ENV = "env"
36
119
  """Environment variable secret type."""
@@ -40,7 +123,49 @@ class SecretType(str, Enum):
40
123
 
41
124
  class Secret(BaseModel):
42
125
  """A secret is a piece of sensitive information that is stored securely in
43
- the Nextmv Cloud."""
126
+ the Nextmv Cloud.
127
+
128
+ You can import the `Secret` class directly from `cloud`:
129
+
130
+ ```python
131
+ from nextmv.cloud import Secret
132
+ ```
133
+
134
+ This class represents an individual secret, detailing its type, location
135
+ (if applicable), and value.
136
+
137
+ Parameters
138
+ ----------
139
+ secret_type : SecretType
140
+ The type of the secret, indicating how it should be handled (e.g.,
141
+ as an environment variable or a file). This is aliased from `type`
142
+ for serialization and validation.
143
+ location : str
144
+ The location where the secret will be made available. For `ENV`
145
+ type secrets, this is the name of the environment variable. For
146
+ `FILE` type secrets, this is the path where the file will be
147
+ created.
148
+ value : str
149
+ The actual content of the secret.
150
+
151
+ Examples
152
+ --------
153
+ >>> env_secret = Secret(
154
+ ... secret_type=SecretType.ENV,
155
+ ... location="API_KEY",
156
+ ... value="supersecretapikey123"
157
+ ... )
158
+ >>> print(env_secret.location)
159
+ API_KEY
160
+ >>> file_secret = Secret(
161
+ ... secret_type=SecretType.FILE,
162
+ ... location="/mnt/secrets/config.json",
163
+ ... value=\'\'\'{"user": "admin", "pass": "secure"}\'\'\'
164
+ ... )
165
+ >>> print(file_secret.secret_type)
166
+ SecretType.FILE
167
+
168
+ """
44
169
 
45
170
  secret_type: SecretType = Field(
46
171
  serialization_alias="type",
@@ -55,7 +180,55 @@ class Secret(BaseModel):
55
180
 
56
181
  class SecretsCollection(SecretsCollectionSummary, BaseModel):
57
182
  """A secrets collection is a mechanism for hosting secrets securely in the
58
- Nextmv Cloud."""
183
+ Nextmv Cloud.
184
+
185
+ You can import the `SecretsCollection` class directly from `cloud`:
186
+
187
+ ```python
188
+ from nextmv.cloud import SecretsCollection
189
+ ```
190
+
191
+ This class extends `SecretsCollectionSummary` by including the actual list
192
+ of secrets contained within the collection.
193
+
194
+ Parameters
195
+ ----------
196
+ secrets : list[Secret]
197
+ A list of `Secret` objects that are part of this collection.
198
+ *args
199
+ Variable length argument list for `SecretsCollectionSummary`.
200
+ **kwargs
201
+ Arbitrary keyword arguments for `SecretsCollectionSummary`.
202
+
203
+
204
+ Examples
205
+ --------
206
+ >>> from datetime import datetime
207
+ >>> secret1 = Secret(
208
+ ... secret_type=SecretType.ENV,
209
+ ... location="DATABASE_USER",
210
+ ... value="nextmv_user"
211
+ ... )
212
+ >>> secret2 = Secret(
213
+ ... secret_type=SecretType.FILE,
214
+ ... location="/etc/app/license.key",
215
+ ... value="longlicensekeystring"
216
+ ... )
217
+ >>> full_collection = SecretsCollection(
218
+ ... collection_id="col_789",
219
+ ... application_id="app_000",
220
+ ... name="Full App Secrets",
221
+ ... description="All secrets required by the main application",
222
+ ... created_at=datetime.now(),
223
+ ... updated_at=datetime.now(),
224
+ ... secrets=[secret1, secret2]
225
+ ... )
226
+ >>> print(full_collection.name)
227
+ Full App Secrets
228
+ >>> print(len(full_collection.secrets))
229
+ 2
230
+
231
+ """
59
232
 
60
233
  secrets: list[Secret]
61
234
  """List of secrets in the collection."""
nextmv/cloud/status.py CHANGED
@@ -1,8 +1,59 @@
1
+ """
2
+ Provides status enums for Nextmv Cloud runs.
3
+
4
+ This module defines enumerations for representing the status of a run in
5
+ Nextmv Cloud. It includes a deprecated `Status` enum and the current `StatusV2`
6
+ enum.
7
+
8
+ Classes
9
+ -------
10
+ Status
11
+ Deprecated status of a run.
12
+ StatusV2
13
+ Represents the status of a run.
14
+ """
15
+
1
16
  from enum import Enum
2
17
 
3
18
 
4
19
  class Status(str, Enum):
5
- """Status of a run. Deprecated: use StatusV2."""
20
+ """
21
+ !!! warning
22
+ `Status` is deprecated, use `StatusV2` instead.
23
+
24
+ Status of a run.
25
+
26
+ You can import the `Status` class directly from `cloud`:
27
+
28
+ ```python
29
+ from nextmv.cloud import Status
30
+ ```
31
+
32
+ This enum represents the possible states of a run. It is deprecated and
33
+ `StatusV2` should be used for new implementations.
34
+
35
+ Attributes
36
+ ----------
37
+ failed : str
38
+ Run failed.
39
+ running : str
40
+ Run is running.
41
+ succeeded : str
42
+ Run succeeded.
43
+
44
+ Examples
45
+ --------
46
+ >>> from nextmv.cloud import Status
47
+ >>> current_status = Status.running
48
+ >>> if current_status == Status.succeeded:
49
+ ... print("Run completed successfully.")
50
+ ... elif current_status == Status.failed:
51
+ ... print("Run failed.")
52
+ ... else:
53
+ ... print(f"Run is currently {current_status.value}.")
54
+ Run is currently running.
55
+
56
+ """
6
57
 
7
58
  failed = "failed"
8
59
  """Run failed."""
@@ -13,7 +64,49 @@ class Status(str, Enum):
13
64
 
14
65
 
15
66
  class StatusV2(str, Enum):
16
- """Status of a run."""
67
+ """
68
+ Status of a run.
69
+
70
+ You can import the `StatusV2` class directly from `cloud`:
71
+
72
+ ```python
73
+ from nextmv.cloud import StatusV2
74
+ ```
75
+
76
+ This enum represents the comprehensive set of possible states for a run
77
+ in Nextmv Cloud.
78
+
79
+ Attributes
80
+ ----------
81
+ canceled : str
82
+ Run was canceled.
83
+ failed : str
84
+ Run failed.
85
+ none : str
86
+ Run has no status.
87
+ queued : str
88
+ Run is queued.
89
+ running : str
90
+ Run is running.
91
+ succeeded : str
92
+ Run succeeded.
93
+
94
+ Examples
95
+ --------
96
+ >>> from nextmv.cloud import StatusV2
97
+ >>> run_status = StatusV2.queued
98
+ >>> print(f"The run status is: {run_status.value}")
99
+ The run status is: queued
100
+
101
+ >>> if run_status == StatusV2.succeeded:
102
+ ... print("Processing complete.")
103
+ ... elif run_status in [StatusV2.queued, StatusV2.running]:
104
+ ... print("Processing in progress.")
105
+ ... else:
106
+ ... print("Processing has not started or has ended with issues.")
107
+ Processing in progress.
108
+
109
+ """
17
110
 
18
111
  canceled = "canceled"
19
112
  """Run was canceled."""