anyscale 0.26.31__py3-none-any.whl → 0.26.33__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.
- anyscale/_private/anyscale_client/anyscale_client.py +15 -0
- anyscale/_private/anyscale_client/common.py +12 -1
- anyscale/_private/anyscale_client/fake_anyscale_client.py +24 -0
- anyscale/_private/docgen/__main__.py +2 -0
- anyscale/_private/docgen/models.md +2 -2
- anyscale/api.py +22 -0
- anyscale/aws_iam_policies.py +0 -3
- anyscale/client/README.md +22 -1
- anyscale/client/openapi_client/__init__.py +17 -0
- anyscale/client/openapi_client/api/default_api.py +611 -157
- anyscale/client/openapi_client/models/__init__.py +17 -0
- anyscale/client/openapi_client/models/baseimagesenum.py +68 -1
- anyscale/client/openapi_client/models/cli_usage_payload.py +440 -0
- anyscale/client/openapi_client/models/cluster_operation.py +266 -0
- anyscale/client/openapi_client/models/cluster_operation_type.py +101 -0
- anyscale/client/openapi_client/models/clusteroperation_response.py +121 -0
- anyscale/client/openapi_client/models/commit_ledger_item_type.py +111 -0
- anyscale/client/openapi_client/models/commit_ledger_record_v2.py +207 -0
- anyscale/client/openapi_client/models/complexity_level.py +101 -0
- anyscale/client/openapi_client/models/credit_grant_record_v2.py +181 -0
- anyscale/client/openapi_client/models/credit_ledger_item_type.py +104 -0
- anyscale/client/openapi_client/models/credit_ledger_record_v2.py +207 -0
- anyscale/client/openapi_client/models/credit_record_commit_v2.py +410 -0
- anyscale/client/openapi_client/models/credit_record_credit_v2.py +410 -0
- anyscale/client/openapi_client/models/credit_type.py +100 -0
- anyscale/client/openapi_client/models/credits_v2.py +355 -0
- anyscale/client/openapi_client/models/operation_error.py +123 -0
- anyscale/client/openapi_client/models/operation_progress.py +123 -0
- anyscale/client/openapi_client/models/operation_result.py +150 -0
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +68 -1
- anyscale/client/openapi_client/models/workspace_template.py +115 -3
- anyscale/client/openapi_client/models/workspace_template_readme.py +59 -3
- anyscale/cloud/__init__.py +16 -0
- anyscale/cloud/_private/cloud_sdk.py +33 -0
- anyscale/cloud/commands.py +35 -0
- anyscale/commands/cloud_commands.py +35 -0
- anyscale/commands/command_examples.py +6 -0
- anyscale/commands/list_util.py +100 -38
- anyscale/integrations.py +0 -20
- anyscale/scripts.py +1 -0
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +68 -1
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +68 -1
- anyscale/shared_anyscale_utils/headers.py +4 -0
- anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
- anyscale/telemetry.py +424 -0
- anyscale/version.py +1 -1
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/METADATA +1 -1
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/RECORD +53 -35
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/LICENSE +0 -0
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/NOTICE +0 -0
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/WHEEL +0 -0
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.31.dist-info → anyscale-0.26.33.dist-info}/top_level.txt +0 -0
@@ -35,16 +35,20 @@ class WorkspaceTemplateReadme(object):
|
|
35
35
|
openapi_types = {
|
36
36
|
'content': 'str',
|
37
37
|
'title': 'str',
|
38
|
-
'description': 'str'
|
38
|
+
'description': 'str',
|
39
|
+
'icon_type': 'str',
|
40
|
+
'icon_bg_color': 'str'
|
39
41
|
}
|
40
42
|
|
41
43
|
attribute_map = {
|
42
44
|
'content': 'content',
|
43
45
|
'title': 'title',
|
44
|
-
'description': 'description'
|
46
|
+
'description': 'description',
|
47
|
+
'icon_type': 'icon_type',
|
48
|
+
'icon_bg_color': 'icon_bg_color'
|
45
49
|
}
|
46
50
|
|
47
|
-
def __init__(self, content=None, title=None, description=None, local_vars_configuration=None): # noqa: E501
|
51
|
+
def __init__(self, content=None, title=None, description=None, icon_type=None, icon_bg_color=None, local_vars_configuration=None): # noqa: E501
|
48
52
|
"""WorkspaceTemplateReadme - a model defined in OpenAPI""" # noqa: E501
|
49
53
|
if local_vars_configuration is None:
|
50
54
|
local_vars_configuration = Configuration()
|
@@ -53,11 +57,17 @@ class WorkspaceTemplateReadme(object):
|
|
53
57
|
self._content = None
|
54
58
|
self._title = None
|
55
59
|
self._description = None
|
60
|
+
self._icon_type = None
|
61
|
+
self._icon_bg_color = None
|
56
62
|
self.discriminator = None
|
57
63
|
|
58
64
|
self.content = content
|
59
65
|
self.title = title
|
60
66
|
self.description = description
|
67
|
+
if icon_type is not None:
|
68
|
+
self.icon_type = icon_type
|
69
|
+
if icon_bg_color is not None:
|
70
|
+
self.icon_bg_color = icon_bg_color
|
61
71
|
|
62
72
|
@property
|
63
73
|
def content(self):
|
@@ -134,6 +144,52 @@ class WorkspaceTemplateReadme(object):
|
|
134
144
|
|
135
145
|
self._description = description
|
136
146
|
|
147
|
+
@property
|
148
|
+
def icon_type(self):
|
149
|
+
"""Gets the icon_type of this WorkspaceTemplateReadme. # noqa: E501
|
150
|
+
|
151
|
+
The remix icon name of the icon for the workspace template # noqa: E501
|
152
|
+
|
153
|
+
:return: The icon_type of this WorkspaceTemplateReadme. # noqa: E501
|
154
|
+
:rtype: str
|
155
|
+
"""
|
156
|
+
return self._icon_type
|
157
|
+
|
158
|
+
@icon_type.setter
|
159
|
+
def icon_type(self, icon_type):
|
160
|
+
"""Sets the icon_type of this WorkspaceTemplateReadme.
|
161
|
+
|
162
|
+
The remix icon name of the icon for the workspace template # noqa: E501
|
163
|
+
|
164
|
+
:param icon_type: The icon_type of this WorkspaceTemplateReadme. # noqa: E501
|
165
|
+
:type: str
|
166
|
+
"""
|
167
|
+
|
168
|
+
self._icon_type = icon_type
|
169
|
+
|
170
|
+
@property
|
171
|
+
def icon_bg_color(self):
|
172
|
+
"""Gets the icon_bg_color of this WorkspaceTemplateReadme. # noqa: E501
|
173
|
+
|
174
|
+
The background color of the icon for the workspace template # noqa: E501
|
175
|
+
|
176
|
+
:return: The icon_bg_color of this WorkspaceTemplateReadme. # noqa: E501
|
177
|
+
:rtype: str
|
178
|
+
"""
|
179
|
+
return self._icon_bg_color
|
180
|
+
|
181
|
+
@icon_bg_color.setter
|
182
|
+
def icon_bg_color(self, icon_bg_color):
|
183
|
+
"""Sets the icon_bg_color of this WorkspaceTemplateReadme.
|
184
|
+
|
185
|
+
The background color of the icon for the workspace template # noqa: E501
|
186
|
+
|
187
|
+
:param icon_bg_color: The icon_bg_color of this WorkspaceTemplateReadme. # noqa: E501
|
188
|
+
:type: str
|
189
|
+
"""
|
190
|
+
|
191
|
+
self._icon_bg_color = icon_bg_color
|
192
|
+
|
137
193
|
def to_dict(self):
|
138
194
|
"""Returns the model properties as a dict"""
|
139
195
|
result = {}
|
anyscale/cloud/__init__.py
CHANGED
@@ -14,9 +14,12 @@ from anyscale.cloud.commands import (
|
|
14
14
|
_GET_ARG_DOCSTRINGS,
|
15
15
|
_GET_DEFAULT_EXAMPLE,
|
16
16
|
_GET_EXAMPLE,
|
17
|
+
_TERMINATE_SYSTEM_CLUSTER_ARG_DOCSTRINGS,
|
18
|
+
_TERMINATE_SYSTEM_CLUSTER_EXAMPLE,
|
17
19
|
add_collaborators,
|
18
20
|
get,
|
19
21
|
get_default,
|
22
|
+
terminate_system_cluster,
|
20
23
|
)
|
21
24
|
from anyscale.cloud.models import Cloud, CreateCloudCollaborator
|
22
25
|
from anyscale.connect import ClientBuilder
|
@@ -73,6 +76,18 @@ class CloudSDK:
|
|
73
76
|
"""
|
74
77
|
return self._private_sdk.get_default()
|
75
78
|
|
79
|
+
@sdk_docs(
|
80
|
+
doc_py_example=_TERMINATE_SYSTEM_CLUSTER_EXAMPLE,
|
81
|
+
arg_docstrings=_TERMINATE_SYSTEM_CLUSTER_ARG_DOCSTRINGS,
|
82
|
+
)
|
83
|
+
def terminate_system_cluster(self, cloud_id: str, wait: bool = False) -> str:
|
84
|
+
"""
|
85
|
+
Terminate the system cluster for a given cloud.
|
86
|
+
|
87
|
+
:return: ID of the terminated system cluster.
|
88
|
+
"""
|
89
|
+
return self._private_sdk.terminate_system_cluster(cloud_id, wait)
|
90
|
+
|
76
91
|
|
77
92
|
# Note: indentation here matches that of connect.py::ClientBuilder.
|
78
93
|
BUILDER_HELP_FOOTER = """
|
@@ -94,6 +109,7 @@ class CloudModule(ModuleType):
|
|
94
109
|
self.add_collaborators = add_collaborators
|
95
110
|
self.get = get
|
96
111
|
self.get_default = get_default
|
112
|
+
self.terminate_system_cluster = terminate_system_cluster
|
97
113
|
|
98
114
|
# Expose Anyscale connect
|
99
115
|
self.new_builder = self._new_builder()
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import List, Optional
|
2
2
|
|
3
3
|
from anyscale._private.sdk.base_sdk import BaseSDK
|
4
|
+
from anyscale.cli_logger import BlockLogger
|
4
5
|
from anyscale.client.openapi_client.models import (
|
5
6
|
Cloud as CloudModel,
|
6
7
|
CreateCloudCollaborator as CreateCloudCollaboratorModel,
|
@@ -11,6 +12,10 @@ from anyscale.cloud.models import (
|
|
11
12
|
ComputeStack,
|
12
13
|
CreateCloudCollaborator,
|
13
14
|
)
|
15
|
+
from anyscale.sdk.anyscale_client.models import ClusterState
|
16
|
+
|
17
|
+
|
18
|
+
logger = BlockLogger()
|
14
19
|
|
15
20
|
|
16
21
|
class PrivateCloudSDK(BaseSDK):
|
@@ -80,3 +85,31 @@ class PrivateCloudSDK(BaseSDK):
|
|
80
85
|
is_default=openapi_cloud.is_default,
|
81
86
|
compute_stack=compute_stack,
|
82
87
|
)
|
88
|
+
|
89
|
+
def terminate_system_cluster(self, cloud_id: str, wait: bool) -> str:
|
90
|
+
resp = self.client.terminate_system_cluster(cloud_id)
|
91
|
+
if wait:
|
92
|
+
self._wait_for_system_cluster_status(cloud_id, ClusterState.TERMINATED)
|
93
|
+
else:
|
94
|
+
logger.info(f"System cluster termination initiated for cloud {cloud_id}.")
|
95
|
+
return resp.result.cluster_id
|
96
|
+
|
97
|
+
def _wait_for_system_cluster_status(
|
98
|
+
self,
|
99
|
+
cloud_id: str,
|
100
|
+
goal_status: str,
|
101
|
+
timeout_s: int = 500,
|
102
|
+
interval_s: int = 10,
|
103
|
+
) -> bool:
|
104
|
+
self.logger.info("Waiting for system cluster termination...", end="")
|
105
|
+
for _ in self.timer.poll(timeout_s=timeout_s, interval_s=interval_s):
|
106
|
+
status = self.client.describe_system_workload_get_status(cloud_id)
|
107
|
+
if status == goal_status:
|
108
|
+
print(".")
|
109
|
+
self.logger.info(f"System cluster for cloud '{cloud_id}' is {status}.")
|
110
|
+
return True
|
111
|
+
else:
|
112
|
+
print(".", end="")
|
113
|
+
raise TimeoutError(
|
114
|
+
f"Timed out waiting for system cluster termination for cloud '{cloud_id}'. Last seen status: {status}."
|
115
|
+
)
|
anyscale/cloud/commands.py
CHANGED
@@ -114,3 +114,38 @@ def get_default(*, _private_sdk: Optional[PrivateCloudSDK] = None) -> Optional[C
|
|
114
114
|
:return: The default `Cloud` object if it exists, otherwise `None`.
|
115
115
|
"""
|
116
116
|
return _private_sdk.get_default() # type: ignore
|
117
|
+
|
118
|
+
|
119
|
+
_TERMINATE_SYSTEM_CLUSTER_EXAMPLE = """
|
120
|
+
import anyscale
|
121
|
+
|
122
|
+
# Terminate the system cluster for the cloud with the specified ID
|
123
|
+
anyscale.cloud.terminate_system_cluster(cloud_id="cloud_id", wait=True)
|
124
|
+
"""
|
125
|
+
|
126
|
+
_TERMINATE_SYSTEM_CLUSTER_ARG_DOCSTRINGS = {
|
127
|
+
"cloud_id": "The ID of the cloud whose system cluster should be terminated.",
|
128
|
+
"wait": "If True, wait for the system cluster to be terminated before returning. Defaults to False.",
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
@sdk_command(
|
133
|
+
_CLOUD_SDK_SINGLETON_KEY,
|
134
|
+
PrivateCloudSDK,
|
135
|
+
doc_py_example=_TERMINATE_SYSTEM_CLUSTER_EXAMPLE,
|
136
|
+
arg_docstrings=_TERMINATE_SYSTEM_CLUSTER_ARG_DOCSTRINGS,
|
137
|
+
)
|
138
|
+
def terminate_system_cluster(
|
139
|
+
cloud_id: str,
|
140
|
+
wait: Optional[bool] = False,
|
141
|
+
*,
|
142
|
+
_private_sdk: Optional[PrivateCloudSDK] = None,
|
143
|
+
) -> str:
|
144
|
+
"""
|
145
|
+
Terminate the system cluster for the specified cloud.
|
146
|
+
|
147
|
+
:param cloud: The name of the cloud whose system cluster should be terminated.
|
148
|
+
:param wait: If True, wait for the system cluster to be terminated before returning. Defaults to False.
|
149
|
+
:return: ID of the terminated system cluster.
|
150
|
+
"""
|
151
|
+
return _private_sdk.terminate_system_cluster(cloud_id, wait) # type: ignore
|
@@ -1269,3 +1269,38 @@ def generate_jobs_report(
|
|
1269
1269
|
)
|
1270
1270
|
except ValueError as e:
|
1271
1271
|
log.error(f"Error generating jobs report: {e}")
|
1272
|
+
|
1273
|
+
|
1274
|
+
@cloud_cli.command(
|
1275
|
+
name="terminate-system-cluster",
|
1276
|
+
help="Terminate the system cluster for a specific given cloud.",
|
1277
|
+
cls=AnyscaleCommand,
|
1278
|
+
example=command_examples.CLOUD_TERMINATE_SYSTEM_CLUSTER_EXAMPLE,
|
1279
|
+
)
|
1280
|
+
@click.option(
|
1281
|
+
"--cloud-id",
|
1282
|
+
"--id",
|
1283
|
+
help="ID of the cloud to terminate the system cluster for.",
|
1284
|
+
type=str,
|
1285
|
+
required=True,
|
1286
|
+
)
|
1287
|
+
@click.option(
|
1288
|
+
"-w",
|
1289
|
+
"--wait",
|
1290
|
+
required=False,
|
1291
|
+
default=False,
|
1292
|
+
type=bool,
|
1293
|
+
is_flag=True,
|
1294
|
+
help="Block this CLI command and print logs until the job finishes.",
|
1295
|
+
)
|
1296
|
+
def terminate_system_cluster(cloud_id: str, wait: Optional[bool]) -> None:
|
1297
|
+
"""
|
1298
|
+
Terminate the system cluster for a specific cloud.
|
1299
|
+
|
1300
|
+
:param cloud_id: The ID of the cloud to terminate the system cluster for.
|
1301
|
+
:param wait: If True, wait for the system cluster to be terminated before returning. Defaults to False.
|
1302
|
+
"""
|
1303
|
+
try:
|
1304
|
+
anyscale.cloud.terminate_system_cluster(cloud_id, wait)
|
1305
|
+
except ValueError as e:
|
1306
|
+
log.error(f"Error terminating system cluster: {e}")
|
@@ -673,6 +673,12 @@ is_default: true
|
|
673
673
|
compute_stack: VM
|
674
674
|
"""
|
675
675
|
|
676
|
+
CLOUD_TERMINATE_SYSTEM_CLUSTER_EXAMPLE = """\
|
677
|
+
$ anyscale cloud terminate-system-cluster --cloud-id cloud_id --wait
|
678
|
+
(anyscale +1.3s) Waiting for system cluster termination............
|
679
|
+
(anyscale +1m22.9s) System cluster for cloud 'cloud_id' is Terminated.
|
680
|
+
"""
|
681
|
+
|
676
682
|
SERVICE_ARCHIVE_EXAMPLE = """\
|
677
683
|
$ anyscale service archive --name my_service
|
678
684
|
"""
|
anyscale/commands/list_util.py
CHANGED
@@ -32,7 +32,47 @@ def _paginate(iterator: Iterator[Any], page_size: Optional[int]) -> Iterator[Lis
|
|
32
32
|
yield page
|
33
33
|
|
34
34
|
|
35
|
-
def
|
35
|
+
def _render_page(
|
36
|
+
page: List[Any],
|
37
|
+
item_formatter: Callable[[Any], Dict[str, Any]],
|
38
|
+
table_creator: Callable[[bool], Table],
|
39
|
+
json_output: bool,
|
40
|
+
is_first: bool,
|
41
|
+
page_num: int,
|
42
|
+
console: Console,
|
43
|
+
) -> int:
|
44
|
+
"""Render a single page of items."""
|
45
|
+
if page_num > 1: # Only show page number for pages after first
|
46
|
+
console.print(f"[dim]Page {page_num}[/dim]")
|
47
|
+
|
48
|
+
rows = [item_formatter(item) for item in page]
|
49
|
+
if json_output:
|
50
|
+
json_str = json_dumps(rows, indent=2, cls=AnyscaleJSONEncoder)
|
51
|
+
console.print_json(json=json_str)
|
52
|
+
else:
|
53
|
+
tbl = table_creator(is_first)
|
54
|
+
for row in rows:
|
55
|
+
tbl.add_row(*row.values())
|
56
|
+
console.print(tbl)
|
57
|
+
|
58
|
+
return len(page)
|
59
|
+
|
60
|
+
|
61
|
+
def _should_continue_pagination(
|
62
|
+
page_size: int, current_page_size: int, console: Console
|
63
|
+
) -> bool:
|
64
|
+
"""Prompt user to continue pagination if needed."""
|
65
|
+
if current_page_size < page_size:
|
66
|
+
return False # Last page, no need to prompt
|
67
|
+
|
68
|
+
console.print()
|
69
|
+
console.print(
|
70
|
+
"[dim]Press [bold]Enter[/bold] to continue, [bold]q[/bold] to quit…[/]"
|
71
|
+
)
|
72
|
+
return input("> ").strip().lower() != "q"
|
73
|
+
|
74
|
+
|
75
|
+
def display_list( # noqa: PLR0913, PLR0912
|
36
76
|
iterator: Iterator[Any],
|
37
77
|
item_formatter: Callable[[Any], Dict[str, Any]],
|
38
78
|
table_creator: Callable[[bool], Table],
|
@@ -65,56 +105,78 @@ def display_list( # noqa: PLR0913
|
|
65
105
|
total_count = 0
|
66
106
|
pages = _paginate(iterator, page_size if interactive else max_items)
|
67
107
|
|
68
|
-
#
|
108
|
+
# Start interactive session if needed
|
109
|
+
if interactive:
|
110
|
+
try:
|
111
|
+
from anyscale.telemetry import start_interactive_session
|
112
|
+
|
113
|
+
start_interactive_session()
|
114
|
+
except Exception: # noqa: BLE001
|
115
|
+
pass
|
116
|
+
|
117
|
+
# Fetch and render first page
|
69
118
|
with console.status("Retrieving items…", spinner="dots"):
|
70
119
|
try:
|
71
120
|
first_page = next(pages)
|
72
121
|
except StopIteration:
|
73
122
|
first_page = []
|
74
123
|
|
75
|
-
def _render(page: List[Any], is_first: bool, page_num: int):
|
76
|
-
nonlocal total_count
|
77
|
-
total_count += len(page)
|
78
|
-
if interactive:
|
79
|
-
console.print(f"[dim]Page {page_num}[/dim]")
|
80
|
-
rows = [item_formatter(item) for item in page]
|
81
|
-
if json_output:
|
82
|
-
json_str = json_dumps(rows, indent=2, cls=AnyscaleJSONEncoder)
|
83
|
-
console.print_json(json=json_str)
|
84
|
-
else:
|
85
|
-
tbl = table_creator(is_first)
|
86
|
-
for row in rows:
|
87
|
-
tbl.add_row(*row.values())
|
88
|
-
console.print(tbl)
|
89
|
-
|
90
|
-
# render first page
|
91
124
|
if first_page:
|
92
|
-
|
125
|
+
total_count += _render_page(
|
126
|
+
first_page, item_formatter, table_creator, json_output, True, 1, console
|
127
|
+
)
|
93
128
|
|
94
|
-
#
|
129
|
+
# For interactive commands, mark when command logic completes
|
130
|
+
if interactive:
|
131
|
+
try:
|
132
|
+
from anyscale.telemetry import mark_command_complete
|
133
|
+
|
134
|
+
mark_command_complete()
|
135
|
+
except Exception: # noqa: BLE001
|
136
|
+
pass
|
137
|
+
|
138
|
+
# Non-interactive: stop after first page
|
95
139
|
if not interactive:
|
96
140
|
return total_count
|
97
141
|
|
98
|
-
#
|
99
|
-
if len(first_page)
|
100
|
-
|
101
|
-
console.print(
|
102
|
-
"[dim]Press [bold]Enter[/bold] to continue, [bold]q[/bold] to quit…[/]"
|
103
|
-
)
|
104
|
-
if input("> ").strip().lower() == "q":
|
105
|
-
return total_count
|
142
|
+
# Interactive: check if user wants to continue
|
143
|
+
if not _should_continue_pagination(page_size, len(first_page), console):
|
144
|
+
return total_count
|
106
145
|
|
107
|
-
#
|
146
|
+
# Render remaining pages with correct telemetry timing
|
108
147
|
page_num = 2
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
148
|
+
while True:
|
149
|
+
# Start page fetch timing and generate new trace ID BEFORE fetching
|
150
|
+
try:
|
151
|
+
from anyscale.telemetry import mark_page_fetch_start
|
152
|
+
|
153
|
+
mark_page_fetch_start(page_num)
|
154
|
+
except Exception: # noqa: BLE001
|
155
|
+
pass
|
156
|
+
|
157
|
+
# Now fetch the page (with the new trace ID)
|
158
|
+
try:
|
159
|
+
page = next(pages)
|
160
|
+
except StopIteration:
|
161
|
+
break
|
162
|
+
|
163
|
+
# Render the page
|
164
|
+
total_count += _render_page(
|
165
|
+
page, item_formatter, table_creator, json_output, False, page_num, console
|
166
|
+
)
|
167
|
+
|
168
|
+
# Complete page fetch telemetry
|
169
|
+
try:
|
170
|
+
from anyscale.telemetry import mark_page_fetch_complete
|
171
|
+
|
172
|
+
mark_page_fetch_complete(page_num)
|
173
|
+
except Exception: # noqa: BLE001
|
174
|
+
pass
|
175
|
+
|
176
|
+
# Check if user wants to continue or if this was the last page
|
177
|
+
if not _should_continue_pagination(page_size, len(page), console):
|
178
|
+
break
|
179
|
+
|
118
180
|
page_num += 1
|
119
181
|
|
120
182
|
return total_count
|
anyscale/integrations.py
CHANGED
@@ -20,8 +20,6 @@ WANDB_API_KEY_NAME = "WANDB_API_KEY_NAME" # pragma: allowlist secret
|
|
20
20
|
WANDB_PROJECT_NAME = "WANDB_PROJECT_NAME"
|
21
21
|
WANDB_GROUP_NAME = "WANDB_GROUP_NAME"
|
22
22
|
|
23
|
-
FLAG_WANDB_INTEGRATION_PROTOTYPE = "wandb-integration-prototype"
|
24
|
-
|
25
23
|
log = BlockLogger() # Anyscale CLI Logger
|
26
24
|
|
27
25
|
|
@@ -131,13 +129,6 @@ def wandb_setup_api_key_hook() -> Optional[str]:
|
|
131
129
|
be called by the OSS WandbLoggerCallback. Because this is called
|
132
130
|
before wandb.init(), any other setup can also be done here.
|
133
131
|
"""
|
134
|
-
api_client = get_auth_api_client(log_output=False).api_client
|
135
|
-
feature_flag_on = api_client.check_is_feature_flag_on_api_v2_userinfo_check_is_feature_flag_on_get(
|
136
|
-
FLAG_WANDB_INTEGRATION_PROTOTYPE
|
137
|
-
).result.is_on
|
138
|
-
if not feature_flag_on:
|
139
|
-
return None
|
140
|
-
|
141
132
|
protected_api_key = wandb_get_api_key()
|
142
133
|
|
143
134
|
try:
|
@@ -171,11 +162,6 @@ def set_wandb_project_group_env_vars():
|
|
171
162
|
for production jobs, workspaces, and Ray jobs.
|
172
163
|
"""
|
173
164
|
api_client = get_auth_api_client(log_output=False).api_client
|
174
|
-
feature_flag_on = api_client.check_is_feature_flag_on_api_v2_userinfo_check_is_feature_flag_on_get(
|
175
|
-
FLAG_WANDB_INTEGRATION_PROTOTYPE
|
176
|
-
).result.is_on
|
177
|
-
if not feature_flag_on:
|
178
|
-
return
|
179
165
|
|
180
166
|
wandb_project_default = None
|
181
167
|
wandb_group_default = None
|
@@ -224,12 +210,6 @@ def wandb_send_run_info_hook(run: Any) -> None:
|
|
224
210
|
api_client = auth_api_client.api_client
|
225
211
|
anyscale_api_client = auth_api_client.anyscale_api_client
|
226
212
|
|
227
|
-
feature_flag_on = api_client.check_is_feature_flag_on_api_v2_userinfo_check_is_feature_flag_on_get(
|
228
|
-
FLAG_WANDB_INTEGRATION_PROTOTYPE
|
229
|
-
).result.is_on
|
230
|
-
if not feature_flag_on:
|
231
|
-
return
|
232
|
-
|
233
213
|
try:
|
234
214
|
import wandb
|
235
215
|
except ImportError:
|
anyscale/scripts.py
CHANGED
@@ -43,6 +43,7 @@ from anyscale.commands.user_commands import user_cli
|
|
43
43
|
from anyscale.commands.workspace_commands import workspace_cli
|
44
44
|
from anyscale.commands.workspace_commands_v2 import workspace_cli as workspace_cli_v2
|
45
45
|
import anyscale.conf
|
46
|
+
import anyscale.telemetry # IMPORTANT: auto-patches click instrumentation on import
|
46
47
|
from anyscale.utils.cli_version_check_util import log_warning_if_version_needs_upgrade
|
47
48
|
|
48
49
|
|