nextmv 1.0.0.dev4__py3-none-any.whl → 1.0.0.dev6__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.
Files changed (38) hide show
  1. nextmv/__about__.py +1 -1
  2. nextmv/__entrypoint__.py +1 -2
  3. nextmv/__init__.py +0 -4
  4. nextmv/cli/cloud/app/push.py +294 -204
  5. nextmv/cli/cloud/input_set/__init__.py +2 -0
  6. nextmv/cli/cloud/input_set/delete.py +67 -0
  7. nextmv/cli/cloud/run/create.py +4 -9
  8. nextmv/cli/cloud/shadow/stop.py +14 -2
  9. nextmv/cli/cloud/switchback/stop.py +14 -2
  10. nextmv/cli/community/clone.py +11 -197
  11. nextmv/cli/community/list.py +46 -116
  12. nextmv/cli/confirm.py +5 -3
  13. nextmv/cloud/__init__.py +4 -38
  14. nextmv/cloud/acceptance_test.py +1 -65
  15. nextmv/cloud/account.py +1 -6
  16. nextmv/cloud/application/__init__.py +1 -198
  17. nextmv/cloud/application/_batch_scenario.py +2 -17
  18. nextmv/cloud/application/_input_set.py +42 -6
  19. nextmv/cloud/application/_instance.py +1 -1
  20. nextmv/cloud/application/_managed_input.py +1 -1
  21. nextmv/cloud/application/_shadow.py +10 -4
  22. nextmv/cloud/application/_switchback.py +11 -2
  23. nextmv/cloud/application/_version.py +1 -1
  24. nextmv/cloud/batch_experiment.py +3 -1
  25. nextmv/cloud/community.py +441 -0
  26. nextmv/cloud/shadow.py +25 -0
  27. nextmv/deprecated.py +5 -3
  28. nextmv/input.py +0 -52
  29. nextmv/local/runner.py +1 -1
  30. nextmv/options.py +11 -256
  31. nextmv/output.py +0 -62
  32. nextmv/run.py +1 -10
  33. nextmv/status.py +1 -51
  34. {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev6.dist-info}/METADATA +3 -1
  35. {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev6.dist-info}/RECORD +38 -36
  36. {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev6.dist-info}/WHEEL +0 -0
  37. {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev6.dist-info}/entry_points.txt +0 -0
  38. {nextmv-1.0.0.dev4.dist-info → nextmv-1.0.0.dev6.dist-info}/licenses/LICENSE +0 -0
@@ -2,18 +2,18 @@
2
2
  This module defines the community list command for the Nextmv CLI.
3
3
  """
4
4
 
5
- from typing import Annotated, Any
5
+ from typing import Annotated
6
6
 
7
- import requests
8
7
  import rich
9
8
  import typer
10
- import yaml
11
9
  from rich.console import Console
12
10
  from rich.table import Table
13
11
 
14
12
  from nextmv.cli.configuration.config import build_client
15
13
  from nextmv.cli.message import error
16
14
  from nextmv.cli.options import ProfileOption
15
+ from nextmv.cloud.client import Client
16
+ from nextmv.cloud.community import CommunityApp, list_community_apps
17
17
 
18
18
  # Set up subcommand application.
19
19
  app = typer.Typer()
@@ -62,96 +62,73 @@ def list(
62
62
  if app is not None and app == "":
63
63
  error("The --app flag cannot be an empty string.")
64
64
 
65
- manifest = download_manifest(profile=profile)
65
+ client = build_client(profile)
66
66
  if flat and app is None:
67
- apps_list(manifest)
67
+ _apps_list(client)
68
68
  raise typer.Exit()
69
69
  elif not flat and app is None:
70
- apps_table(manifest)
70
+ _apps_table(client)
71
71
  raise typer.Exit()
72
72
  elif flat and app is not None and app != "":
73
- versions_list(manifest, app)
73
+ _versions_list(client, app)
74
74
  raise typer.Exit()
75
75
  elif not flat and app is not None and app != "":
76
- versions_table(manifest, app)
76
+ _versions_table(client, app)
77
77
  raise typer.Exit()
78
78
 
79
79
 
80
- def download_manifest(profile: str | None = None) -> dict:
80
+ def _apps_table(client: Client) -> None:
81
81
  """
82
- Downloads and returns the community apps manifest.
82
+ This function prints a table of community apps.
83
83
 
84
84
  Parameters
85
85
  ----------
86
- profile : str | None
87
- The profile name to use. If None, the default profile is used.
88
-
89
- Returns
90
- -------
91
- dict
92
- The community apps manifest as a dictionary.
93
-
94
- Raises
95
- requests.HTTPError
96
- If the response status code is not 2xx.
97
- """
98
-
99
- response = download_file(directory="community-apps", file="manifest.yml", profile=profile)
100
- manifest = yaml.safe_load(response.text)
101
-
102
- return manifest
103
-
104
-
105
- def apps_table(manifest: dict[str, Any]) -> None:
106
- """
107
- This function prints a table of community apps from the manifest.
108
-
109
- Parameters
110
- ----------
111
- manifest : dict[str, Any]
112
- The community apps manifest.
86
+ client : Client
87
+ The Nextmv Cloud client to use for the request.
113
88
  """
114
89
 
90
+ apps = list_community_apps(client)
115
91
  table = Table("Name", "Type", "Latest", "Description", border_style="cyan", header_style="cyan")
116
- for app in manifest.get("apps", []):
92
+ for app in apps:
117
93
  table.add_row(
118
- app.get("name", ""),
119
- app.get("type", ""),
120
- app.get("latest_app_version", ""),
121
- app.get("description", ""),
94
+ app.name,
95
+ app.app_type,
96
+ app.latest_app_version if app.latest_app_version is not None else "",
97
+ app.description,
122
98
  )
123
99
 
124
100
  console.print(table)
125
101
 
126
102
 
127
- def apps_list(manifest: dict[str, Any]) -> None:
103
+ def _apps_list(client: Client) -> None:
128
104
  """
129
- This function prints a flat list of community app names from the manifest.
105
+ This function prints a flat list of community app names.
130
106
 
131
107
  Parameters
132
108
  ----------
133
- manifest : dict[str, Any]
134
- The community apps manifest.
109
+ client : Client
110
+ The Nextmv Cloud client to use for the request.
135
111
  """
136
112
 
137
- names = [app.get("name", "") for app in manifest.get("apps", [])]
113
+ apps = list_community_apps(client)
114
+ names = [app.name for app in apps]
138
115
  print("\n".join(names))
139
116
 
140
117
 
141
- def versions_table(manifest: dict[str, Any], app: str) -> None:
118
+ def _versions_table(client: Client, app: str) -> None:
142
119
  """
143
120
  This function prints a table of versions for a specific community app.
144
121
 
145
122
  Parameters
146
123
  ----------
147
- manifest : dict[str, Any]
148
- The community apps manifest.
124
+ client : Client
125
+ The Nextmv Cloud client to use for the request.
149
126
  app : str
150
127
  The name of the community app.
151
128
  """
152
129
 
153
- app_obj = find_app(manifest, app)
154
- latest_version = app_obj.get("latest_app_version", "")
130
+ comm_app = _find_app(client, app)
131
+ latest_version = comm_app.latest_app_version if comm_app.latest_app_version is not None else ""
155
132
 
156
133
  # Add the latest version with indicator
157
134
  table = Table("Version", "Latest?", border_style="cyan", header_style="cyan")
@@ -159,7 +136,7 @@ def versions_table(manifest: dict[str, Any], app: str) -> None:
159
136
  table.add_row("", "") # Empty row to separate latest from others.
160
137
 
161
138
  # Add all other versions (excluding the latest)
162
- versions = app_obj.get("app_versions", [])
139
+ versions = comm_app.app_versions if comm_app.app_versions is not None else []
163
140
  for version in versions:
164
141
  if version != latest_version:
165
142
  table.add_row(version, "")
@@ -167,99 +144,52 @@ def versions_table(manifest: dict[str, Any], app: str) -> None:
167
144
  console.print(table)
168
145
 
169
146
 
170
- def versions_list(manifest: dict[str, Any], app: str) -> None:
147
+ def _versions_list(client: Client, app: str) -> None:
171
148
  """
172
149
  This function prints a flat list of versions for a specific community app.
173
150
 
174
151
  Parameters
175
152
  ----------
176
- manifest : dict[str, Any]
177
- The community apps manifest.
153
+ client : Client
154
+ The Nextmv Cloud client to use for the request.
178
155
  app : str
179
156
  The name of the community app.
180
157
  """
181
158
 
182
- app_obj = find_app(manifest, app)
183
- versions = app_obj.get("app_versions", [])
159
+ comm_app = _find_app(client, app)
160
+ versions = comm_app.app_versions if comm_app.app_versions is not None else []
184
161
 
185
162
  versions_output = ""
186
163
  for version in versions:
187
164
  versions_output += f"{version}\n"
188
165
 
189
- print("\n".join(app_obj.get("app_versions", [])))
190
-
191
-
192
- def download_file(
193
- directory: str,
194
- file: str,
195
- profile: str | None = None,
196
- ) -> requests.Response:
197
- """
198
- Gets a file from an internal bucket and return it.
199
-
200
- Parameters
201
- ----------
202
- directory : str
203
- The directory in the bucket where the file is located.
204
- file : str
205
- The name of the file to download.
206
- profile : str | None
207
- The profile name to use. If None, the default profile is used.
208
-
209
- Returns
210
- -------
211
- requests.Response
212
- The response object containing the file data.
213
-
214
- Raises
215
- requests.HTTPError
216
- If the response status code is not 2xx.
217
- """
218
-
219
- client = build_client(profile)
220
-
221
- # Request the download URL for the file.
222
- response = client.request(
223
- method="GET",
224
- endpoint="v0/internal/tools",
225
- headers=client.headers | {"request-source": "cli"}, # Pass `client.headers` to preserve auth.
226
- query_params={"file": f"{directory}/{file}"},
227
- )
228
-
229
- # Use the URL obtained to download the file.
230
- body = response.json()
231
- download_response = client.request(
232
- method="GET",
233
- endpoint=body.get("url"),
234
- headers={"Content-Type": "application/json"},
235
- )
236
-
237
- return download_response
166
+ print("\n".join(versions_output))
238
167
 
239
168
 
240
- def find_app(manifest: dict[str, Any], app: str) -> dict[str, Any] | None:
169
+ def _find_app(client: Client, app: str) -> CommunityApp | None:
241
170
  """
242
171
  Finds and returns a community app from the manifest by its name.
243
172
 
244
173
  Parameters
245
174
  ----------
246
- manifest : dict[str, Any]
247
- The community apps manifest.
175
+ client : Client
176
+ The Nextmv Cloud client to use for the request.
248
177
  app : str
249
178
  The name of the community app to find.
250
179
 
251
180
  Returns
252
181
  -------
253
- dict[str, Any] | None
254
- The community app dictionary if found, otherwise None.
182
+ CommunityApp | None
183
+ The community app if found, otherwise None.
255
184
  """
256
185
 
257
- for manifest_app in manifest.get("apps", []):
258
- if manifest_app.get("name", "") == app:
259
- return manifest_app
186
+ comm_apps = list_community_apps(client)
187
+ for comm_app in comm_apps:
188
+ if comm_app.name == app:
189
+ return comm_app
260
190
 
261
191
  # We don't use error() here to allow printing something before exiting.
262
192
  rich.print(f"[red]Error:[/red] Community app [magenta]{app}[/magenta] was not found. Here are the available apps:")
263
- apps_table(manifest)
193
+ _apps_table(client)
264
194
 
265
195
  raise typer.Exit(code=1)
nextmv/cli/confirm.py CHANGED
@@ -3,7 +3,7 @@ import sys
3
3
  from rich.prompt import Confirm
4
4
 
5
5
 
6
- def get_confirmation(msg: str) -> bool:
6
+ def get_confirmation(msg: str, default: bool = False) -> bool:
7
7
  """
8
8
  Method to get a yes/no confirmation from the user.
9
9
 
@@ -11,6 +11,8 @@ def get_confirmation(msg: str) -> bool:
11
11
  ----------
12
12
  msg : str
13
13
  The message to display to the user.
14
+ default : bool, optional
15
+ The default value if the user just presses Enter. Default is False.
14
16
 
15
17
  Returns
16
18
  -------
@@ -21,11 +23,11 @@ def get_confirmation(msg: str) -> bool:
21
23
  # If this is not an interactive terminal, do not ask for confirmation, to
22
24
  # avoid hanging indefinitely waiting for a user response.
23
25
  if not sys.stdin.isatty():
24
- return False
26
+ return default
25
27
 
26
28
  return Confirm.ask(
27
29
  msg,
28
- default=False,
30
+ default=default,
29
31
  case_sensitive=False,
30
32
  show_default=True,
31
33
  show_choices=True,
nextmv/cloud/__init__.py CHANGED
@@ -1,42 +1,5 @@
1
1
  """Functionality for interacting with the Nextmv Cloud."""
2
2
 
3
- # These imports are kept for backwards compatibility but the preferred import path is
4
- # from nextmv directly. These imports will be removed in a future release.
5
- from nextmv.manifest import MANIFEST_FILE_NAME as MANIFEST_FILE_NAME
6
- from nextmv.manifest import Manifest as Manifest
7
- from nextmv.manifest import ManifestBuild as ManifestBuild
8
- from nextmv.manifest import ManifestContent as ManifestContent
9
- from nextmv.manifest import ManifestContentMultiFile as ManifestContentMultiFile
10
- from nextmv.manifest import ManifestContentMultiFileInput as ManifestContentMultiFileInput
11
- from nextmv.manifest import ManifestContentMultiFileOutput as ManifestContentMultiFileOutput
12
- from nextmv.manifest import ManifestOption as ManifestOption
13
- from nextmv.manifest import ManifestPython as ManifestPython
14
- from nextmv.manifest import ManifestPythonModel as ManifestPythonModel
15
- from nextmv.manifest import ManifestRuntime as ManifestRuntime
16
- from nextmv.manifest import ManifestType as ManifestType
17
- from nextmv.polling import PollingOptions as PollingOptions
18
- from nextmv.polling import poll as poll
19
- from nextmv.run import ErrorLog as ErrorLog
20
- from nextmv.run import ExternalRunResult as ExternalRunResult
21
- from nextmv.run import Format as Format
22
- from nextmv.run import FormatInput as FormatInput
23
- from nextmv.run import FormatOutput as FormatOutput
24
- from nextmv.run import Metadata as Metadata
25
- from nextmv.run import RunConfiguration as RunConfiguration
26
- from nextmv.run import RunInformation as RunInformation
27
- from nextmv.run import RunLog as RunLog
28
- from nextmv.run import RunQueuing as RunQueuing
29
- from nextmv.run import RunResult as RunResult
30
- from nextmv.run import RunType as RunType
31
- from nextmv.run import RunTypeConfiguration as RunTypeConfiguration
32
- from nextmv.run import TrackedRun as TrackedRun
33
- from nextmv.run import TrackedRunStatus as TrackedRunStatus
34
- from nextmv.run import run_duration as run_duration
35
- from nextmv.safe import safe_id as safe_id
36
- from nextmv.safe import safe_name_and_id as safe_name_and_id
37
- from nextmv.status import Status as Status
38
- from nextmv.status import StatusV2 as StatusV2
39
-
40
3
  from .acceptance_test import AcceptanceTest as AcceptanceTest
41
4
  from .acceptance_test import AcceptanceTestResults as AcceptanceTestResults
42
5
  from .acceptance_test import Comparison as Comparison
@@ -52,7 +15,6 @@ from .acceptance_test import MetricToleranceType as MetricToleranceType
52
15
  from .acceptance_test import MetricType as MetricType
53
16
  from .acceptance_test import ResultStatistics as ResultStatistics
54
17
  from .acceptance_test import StatisticType as StatisticType
55
- from .acceptance_test import ToleranceType as ToleranceType
56
18
  from .account import Account as Account
57
19
  from .account import AccountMember as AccountMember
58
20
  from .account import Queue as Queue
@@ -68,6 +30,9 @@ from .batch_experiment import BatchExperimentRun as BatchExperimentRun
68
30
  from .batch_experiment import ExperimentStatus as ExperimentStatus
69
31
  from .client import Client as Client
70
32
  from .client import get_size as get_size
33
+ from .community import CommunityApp as CommunityApp
34
+ from .community import clone_community_app as clone_community_app
35
+ from .community import list_community_apps as list_community_apps
71
36
  from .ensemble import EnsembleDefinition as EnsembleDefinition
72
37
  from .ensemble import EvaluationRule as EvaluationRule
73
38
  from .ensemble import RuleObjective as RuleObjective
@@ -93,6 +58,7 @@ from .secrets import SecretType as SecretType
93
58
  from .shadow import ShadowTest as ShadowTest
94
59
  from .shadow import ShadowTestMetadata as ShadowTestMetadata
95
60
  from .shadow import StartEvents as StartEvents
61
+ from .shadow import StopIntent as StopIntent
96
62
  from .shadow import TerminationEvents as TerminationEvents
97
63
  from .shadow import TestComparison as TestComparison
98
64
  from .switchback import SwitchbackPlan as SwitchbackPlan
@@ -13,7 +13,7 @@ StatisticType : Enum
13
13
  Type of statistical process for collapsing multiple values of a metric.
14
14
  Comparison : Enum
15
15
  Comparison operators to use for comparing two metrics.
16
- ToleranceType : Enum
16
+ MetricToleranceType : Enum
17
17
  Type of tolerance used for a metric.
18
18
  ExperimentStatus : Enum
19
19
  Status of an acceptance test experiment.
@@ -46,7 +46,6 @@ from enum import Enum
46
46
 
47
47
  from nextmv.base_model import BaseModel
48
48
  from nextmv.cloud.batch_experiment import ExperimentStatus
49
- from nextmv.deprecated import deprecated
50
49
 
51
50
 
52
51
  class MetricType(str, Enum):
@@ -212,69 +211,6 @@ class Comparison(str, Enum):
212
211
  """Not equal to metric type."""
213
212
 
214
213
 
215
- class ToleranceType(str, Enum):
216
- """
217
- !!! warning
218
- `ToleranceType` is deprecated, use `MetricToleranceType` instead.
219
-
220
- Type of tolerance used for a metric.
221
-
222
- You can import the `ToleranceType` class directly from `cloud`:
223
-
224
- ```python
225
- from nextmv.cloud import ToleranceType
226
- ```
227
-
228
- This enumeration defines the different types of tolerances that can be used
229
- when comparing metrics in acceptance tests.
230
-
231
- Attributes
232
- ----------
233
- undefined : str
234
- Undefined tolerance type (empty string).
235
- absolute : str
236
- Absolute tolerance type, using a fixed value.
237
- relative : str
238
- Relative tolerance type, using a percentage.
239
-
240
- Examples
241
- --------
242
- >>> from nextmv.cloud import ToleranceType
243
- >>> tol_type = ToleranceType.absolute
244
- >>> tol_type
245
- <ToleranceType.absolute: 'absolute'>
246
- """
247
-
248
- undefined = ""
249
- """ToleranceType is deprecated, please use MetricToleranceType instead.
250
- Undefined tolerance type."""
251
- absolute = "absolute"
252
- """ToleranceType is deprecated, please use MetricToleranceType instead.
253
- Absolute tolerance type."""
254
- relative = "relative"
255
- """ToleranceType is deprecated, please use MetricToleranceType instead.
256
- Relative tolerance type."""
257
-
258
-
259
- # Override __getattribute__ to emit deprecation warnings when enum values are accessed
260
- _original_getattribute = ToleranceType.__class__.__getattribute__
261
-
262
-
263
- def _deprecated_getattribute(cls, name: str):
264
- # Only emit deprecation warning if this is specifically the ToleranceType class
265
- if cls is ToleranceType and name in ("undefined", "absolute", "relative"):
266
- deprecated(
267
- f"ToleranceType.{name}",
268
- "ToleranceType is deprecated and will be removed in a future version. "
269
- "Please use MetricToleranceType instead",
270
- )
271
-
272
- return _original_getattribute(cls, name)
273
-
274
-
275
- ToleranceType.__class__.__getattribute__ = _deprecated_getattribute
276
-
277
-
278
214
  class MetricToleranceType(str, Enum):
279
215
  """
280
216
  Type of tolerance used for a metric.
nextmv/cloud/account.py CHANGED
@@ -21,7 +21,7 @@ from pydantic import AliasChoices, Field
21
21
 
22
22
  from nextmv.base_model import BaseModel
23
23
  from nextmv.cloud.client import Client
24
- from nextmv.status import Status, StatusV2
24
+ from nextmv.status import StatusV2
25
25
 
26
26
 
27
27
  class QueuedRun(BaseModel):
@@ -57,8 +57,6 @@ class QueuedRun(BaseModel):
57
57
  ID of the application version used for the run.
58
58
  execution_class : str
59
59
  Execution class used for the run.
60
- status : Status
61
- Deprecated: use status_v2.
62
60
  status_v2 : StatusV2
63
61
  Status of the run.
64
62
 
@@ -74,7 +72,6 @@ class QueuedRun(BaseModel):
74
72
  ... "application_instance_id": "appins-123456",
75
73
  ... "application_version_id": "appver-123456",
76
74
  ... "execution_class": "standard",
77
- ... "status": "RUNNING",
78
75
  ... "status_v2": "RUNNING"
79
76
  ... })
80
77
  >>> print(queued_run.name)
@@ -99,8 +96,6 @@ class QueuedRun(BaseModel):
99
96
  """ID of the application version used for the run."""
100
97
  execution_class: str
101
98
  """Execution class used for the run."""
102
- status: Status
103
- """Deprecated: use status_v2."""
104
99
  status_v2: StatusV2
105
100
  """Status of the run."""
106
101