anyscale 0.26.21__py3-none-any.whl → 0.26.23__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 +103 -43
- anyscale/_private/anyscale_client/common.py +38 -8
- anyscale/_private/anyscale_client/fake_anyscale_client.py +98 -27
- anyscale/_private/docgen/models.md +2 -2
- anyscale/_private/models/model_base.py +95 -0
- anyscale/_private/workload/workload_sdk.py +3 -1
- anyscale/aggregated_instance_usage/models.py +4 -4
- anyscale/client/README.md +1 -0
- anyscale/client/openapi_client/api/default_api.py +122 -1
- anyscale/client/openapi_client/models/baseimagesenum.py +68 -1
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +68 -1
- anyscale/commands/command_examples.py +4 -0
- anyscale/commands/list_util.py +107 -0
- anyscale/commands/service_commands.py +267 -31
- anyscale/commands/util.py +5 -4
- anyscale/controllers/service_controller.py +7 -86
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +68 -1
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +68 -1
- anyscale/service/__init__.py +53 -3
- anyscale/service/_private/service_sdk.py +177 -41
- anyscale/service/commands.py +78 -1
- anyscale/service/models.py +65 -0
- anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
- anyscale/util.py +35 -1
- anyscale/version.py +1 -1
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/METADATA +1 -1
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/RECORD +32 -31
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/LICENSE +0 -0
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/NOTICE +0 -0
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/WHEEL +0 -0
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.21.dist-info → anyscale-0.26.23.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,13 @@
|
|
1
|
+
import asyncio
|
2
|
+
from collections import deque
|
1
3
|
from dataclasses import asdict, fields
|
2
4
|
from enum import Enum, EnumMeta
|
3
5
|
import inspect
|
4
6
|
from typing import (
|
5
7
|
Any,
|
8
|
+
Awaitable,
|
6
9
|
Callable,
|
10
|
+
Deque,
|
7
11
|
Dict,
|
8
12
|
Generic,
|
9
13
|
Iterable,
|
@@ -252,3 +256,94 @@ class ListResponse(List[TModelBase]):
|
|
252
256
|
return
|
253
257
|
if index >= len(self) and self.has_more:
|
254
258
|
self._fetch_next_page()
|
259
|
+
|
260
|
+
|
261
|
+
RT = TypeVar("RT")
|
262
|
+
|
263
|
+
|
264
|
+
class ResultIterator(Generic[RT]):
|
265
|
+
"""
|
266
|
+
Lazily fetch and parse pages from a paged-list API that returns
|
267
|
+
Pydantic models with `.results` and `.metadata.next_paging_token`.
|
268
|
+
"""
|
269
|
+
|
270
|
+
def __init__(
|
271
|
+
self,
|
272
|
+
*,
|
273
|
+
page_token: Optional[str],
|
274
|
+
max_items: Optional[int],
|
275
|
+
fetch_page: Callable[[Optional[str]], Any],
|
276
|
+
parse_fn: Optional[Callable[[Any], RT]] = None,
|
277
|
+
async_parse_fn: Optional[Callable[[Any], Awaitable[RT]]] = None,
|
278
|
+
):
|
279
|
+
if parse_fn and async_parse_fn:
|
280
|
+
raise ValueError("Only one of parse_fn or async_parse_fn may be provided")
|
281
|
+
|
282
|
+
self._token = page_token
|
283
|
+
self._max = max_items
|
284
|
+
self._fetch = fetch_page
|
285
|
+
self._parse = parse_fn
|
286
|
+
self._aparse = async_parse_fn
|
287
|
+
self._buffer: Deque[RT] = deque()
|
288
|
+
self._count = 0
|
289
|
+
self._finished = False
|
290
|
+
|
291
|
+
def __iter__(self) -> Iterator[RT]:
|
292
|
+
while True:
|
293
|
+
# 1) Drain the buffer
|
294
|
+
while self._buffer:
|
295
|
+
if self._max is not None and self._count >= self._max:
|
296
|
+
return
|
297
|
+
self._count += 1
|
298
|
+
yield self._buffer.popleft()
|
299
|
+
|
300
|
+
# 2) Done?
|
301
|
+
if self._finished or (self._max is not None and self._count >= self._max):
|
302
|
+
return
|
303
|
+
|
304
|
+
# 3) Fetch the next page (Pydantic model)
|
305
|
+
page = self._fetch(self._token)
|
306
|
+
raw_results = page.results
|
307
|
+
self._token = page.metadata.next_paging_token
|
308
|
+
|
309
|
+
# 4) No more data?
|
310
|
+
if not raw_results:
|
311
|
+
self._finished = True
|
312
|
+
return
|
313
|
+
|
314
|
+
# 5) Parse—sync or async
|
315
|
+
if self._aparse:
|
316
|
+
processed = asyncio.run(
|
317
|
+
ResultIterator._process_items_async(raw_results, self._aparse)
|
318
|
+
)
|
319
|
+
self._buffer.extend(processed)
|
320
|
+
|
321
|
+
elif self._parse:
|
322
|
+
try:
|
323
|
+
for raw in raw_results:
|
324
|
+
self._buffer.append(self._parse(raw))
|
325
|
+
except Exception as e: # noqa: BLE001
|
326
|
+
raise RuntimeError(f"sync parse error: {e}") from e
|
327
|
+
|
328
|
+
else:
|
329
|
+
# No parser: assume items are already RT
|
330
|
+
self._buffer.extend(raw_results) # type: ignore
|
331
|
+
|
332
|
+
# 6) If no next token, finish on next loop
|
333
|
+
if self._token is None:
|
334
|
+
self._finished = True
|
335
|
+
|
336
|
+
@staticmethod
|
337
|
+
async def _process_items_async(
|
338
|
+
items: List[Any], parser: Callable[[Any], Awaitable[RT]],
|
339
|
+
) -> List[RT]:
|
340
|
+
if not items:
|
341
|
+
return []
|
342
|
+
tasks = [parser(item) for item in items]
|
343
|
+
results = await asyncio.gather(*tasks, return_exceptions=True)
|
344
|
+
processed: List[RT] = []
|
345
|
+
for idx, res in enumerate(results):
|
346
|
+
if isinstance(res, Exception):
|
347
|
+
raise RuntimeError(f"async parse failed on item {idx}: {res}") from res
|
348
|
+
processed.append(res)
|
349
|
+
return processed
|
@@ -328,4 +328,6 @@ class WorkloadSDK(BaseSDK):
|
|
328
328
|
if not compute_config.anonymous:
|
329
329
|
return compute_config_name
|
330
330
|
|
331
|
-
return self._compute_config_sdk.
|
331
|
+
return self._compute_config_sdk._convert_api_model_to_compute_config_version( # noqa: SLF001
|
332
|
+
compute_config
|
333
|
+
).config
|
@@ -15,9 +15,9 @@ import anyscale
|
|
15
15
|
from anyscale.aggregated_instance_usage.models import DownloadCSVFilters
|
16
16
|
|
17
17
|
download_csv_filters = DownloadCSVFilters(
|
18
|
-
# Start date (inclusive) for the usage CSV.
|
18
|
+
# Start date (UTC inclusive) for the usage CSV.
|
19
19
|
start_date="2024-10-01",
|
20
|
-
# End date (inclusive) for the usage CSV.
|
20
|
+
# End date (UTC inclusive) for the usage CSV.
|
21
21
|
end_date="2024-10-31",
|
22
22
|
# Optional cloud name to filter by.
|
23
23
|
cloud="cloud_name",
|
@@ -39,14 +39,14 @@ download_csv_filters = DownloadCSVFilters(
|
|
39
39
|
raise ValueError("Incorrect date format, should be YYYY-MM-DD")
|
40
40
|
|
41
41
|
start_date: str = field(
|
42
|
-
metadata={"docstring": "Start date (inclusive) for the usage CSV."}
|
42
|
+
metadata={"docstring": "Start date (UTC inclusive) for the usage CSV."}
|
43
43
|
)
|
44
44
|
|
45
45
|
def _validate_start_date(self, start_date: str):
|
46
46
|
self._validate_date(start_date)
|
47
47
|
|
48
48
|
end_date: str = field(
|
49
|
-
metadata={"docstring": "End date (inclusive) for the usage CSV."}
|
49
|
+
metadata={"docstring": "End date (UTC inclusive) for the usage CSV."}
|
50
50
|
)
|
51
51
|
|
52
52
|
def _validate_end_date(self, end_date: str):
|
anyscale/client/README.md
CHANGED
@@ -294,6 +294,7 @@ Class | Method | HTTP request | Description
|
|
294
294
|
*DefaultApi* | [**list_project_collaborators_api_v2_projects_project_id_collaborators_users_get**](docs/DefaultApi.md#list_project_collaborators_api_v2_projects_project_id_collaborators_users_get) | **GET** /api/v2/projects/{project_id}/collaborators/users | List Project Collaborators
|
295
295
|
*DefaultApi* | [**list_projects_api_v2_projects_get**](docs/DefaultApi.md#list_projects_api_v2_projects_get) | **GET** /api/v2/projects/ | List Projects
|
296
296
|
*DefaultApi* | [**list_ray_sessions_api_v2_tasks_dashboard_list_ray_sessions_get**](docs/DefaultApi.md#list_ray_sessions_api_v2_tasks_dashboard_list_ray_sessions_get) | **GET** /api/v2/tasks_dashboard/list_ray_sessions | List Ray Sessions
|
297
|
+
*DefaultApi* | [**list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get**](docs/DefaultApi.md#list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get) | **GET** /api/v2/experimental_workspaces/templates/recommended | List Recommended Workspace Templates
|
297
298
|
*DefaultApi* | [**list_services_api_v2_services_v2_get**](docs/DefaultApi.md#list_services_api_v2_services_v2_get) | **GET** /api/v2/services-v2/ | List Services
|
298
299
|
*DefaultApi* | [**list_sessions_api_v2_sessions_get**](docs/DefaultApi.md#list_sessions_api_v2_sessions_get) | **GET** /api/v2/sessions/ | List Sessions
|
299
300
|
*DefaultApi* | [**list_workspace_templates_api_v2_experimental_workspaces_templates_get**](docs/DefaultApi.md#list_workspace_templates_api_v2_experimental_workspaces_templates_get) | **GET** /api/v2/experimental_workspaces/templates | List Workspace Templates
|
@@ -20980,6 +20980,7 @@ class DefaultApi(object):
|
|
20980
20980
|
|
20981
20981
|
:param async_req bool: execute request asynchronously
|
20982
20982
|
:param str cluster_id: (required)
|
20983
|
+
:param bool skip_job_details: Skip decorating job details, which can be an expensive operation.
|
20983
20984
|
:param _preload_content: if False, the urllib3.HTTPResponse object will
|
20984
20985
|
be returned without reading/decoding response
|
20985
20986
|
data. Default is True.
|
@@ -21004,6 +21005,7 @@ class DefaultApi(object):
|
|
21004
21005
|
|
21005
21006
|
:param async_req bool: execute request asynchronously
|
21006
21007
|
:param str cluster_id: (required)
|
21008
|
+
:param bool skip_job_details: Skip decorating job details, which can be an expensive operation.
|
21007
21009
|
:param _return_http_data_only: response data without head status code
|
21008
21010
|
and headers
|
21009
21011
|
:param _preload_content: if False, the urllib3.HTTPResponse object will
|
@@ -21021,7 +21023,8 @@ class DefaultApi(object):
|
|
21021
21023
|
local_var_params = locals()
|
21022
21024
|
|
21023
21025
|
all_params = [
|
21024
|
-
'cluster_id'
|
21026
|
+
'cluster_id',
|
21027
|
+
'skip_job_details'
|
21025
21028
|
]
|
21026
21029
|
all_params.extend(
|
21027
21030
|
[
|
@@ -21052,6 +21055,8 @@ class DefaultApi(object):
|
|
21052
21055
|
query_params = []
|
21053
21056
|
if 'cluster_id' in local_var_params and local_var_params['cluster_id'] is not None: # noqa: E501
|
21054
21057
|
query_params.append(('cluster_id', local_var_params['cluster_id'])) # noqa: E501
|
21058
|
+
if 'skip_job_details' in local_var_params and local_var_params['skip_job_details'] is not None: # noqa: E501
|
21059
|
+
query_params.append(('skip_job_details', local_var_params['skip_job_details'])) # noqa: E501
|
21055
21060
|
|
21056
21061
|
header_params = {}
|
21057
21062
|
|
@@ -26320,6 +26325,122 @@ class DefaultApi(object):
|
|
26320
26325
|
_request_timeout=local_var_params.get('_request_timeout'),
|
26321
26326
|
collection_formats=collection_formats)
|
26322
26327
|
|
26328
|
+
def list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get(self, **kwargs): # noqa: E501
|
26329
|
+
"""List Recommended Workspace Templates # noqa: E501
|
26330
|
+
|
26331
|
+
Lists all workspace templates ranked by user's organization marketing questions # noqa: E501
|
26332
|
+
This method makes a synchronous HTTP request by default. To make an
|
26333
|
+
asynchronous HTTP request, please pass async_req=True
|
26334
|
+
>>> thread = api.list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get(async_req=True)
|
26335
|
+
>>> result = thread.get()
|
26336
|
+
|
26337
|
+
:param async_req bool: execute request asynchronously
|
26338
|
+
:param int count: Maximum number of templates to return
|
26339
|
+
:param list[str] oa_group_names: Search for templates that belong to the provided group name
|
26340
|
+
:param _preload_content: if False, the urllib3.HTTPResponse object will
|
26341
|
+
be returned without reading/decoding response
|
26342
|
+
data. Default is True.
|
26343
|
+
:param _request_timeout: timeout setting for this request. If one
|
26344
|
+
number provided, it will be total request
|
26345
|
+
timeout. It can also be a pair (tuple) of
|
26346
|
+
(connection, read) timeouts.
|
26347
|
+
:return: WorkspacetemplateListResponse
|
26348
|
+
If the method is called asynchronously,
|
26349
|
+
returns the request thread.
|
26350
|
+
"""
|
26351
|
+
kwargs['_return_http_data_only'] = True
|
26352
|
+
return self.list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get_with_http_info(**kwargs) # noqa: E501
|
26353
|
+
|
26354
|
+
def list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get_with_http_info(self, **kwargs): # noqa: E501
|
26355
|
+
"""List Recommended Workspace Templates # noqa: E501
|
26356
|
+
|
26357
|
+
Lists all workspace templates ranked by user's organization marketing questions # noqa: E501
|
26358
|
+
This method makes a synchronous HTTP request by default. To make an
|
26359
|
+
asynchronous HTTP request, please pass async_req=True
|
26360
|
+
>>> thread = api.list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get_with_http_info(async_req=True)
|
26361
|
+
>>> result = thread.get()
|
26362
|
+
|
26363
|
+
:param async_req bool: execute request asynchronously
|
26364
|
+
:param int count: Maximum number of templates to return
|
26365
|
+
:param list[str] oa_group_names: Search for templates that belong to the provided group name
|
26366
|
+
:param _return_http_data_only: response data without head status code
|
26367
|
+
and headers
|
26368
|
+
:param _preload_content: if False, the urllib3.HTTPResponse object will
|
26369
|
+
be returned without reading/decoding response
|
26370
|
+
data. Default is True.
|
26371
|
+
:param _request_timeout: timeout setting for this request. If one
|
26372
|
+
number provided, it will be total request
|
26373
|
+
timeout. It can also be a pair (tuple) of
|
26374
|
+
(connection, read) timeouts.
|
26375
|
+
:return: tuple(WorkspacetemplateListResponse, status_code(int), headers(HTTPHeaderDict))
|
26376
|
+
If the method is called asynchronously,
|
26377
|
+
returns the request thread.
|
26378
|
+
"""
|
26379
|
+
|
26380
|
+
local_var_params = locals()
|
26381
|
+
|
26382
|
+
all_params = [
|
26383
|
+
'count',
|
26384
|
+
'oa_group_names'
|
26385
|
+
]
|
26386
|
+
all_params.extend(
|
26387
|
+
[
|
26388
|
+
'async_req',
|
26389
|
+
'_return_http_data_only',
|
26390
|
+
'_preload_content',
|
26391
|
+
'_request_timeout'
|
26392
|
+
]
|
26393
|
+
)
|
26394
|
+
|
26395
|
+
for key, val in six.iteritems(local_var_params['kwargs']):
|
26396
|
+
if key not in all_params:
|
26397
|
+
raise ApiTypeError(
|
26398
|
+
"Got an unexpected keyword argument '%s'"
|
26399
|
+
" to method list_recommended_workspace_templates_api_v2_experimental_workspaces_templates_recommended_get" % key
|
26400
|
+
)
|
26401
|
+
local_var_params[key] = val
|
26402
|
+
del local_var_params['kwargs']
|
26403
|
+
|
26404
|
+
collection_formats = {}
|
26405
|
+
|
26406
|
+
path_params = {}
|
26407
|
+
|
26408
|
+
query_params = []
|
26409
|
+
if 'count' in local_var_params and local_var_params['count'] is not None: # noqa: E501
|
26410
|
+
query_params.append(('count', local_var_params['count'])) # noqa: E501
|
26411
|
+
if 'oa_group_names' in local_var_params and local_var_params['oa_group_names'] is not None: # noqa: E501
|
26412
|
+
query_params.append(('oa_group_names', local_var_params['oa_group_names'])) # noqa: E501
|
26413
|
+
collection_formats['oa_group_names'] = 'multi' # noqa: E501
|
26414
|
+
|
26415
|
+
header_params = {}
|
26416
|
+
|
26417
|
+
form_params = []
|
26418
|
+
local_var_files = {}
|
26419
|
+
|
26420
|
+
body_params = None
|
26421
|
+
# HTTP header `Accept`
|
26422
|
+
header_params['Accept'] = self.api_client.select_header_accept(
|
26423
|
+
['application/json']) # noqa: E501
|
26424
|
+
|
26425
|
+
# Authentication setting
|
26426
|
+
auth_settings = [] # noqa: E501
|
26427
|
+
|
26428
|
+
return self.api_client.call_api(
|
26429
|
+
'/api/v2/experimental_workspaces/templates/recommended', 'GET',
|
26430
|
+
path_params,
|
26431
|
+
query_params,
|
26432
|
+
header_params,
|
26433
|
+
body=body_params,
|
26434
|
+
post_params=form_params,
|
26435
|
+
files=local_var_files,
|
26436
|
+
response_type='WorkspacetemplateListResponse', # noqa: E501
|
26437
|
+
auth_settings=auth_settings,
|
26438
|
+
async_req=local_var_params.get('async_req'),
|
26439
|
+
_return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501
|
26440
|
+
_preload_content=local_var_params.get('_preload_content', True),
|
26441
|
+
_request_timeout=local_var_params.get('_request_timeout'),
|
26442
|
+
collection_formats=collection_formats)
|
26443
|
+
|
26323
26444
|
def list_services_api_v2_services_v2_get(self, **kwargs): # noqa: E501
|
26324
26445
|
"""List Services # noqa: E501
|
26325
26446
|
|