anyscale 0.26.51__py3-none-any.whl → 0.26.52__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 (46) hide show
  1. anyscale/_private/anyscale_client/README.md +1 -1
  2. anyscale/_private/anyscale_client/anyscale_client.py +178 -46
  3. anyscale/_private/anyscale_client/common.py +61 -2
  4. anyscale/_private/anyscale_client/fake_anyscale_client.py +145 -8
  5. anyscale/_private/docgen/__main__.py +34 -23
  6. anyscale/_private/docgen/generator.py +15 -18
  7. anyscale/_private/docgen/models.md +4 -2
  8. anyscale/_private/workload/workload_sdk.py +103 -8
  9. anyscale/client/README.md +3 -0
  10. anyscale/client/openapi_client/__init__.py +1 -0
  11. anyscale/client/openapi_client/api/default_api.py +249 -0
  12. anyscale/client/openapi_client/models/__init__.py +1 -0
  13. anyscale/client/openapi_client/models/baseimagesenum.py +83 -1
  14. anyscale/client/openapi_client/models/cloud_resource.py +59 -3
  15. anyscale/client/openapi_client/models/cloud_resource_gcp.py +59 -3
  16. anyscale/client/openapi_client/models/clouddeployment_response.py +121 -0
  17. anyscale/client/openapi_client/models/create_cloud_resource.py +59 -3
  18. anyscale/client/openapi_client/models/create_cloud_resource_gcp.py +59 -3
  19. anyscale/client/openapi_client/models/object_storage.py +2 -2
  20. anyscale/client/openapi_client/models/ray_runtime_env_config.py +57 -1
  21. anyscale/client/openapi_client/models/supportedbaseimagesenum.py +80 -1
  22. anyscale/cloud/models.py +1 -1
  23. anyscale/commands/cloud_commands.py +73 -70
  24. anyscale/commands/command_examples.py +28 -40
  25. anyscale/commands/project_commands.py +377 -106
  26. anyscale/controllers/cloud_controller.py +81 -86
  27. anyscale/job/_private/job_sdk.py +38 -20
  28. anyscale/project/__init__.py +101 -1
  29. anyscale/project/_private/project_sdk.py +90 -2
  30. anyscale/project/commands.py +188 -1
  31. anyscale/project/models.py +198 -2
  32. anyscale/sdk/anyscale_client/models/baseimagesenum.py +83 -1
  33. anyscale/sdk/anyscale_client/models/ray_runtime_env_config.py +57 -1
  34. anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +80 -1
  35. anyscale/service/_private/service_sdk.py +2 -1
  36. anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
  37. anyscale/util.py +3 -0
  38. anyscale/utils/runtime_env.py +3 -1
  39. anyscale/version.py +1 -1
  40. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/METADATA +1 -1
  41. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/RECORD +46 -45
  42. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/WHEEL +0 -0
  43. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/entry_points.txt +0 -0
  44. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/licenses/LICENSE +0 -0
  45. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/licenses/NOTICE +0 -0
  46. {anyscale-0.26.51.dist-info → anyscale-0.26.52.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,14 @@
1
1
  from typing import List, Optional
2
2
 
3
+ from anyscale._private.models.model_base import ResultIterator
3
4
  from anyscale._private.sdk import sdk_command
4
5
  from anyscale.project._private.project_sdk import PrivateProjectSDK
5
- from anyscale.project.models import CreateProjectCollaborator
6
+ from anyscale.project.models import (
7
+ CreateProjectCollaborator,
8
+ Project,
9
+ ProjectSortField,
10
+ ProjectSortOrder,
11
+ )
6
12
 
7
13
 
8
14
  _PROJECT_SDK_SINGLETON_KEY = "project_sdk"
@@ -54,3 +60,184 @@ def add_collaborators(
54
60
  """Batch add collaborators to a project.
55
61
  """
56
62
  return _private_sdk.add_collaborators(cloud, project, collaborators) # type: ignore
63
+
64
+
65
+ _GET_PROJECT_EXAMPLE = """
66
+ import anyscale
67
+ from anyscale.project.models import Project
68
+
69
+ project: Project = anyscale.project.get(project_id="my-project-id")
70
+ """
71
+
72
+ _GET_PROJECT_DOCSTRINGS = {
73
+ "project_id": "The ID of the project to get details of.",
74
+ }
75
+
76
+
77
+ @sdk_command(
78
+ _PROJECT_SDK_SINGLETON_KEY,
79
+ PrivateProjectSDK,
80
+ doc_py_example=_GET_PROJECT_EXAMPLE,
81
+ arg_docstrings=_GET_PROJECT_DOCSTRINGS,
82
+ )
83
+ def get(
84
+ project_id: str, *, _private_sdk: Optional[PrivateProjectSDK] = None
85
+ ) -> Project:
86
+ """Get details of a project.
87
+ """
88
+ return _private_sdk.get(project_id) # type: ignore
89
+
90
+
91
+ _LIST_PROJECTS_EXAMPLE = """
92
+ from typing import Iterator
93
+
94
+ import anyscale
95
+ from anyscale.project.models import Project, ProjectSortField, ProjectSortOrder
96
+
97
+ projects: Iterator[Project] = anyscale.project.list(
98
+ name_contains="my-project",
99
+ creator_id="my-user-id",
100
+ parent_cloud_id="my-cloud-id",
101
+ include_defaults=True,
102
+ max_items=20,
103
+ page_size=10,
104
+ sort_field=ProjectSortField.NAME,
105
+ sort_order=ProjectSortOrder.ASC,
106
+ )
107
+ for project in projects:
108
+ print(project.name)
109
+ """
110
+
111
+ _LIST_PROJECTS_DOCSTRINGS = {
112
+ "name_contains": "A string to filter projects by name.",
113
+ "creator_id": "The ID of a creator to filter projects.",
114
+ "parent_cloud_id": "The ID of a parent cloud to filter projects.",
115
+ "include_defaults": "Whether to include default projects.",
116
+ "max_items": "The maximum number of projects to return.",
117
+ "page_size": "The number of projects to return per page.",
118
+ "sort_field": "The field to sort projects by.",
119
+ "sort_order": "The order to sort projects by.",
120
+ }
121
+
122
+
123
+ @sdk_command(
124
+ _PROJECT_SDK_SINGLETON_KEY,
125
+ PrivateProjectSDK,
126
+ doc_py_example=_LIST_PROJECTS_EXAMPLE,
127
+ arg_docstrings=_LIST_PROJECTS_DOCSTRINGS,
128
+ )
129
+ def list( # noqa: A001
130
+ *,
131
+ name_contains: Optional[str] = None,
132
+ creator_id: Optional[str] = None,
133
+ parent_cloud_id: Optional[str] = None,
134
+ include_defaults: bool = True,
135
+ max_items: Optional[int] = None,
136
+ page_size: Optional[int] = None,
137
+ sort_field: Optional[ProjectSortField] = None,
138
+ sort_order: Optional[ProjectSortOrder] = None,
139
+ _private_sdk: Optional[PrivateProjectSDK] = None
140
+ ) -> ResultIterator[Project]:
141
+ """List projects.
142
+ """
143
+ return _private_sdk.list( # type: ignore
144
+ name_contains=name_contains,
145
+ creator_id=creator_id,
146
+ parent_cloud_id=parent_cloud_id,
147
+ include_defaults=include_defaults,
148
+ max_items=max_items,
149
+ page_size=page_size,
150
+ sort_field=sort_field,
151
+ sort_order=sort_order,
152
+ )
153
+
154
+
155
+ _CREATE_PROJECT_EXAMPLE = """
156
+ import anyscale
157
+
158
+ project_id: str = anyscale.project.create(
159
+ name="my-project",
160
+ parent_cloud_id="my-cloud-id",
161
+ description="my-project-description",
162
+ )
163
+ """
164
+
165
+ _CREATE_PROJECT_DOCSTRINGS = {
166
+ "name": "The name of the project.",
167
+ "parent_cloud_id": "The parent cloud that the project belongs to.",
168
+ "description": "The description of the project.",
169
+ "initial_cluster_config": "A YAML string containing the initial cluster config for the project.",
170
+ }
171
+
172
+
173
+ @sdk_command(
174
+ _PROJECT_SDK_SINGLETON_KEY,
175
+ PrivateProjectSDK,
176
+ doc_py_example=_CREATE_PROJECT_EXAMPLE,
177
+ arg_docstrings=_CREATE_PROJECT_DOCSTRINGS,
178
+ )
179
+ def create(
180
+ name: str,
181
+ parent_cloud_id: str,
182
+ *,
183
+ description: Optional[str] = None,
184
+ initial_cluster_config: Optional[str] = None,
185
+ _private_sdk: Optional[PrivateProjectSDK] = None
186
+ ) -> str:
187
+ """Create a project.
188
+ """
189
+ return _private_sdk.create( # type: ignore
190
+ name,
191
+ description or "",
192
+ parent_cloud_id,
193
+ initial_cluster_config=initial_cluster_config,
194
+ )
195
+
196
+
197
+ _DELETE_PROJECT_EXAMPLE = """
198
+ import anyscale
199
+
200
+ anyscale.project.delete(project_id="my-project-id")
201
+ """
202
+
203
+ _DELETE_PROJECT_DOCSTRINGS = {
204
+ "project_id": "The ID of the project to delete.",
205
+ }
206
+
207
+
208
+ @sdk_command(
209
+ _PROJECT_SDK_SINGLETON_KEY,
210
+ PrivateProjectSDK,
211
+ doc_py_example=_DELETE_PROJECT_EXAMPLE,
212
+ arg_docstrings=_DELETE_PROJECT_DOCSTRINGS,
213
+ )
214
+ def delete(project_id: str, *, _private_sdk: Optional[PrivateProjectSDK] = None):
215
+ """Delete a project.
216
+ """
217
+ _private_sdk.delete(project_id) # type: ignore
218
+
219
+
220
+ _GET_DEFAULT_PROJECT_EXAMPLE = """
221
+ import anyscale
222
+ from anyscale.project.models import Project
223
+
224
+ project: Project = anyscale.project.get_default(parent_cloud_id="my-cloud-id")
225
+ """
226
+
227
+ _GET_DEFAULT_PROJECT_DOCSTRINGS = {
228
+ "parent_cloud_id": "The ID of the parent cloud to get the default project for.",
229
+ }
230
+
231
+
232
+ @sdk_command(
233
+ _PROJECT_SDK_SINGLETON_KEY,
234
+ PrivateProjectSDK,
235
+ doc_py_example=_GET_DEFAULT_PROJECT_EXAMPLE,
236
+ arg_docstrings=_GET_DEFAULT_PROJECT_DOCSTRINGS,
237
+ )
238
+ def get_default(
239
+ parent_cloud_id: str, *, _private_sdk: Optional[PrivateProjectSDK] = None
240
+ ) -> Project:
241
+ """Get the default project for a cloud.
242
+ """
243
+ return _private_sdk.get_default(parent_cloud_id) # type: ignore
@@ -1,5 +1,8 @@
1
- from dataclasses import dataclass, field
2
- from typing import Any, Dict, List
1
+ import contextlib
2
+ from dataclasses import dataclass, field, fields
3
+ from datetime import datetime
4
+ import json
5
+ from typing import Any, Dict, List, Optional, Union
3
6
 
4
7
  from anyscale._private.models import ModelBase, ModelEnum
5
8
 
@@ -89,3 +92,196 @@ create_project_collaborators = CreateProjectCollaborators(
89
92
  def _validate_collaborators(self, collaborators: List[Dict[str, Any]]):
90
93
  if not isinstance(collaborators, list):
91
94
  raise TypeError("Collaborators must be a list.")
95
+
96
+
97
+ @dataclass(frozen=True)
98
+ class ProjectMinimal(ModelBase):
99
+ """Minimal Project object."""
100
+
101
+ id: str = field(metadata={"docstring": "ID of the project."},)
102
+
103
+ def _validate_id(self, id: str): # noqa: A002
104
+ if not isinstance(id, str):
105
+ raise TypeError("'id' must be a string.")
106
+
107
+ name: str = field(metadata={"docstring": "Name of the project."},)
108
+
109
+ def _validate_name(self, name: str):
110
+ if not isinstance(name, str):
111
+ raise TypeError("'name' must be a string.")
112
+
113
+ description: str = field(metadata={"docstring": "Description of the project."},)
114
+
115
+ def _validate_description(self, description: str):
116
+ if not isinstance(description, str):
117
+ raise TypeError("'description' must be a string.")
118
+
119
+ created_at: str = field(
120
+ metadata={"docstring": "Datetime of the project creation."},
121
+ )
122
+
123
+ def _validate_created_at(self, created_at: str):
124
+ if not isinstance(created_at, str):
125
+ raise TypeError("'created_at' must be a string.")
126
+
127
+ creator_id: Optional[str] = field(
128
+ default=None, metadata={"docstring": "ID of the creator of the project."},
129
+ )
130
+
131
+ def _validate_creator_id(self, creator_id: Optional[str]):
132
+ if creator_id is not None and not isinstance(creator_id, str):
133
+ raise TypeError("'creator_id' must be a string.")
134
+
135
+ parent_cloud_id: Optional[str] = field(
136
+ default=None, metadata={"docstring": "ID of the parent cloud."},
137
+ )
138
+
139
+ def _validate_parent_cloud_id(self, parent_cloud_id: Optional[str]):
140
+ if parent_cloud_id is not None and not isinstance(parent_cloud_id, str):
141
+ raise TypeError("'parent_cloud_id' must be a string.")
142
+
143
+ @classmethod
144
+ def from_dict(cls, data: Dict[str, Any]) -> "ProjectMinimal":
145
+ # remove any fields that are not in the dataclass
146
+ valid_fields = {field_.name for field_ in fields(cls)}
147
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
148
+ return cls(**filtered_data)
149
+
150
+
151
+ @dataclass(frozen=True)
152
+ class Project(ProjectMinimal):
153
+ """Project object.
154
+ """
155
+
156
+ __doc_py_example__ = """\
157
+ import anyscale
158
+ from anyscale.project.models import Project
159
+
160
+ project: Project = anyscale.project.get(project_id="my-project-id")
161
+ """
162
+
163
+ is_owner: bool = field(
164
+ default=False,
165
+ metadata={"docstring": "Whether the user is the owner of the project."},
166
+ )
167
+
168
+ def _validate_is_owner(self, is_owner: bool):
169
+ if not isinstance(is_owner, bool):
170
+ raise TypeError("'is_owner' must be a boolean.")
171
+
172
+ is_read_only: bool = field(
173
+ default=False,
174
+ metadata={"docstring": "Whether the user has read-only access to the project."},
175
+ )
176
+
177
+ def _validate_is_read_only(self, is_read_only: bool):
178
+ if not isinstance(is_read_only, bool):
179
+ raise TypeError("'is_read_only' must be a boolean.")
180
+
181
+ directory_name: str = field(
182
+ default="",
183
+ metadata={
184
+ "docstring": "Directory name of project to be used as working directory of clusters."
185
+ },
186
+ )
187
+
188
+ def _validate_directory_name(self, directory_name: str):
189
+ if not isinstance(directory_name, str):
190
+ raise TypeError("'directory_name' must be a string.")
191
+
192
+ is_default: bool = field(
193
+ default=False,
194
+ metadata={
195
+ "docstring": "Whether the project is the default project for the organization."
196
+ },
197
+ )
198
+
199
+ def _validate_is_default(self, is_default: bool):
200
+ if not isinstance(is_default, bool):
201
+ raise TypeError("'is_default' must be a boolean.")
202
+
203
+ initial_cluster_config: Optional[Union[str, Dict[str, Any]]] = field(
204
+ default=None,
205
+ metadata={"docstring": "Initial cluster config associated with the project."},
206
+ )
207
+
208
+ def _validate_initial_cluster_config(
209
+ self, initial_cluster_config: Union[str, Dict[str, Any], None]
210
+ ):
211
+ if initial_cluster_config is not None and not isinstance(
212
+ initial_cluster_config, (str, dict)
213
+ ):
214
+ raise TypeError("'initial_cluster_config' must be a string or dictionary.")
215
+
216
+ last_used_cloud_id: Optional[str] = field(
217
+ default=None,
218
+ metadata={
219
+ "docstring": "ID of the last cloud used in this project, or by the user if this is a new project."
220
+ },
221
+ )
222
+
223
+ def _validate_last_used_cloud_id(self, last_used_cloud_id: Optional[str]):
224
+ if last_used_cloud_id is not None and not isinstance(last_used_cloud_id, str):
225
+ raise TypeError("'last_used_cloud_id' must be a string.")
226
+
227
+ owners: List[str] = field(
228
+ default_factory=list,
229
+ metadata={
230
+ "docstring": "List of IDs of users who have owner access to the project."
231
+ },
232
+ )
233
+
234
+ def _validate_owners(self, owners: List[str]):
235
+ if not isinstance(owners, list):
236
+ raise TypeError("'owners' must be a list.")
237
+ for owner in owners:
238
+ if not isinstance(owner, str):
239
+ raise TypeError(f"'{owner}' must be a string.")
240
+
241
+ @classmethod
242
+ def from_dict(cls, d: Dict[str, Any]) -> "Project":
243
+ data = d.copy()
244
+ # convert datetime fields to string
245
+ for field_ in fields(cls):
246
+ if field_.name in data and isinstance(data[field_.name], datetime):
247
+ data[field_.name] = data[field_.name].strftime("%Y-%m-%d %H:%M:%S")
248
+
249
+ # convert initial_cluster_config JSON string to dict
250
+ if "initial_cluster_config" in data and isinstance(
251
+ data["initial_cluster_config"], str
252
+ ):
253
+ with contextlib.suppress(json.JSONDecodeError):
254
+ data["initial_cluster_config"] = json.loads(
255
+ data["initial_cluster_config"]
256
+ )
257
+
258
+ # convert owners list of dicts to list of string IDs
259
+ if "owners" in data and isinstance(data["owners"], list):
260
+ data["owners"] = [owner.get("id") for owner in data["owners"]]
261
+
262
+ # remove any fields that are not in the dataclass
263
+ valid_fields = {field_.name for field_ in fields(cls)}
264
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
265
+ return cls(**filtered_data)
266
+
267
+
268
+ class ProjectSortField(ModelEnum):
269
+ """Field to sort projects by."""
270
+
271
+ NAME = "NAME"
272
+
273
+ __docstrings__ = {
274
+ NAME: "Sort by project name.",
275
+ }
276
+
277
+
278
+ class ProjectSortOrder(ModelEnum):
279
+ """Direction of sorting."""
280
+
281
+ ASC = "ASC"
282
+ DESC = "DESC"
283
+
284
+ __docstrings__ = {
285
+ ASC: "Sort in ascending order.",
286
+ DESC: "Sort in descending order.",
287
+ }