anyscale 0.26.51__py3-none-any.whl → 0.26.53__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 (75) 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 +42 -31
  6. anyscale/_private/docgen/generator.py +63 -28
  7. anyscale/_private/docgen/models.md +4 -2
  8. anyscale/_private/sdk/__init__.py +124 -1
  9. anyscale/_private/workload/workload_config.py +4 -6
  10. anyscale/_private/workload/workload_sdk.py +105 -12
  11. anyscale/client/README.md +13 -11
  12. anyscale/client/openapi_client/__init__.py +3 -3
  13. anyscale/client/openapi_client/api/default_api.py +512 -316
  14. anyscale/client/openapi_client/models/__init__.py +3 -3
  15. anyscale/client/openapi_client/models/aws_config.py +2 -2
  16. anyscale/client/openapi_client/models/baseimagesenum.py +158 -1
  17. anyscale/client/openapi_client/models/cloud_data_bucket_presigned_url_request.py +31 -3
  18. anyscale/client/openapi_client/models/cloud_deployment.py +37 -36
  19. anyscale/client/openapi_client/models/cloud_resource.py +59 -3
  20. anyscale/client/openapi_client/models/cloud_resource_gcp.py +59 -3
  21. anyscale/client/openapi_client/models/create_cloud_resource.py +59 -3
  22. anyscale/client/openapi_client/models/create_cloud_resource_gcp.py +59 -3
  23. anyscale/client/openapi_client/models/create_resource_notification.py +31 -3
  24. anyscale/client/openapi_client/models/{decorated_cloud_deployment.py → decorated_cloud_resource.py} +124 -96
  25. anyscale/client/openapi_client/models/{clouddeployment_list_response.py → decoratedcloudresource_list_response.py} +15 -15
  26. anyscale/client/openapi_client/models/{decoratedclouddeployment_response.py → decoratedcloudresource_response.py} +11 -11
  27. anyscale/client/openapi_client/models/file_storage.py +4 -4
  28. anyscale/client/openapi_client/models/gcp_config.py +2 -2
  29. anyscale/client/openapi_client/models/ha_job_error_types.py +9 -2
  30. anyscale/client/openapi_client/models/object_storage.py +4 -4
  31. anyscale/client/openapi_client/models/ray_runtime_env_config.py +57 -1
  32. anyscale/client/openapi_client/models/resource_alert_event_type.py +2 -1
  33. anyscale/client/openapi_client/models/resource_notification.py +29 -1
  34. anyscale/client/openapi_client/models/supportedbaseimagesenum.py +155 -1
  35. anyscale/client/openapi_client/models/workload_info.py +31 -3
  36. anyscale/client/openapi_client/models/workload_state_info.py +29 -1
  37. anyscale/cloud/models.py +40 -43
  38. anyscale/commands/cloud_commands.py +93 -88
  39. anyscale/commands/command_examples.py +37 -49
  40. anyscale/commands/exec_commands.py +12 -1
  41. anyscale/commands/list_commands.py +42 -12
  42. anyscale/commands/project_commands.py +399 -115
  43. anyscale/commands/schedule_commands.py +22 -11
  44. anyscale/commands/service_commands.py +11 -6
  45. anyscale/commands/util.py +94 -1
  46. anyscale/commands/workspace_commands.py +92 -38
  47. anyscale/compute_config/__init__.py +1 -1
  48. anyscale/compute_config/_private/compute_config_sdk.py +8 -11
  49. anyscale/compute_config/commands.py +3 -3
  50. anyscale/compute_config/models.py +30 -30
  51. anyscale/controllers/cloud_controller.py +361 -360
  52. anyscale/controllers/kubernetes_verifier.py +1 -1
  53. anyscale/job/_private/job_sdk.py +41 -23
  54. anyscale/job/models.py +1 -1
  55. anyscale/project/__init__.py +101 -1
  56. anyscale/project/_private/project_sdk.py +90 -2
  57. anyscale/project/commands.py +188 -1
  58. anyscale/project/models.py +198 -2
  59. anyscale/sdk/anyscale_client/models/baseimagesenum.py +158 -1
  60. anyscale/sdk/anyscale_client/models/ray_runtime_env_config.py +57 -1
  61. anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +155 -1
  62. anyscale/service/_private/service_sdk.py +2 -1
  63. anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
  64. anyscale/util.py +3 -0
  65. anyscale/utils/runtime_env.py +3 -1
  66. anyscale/version.py +1 -1
  67. anyscale/workspace/commands.py +114 -23
  68. anyscale/workspace/models.py +3 -5
  69. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/METADATA +1 -1
  70. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/RECORD +75 -75
  71. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/WHEEL +0 -0
  72. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/entry_points.txt +0 -0
  73. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/licenses/LICENSE +0 -0
  74. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/licenses/NOTICE +0 -0
  75. {anyscale-0.26.51.dist-info → anyscale-0.26.53.dist-info}/top_level.txt +0 -0
@@ -1367,7 +1367,7 @@ class KubernetesCloudDeploymentVerifier:
1367
1367
  Args:
1368
1368
  cloud_deployment: The cloud deployment configuration
1369
1369
  """
1370
- deployment_name = cloud_deployment.name or cloud_deployment.cloud_deployment_id
1370
+ deployment_name = cloud_deployment.name or cloud_deployment.cloud_resource_id
1371
1371
  self.log.info(f"Starting Kubernetes verification for: {deployment_name}")
1372
1372
 
1373
1373
  if cloud_deployment.file_storage is not None and isinstance(
@@ -19,7 +19,7 @@ from anyscale.client.openapi_client.models.ray_runtime_env_config import (
19
19
  from anyscale.compute_config.models import (
20
20
  ComputeConfig,
21
21
  ComputeConfigType,
22
- MultiDeploymentComputeConfig,
22
+ MultiResourceComputeConfig,
23
23
  )
24
24
  from anyscale.job.models import (
25
25
  JobConfig,
@@ -82,19 +82,34 @@ class PrivateJobSDK(WorkloadSDK):
82
82
  - 'working_dir' will be set to '.'.
83
83
  - 'pip' will be set to the workspace-managed requirements file.
84
84
  """
85
- runtime_env: Dict[str, Any] = {}
86
- [runtime_env] = self.override_and_upload_local_dirs(
87
- [runtime_env],
88
- working_dir_override=config.working_dir,
89
- excludes_override=config.excludes,
90
- cloud_id=cloud_id,
91
- autopopulate_in_workspace=autopopulate_in_workspace,
92
- additional_py_modules=config.py_modules,
93
- py_executable_override=config.py_executable,
94
- has_multiple_cloud_deployments=self._compute_config_has_multiple_cloud_deployments(
95
- compute_config=config.compute_config, cloud=config.cloud
96
- ),
85
+ cloud_resource_names = self._get_compute_config_cloud_resources(
86
+ compute_config=config.compute_config, cloud=config.cloud
97
87
  )
88
+ assert len(cloud_resource_names) > 0
89
+
90
+ runtime_env: Dict[str, Any] = {}
91
+ if len(cloud_resource_names) == 1:
92
+ [runtime_env] = self.override_and_upload_local_dirs_single_deployment(
93
+ [runtime_env],
94
+ working_dir_override=config.working_dir,
95
+ excludes_override=config.excludes,
96
+ cloud_id=cloud_id,
97
+ autopopulate_in_workspace=autopopulate_in_workspace,
98
+ additional_py_modules=config.py_modules,
99
+ py_executable_override=config.py_executable,
100
+ cloud_resource_name=cloud_resource_names[0],
101
+ )
102
+ else:
103
+ [runtime_env] = self.override_and_upload_local_dirs_multi_cloud_resource(
104
+ [runtime_env],
105
+ working_dir_override=config.working_dir,
106
+ excludes_override=config.excludes,
107
+ cloud_id=cloud_id,
108
+ autopopulate_in_workspace=autopopulate_in_workspace,
109
+ additional_py_modules=config.py_modules,
110
+ py_executable_override=config.py_executable,
111
+ cloud_resource_names=cloud_resource_names,
112
+ )
98
113
  [runtime_env] = self.override_and_load_requirements_files(
99
114
  [runtime_env],
100
115
  requirements_override=config.requirements,
@@ -106,15 +121,15 @@ class PrivateJobSDK(WorkloadSDK):
106
121
 
107
122
  return runtime_env or None
108
123
 
109
- def _compute_config_has_multiple_cloud_deployments(
124
+ def _get_compute_config_cloud_resources(
110
125
  self, compute_config: Union[ComputeConfigType, str, None], cloud: Optional[str]
111
- ) -> bool:
126
+ ) -> List[Optional[str]]:
112
127
  if isinstance(compute_config, ComputeConfig):
113
- # single-deployment compute config
114
- return False
128
+ # single-cloud resource compute config
129
+ return [compute_config.cloud_resource]
115
130
 
116
- if isinstance(compute_config, MultiDeploymentComputeConfig):
117
- return len(compute_config.configs) > 1
131
+ if isinstance(compute_config, MultiResourceComputeConfig):
132
+ return [config.cloud_resource for config in compute_config.configs]
118
133
 
119
134
  compute_config_id = self._resolve_compute_config_id(
120
135
  compute_config=compute_config, cloud=cloud
@@ -125,10 +140,13 @@ class PrivateJobSDK(WorkloadSDK):
125
140
  f"The compute config '{compute_config_id}' does not exist."
126
141
  )
127
142
 
128
- return (
129
- compute_template.config.deployment_configs
130
- and len(compute_template.config.deployment_configs) > 1
131
- )
143
+ if compute_template.config.deployment_configs is None:
144
+ return [None]
145
+
146
+ return [
147
+ config.cloud_deployment
148
+ for config in compute_template.config.deployment_configs
149
+ ]
132
150
 
133
151
  def get_default_name(self) -> str:
134
152
  """Get a default name for the job.
anyscale/job/models.py CHANGED
@@ -269,7 +269,7 @@ config = JobConfig(
269
269
  name="my-job",
270
270
  entrypoint="python main.py",
271
271
  max_retries=1,
272
- # An inline `ComputeConfig` or `MultiDeploymentComputeConfig` can also be provided.
272
+ # An inline `ComputeConfig` or `MultiResourceComputeConfig` can also be provided.
273
273
  compute_config="my-compute-config:1",
274
274
  # A containerfile path can also be provided.
275
275
  image_uri="anyscale/image/my-image:1",
@@ -1,6 +1,7 @@
1
1
  from typing import List, Optional
2
2
 
3
3
  from anyscale._private.anyscale_client import AnyscaleClientInterface
4
+ from anyscale._private.models.model_base import ResultIterator
4
5
  from anyscale._private.sdk import sdk_docs
5
6
  from anyscale._private.sdk.base_sdk import Timer
6
7
  from anyscale.cli_logger import BlockLogger
@@ -8,9 +9,30 @@ from anyscale.project._private.project_sdk import PrivateProjectSDK
8
9
  from anyscale.project.commands import (
9
10
  _ADD_COLLABORATORS_DOCSTRINGS,
10
11
  _ADD_COLLABORATORS_EXAMPLE,
12
+ _CREATE_PROJECT_DOCSTRINGS,
13
+ _CREATE_PROJECT_EXAMPLE,
14
+ _DELETE_PROJECT_DOCSTRINGS,
15
+ _DELETE_PROJECT_EXAMPLE,
16
+ _GET_DEFAULT_PROJECT_DOCSTRINGS,
17
+ _GET_DEFAULT_PROJECT_EXAMPLE,
18
+ _GET_PROJECT_DOCSTRINGS,
19
+ _GET_PROJECT_EXAMPLE,
20
+ _LIST_PROJECTS_DOCSTRINGS,
21
+ _LIST_PROJECTS_EXAMPLE,
11
22
  add_collaborators,
23
+ create,
24
+ delete,
25
+ get,
26
+ get_default,
27
+ list,
28
+ )
29
+ from anyscale.project.models import (
30
+ CreateProjectCollaborator,
31
+ Project,
32
+ ProjectPermissionLevel,
33
+ ProjectSortField,
34
+ ProjectSortOrder,
12
35
  )
13
- from anyscale.project.models import CreateProjectCollaborator
14
36
 
15
37
 
16
38
  class ProjectSDK:
@@ -33,3 +55,81 @@ class ProjectSDK:
33
55
  """Batch add collaborators to a project.
34
56
  """
35
57
  self._private_sdk.add_collaborators(cloud, project, collaborators)
58
+
59
+ @sdk_docs(
60
+ doc_py_example=_GET_PROJECT_EXAMPLE, arg_docstrings=_GET_PROJECT_DOCSTRINGS,
61
+ )
62
+ def get(self, project_id: str) -> Project: # noqa: F811
63
+ """Get details of a project."""
64
+ return self._private_sdk.get(project_id)
65
+
66
+ @sdk_docs(
67
+ doc_py_example=_LIST_PROJECTS_EXAMPLE, arg_docstrings=_LIST_PROJECTS_DOCSTRINGS,
68
+ )
69
+ def list( # noqa: F811
70
+ self,
71
+ *,
72
+ name_contains: Optional[str] = None,
73
+ creator_id: Optional[str] = None,
74
+ parent_cloud_id: Optional[str] = None,
75
+ include_defaults: bool = True,
76
+ max_items: Optional[int] = None,
77
+ page_size: Optional[int] = None,
78
+ sort_field: Optional[ProjectSortField] = None,
79
+ sort_order: Optional[ProjectSortOrder] = None,
80
+ ) -> ResultIterator[Project]:
81
+ """List all projects with optional filters.
82
+
83
+ Returns
84
+ -------
85
+ ResultIterator[Project]
86
+ An iterator yielding Project objects. Fetches pages
87
+ lazily as needed. Use a `for` loop to iterate or `list()`
88
+ to consume all at once.
89
+ """
90
+ return self._private_sdk.list(
91
+ name_contains=name_contains,
92
+ creator_id=creator_id,
93
+ parent_cloud_id=parent_cloud_id,
94
+ include_defaults=include_defaults,
95
+ max_items=max_items,
96
+ page_size=page_size,
97
+ sort_field=sort_field,
98
+ sort_order=sort_order,
99
+ )
100
+
101
+ @sdk_docs(
102
+ doc_py_example=_CREATE_PROJECT_EXAMPLE,
103
+ arg_docstrings=_CREATE_PROJECT_DOCSTRINGS,
104
+ )
105
+ def create( # noqa: F811
106
+ self,
107
+ name: str,
108
+ parent_cloud_id: str,
109
+ *,
110
+ description: Optional[str] = None,
111
+ initial_cluster_config: Optional[str] = None,
112
+ ) -> str:
113
+ """Create a project."""
114
+ return self._private_sdk.create(
115
+ name,
116
+ description or "",
117
+ parent_cloud_id,
118
+ initial_cluster_config=initial_cluster_config,
119
+ )
120
+
121
+ @sdk_docs(
122
+ doc_py_example=_DELETE_PROJECT_EXAMPLE,
123
+ arg_docstrings=_DELETE_PROJECT_DOCSTRINGS,
124
+ )
125
+ def delete(self, project_id: str): # noqa: F811
126
+ """Delete a project."""
127
+ self._private_sdk.delete(project_id)
128
+
129
+ @sdk_docs(
130
+ doc_py_example=_GET_DEFAULT_PROJECT_EXAMPLE,
131
+ arg_docstrings=_GET_DEFAULT_PROJECT_DOCSTRINGS,
132
+ )
133
+ def get_default(self, parent_cloud_id: str) -> Project: # noqa: F811
134
+ """Get the default project for a cloud."""
135
+ return self._private_sdk.get_default(parent_cloud_id)
@@ -1,11 +1,23 @@
1
- from typing import List
1
+ from typing import List, Optional
2
2
 
3
+ from anyscale._private.models.model_base import ResultIterator
3
4
  from anyscale._private.sdk.base_sdk import BaseSDK
4
5
  from anyscale.client.openapi_client import (
5
6
  CreateUserProjectCollaborator,
6
7
  CreateUserProjectCollaboratorValue,
8
+ Project as OpenAPIProject,
9
+ ProjectListResponse,
10
+ WriteProject,
7
11
  )
8
- from anyscale.project.models import CreateProjectCollaborator
12
+ from anyscale.project.models import (
13
+ CreateProjectCollaborator,
14
+ Project,
15
+ ProjectSortField,
16
+ ProjectSortOrder,
17
+ )
18
+
19
+
20
+ MAX_PAGE_SIZE = 50
9
21
 
10
22
 
11
23
  class PrivateProjectSDK(BaseSDK):
@@ -25,3 +37,79 @@ class PrivateProjectSDK(BaseSDK):
25
37
  for collaborator in collaborators
26
38
  ],
27
39
  )
40
+
41
+ def get(self, project_id: str) -> Optional[Project]:
42
+ project: OpenAPIProject = self.client.get_project(project_id)
43
+ return Project.from_dict(project.to_dict()) if project else None
44
+
45
+ def list(
46
+ self,
47
+ *,
48
+ # filters
49
+ name_contains: Optional[str] = None,
50
+ creator_id: Optional[str] = None,
51
+ parent_cloud_id: Optional[str] = None,
52
+ include_defaults: bool = True,
53
+ # pagination
54
+ max_items: Optional[int] = None,
55
+ page_size: Optional[int] = None,
56
+ # sorting
57
+ sort_field: Optional[ProjectSortField] = None,
58
+ sort_order: Optional[ProjectSortOrder] = None,
59
+ ) -> ResultIterator[Project]:
60
+ if max_items is not None and (max_items <= 0):
61
+ raise ValueError("'max_items' must be greater than 0.")
62
+
63
+ if page_size is not None and (page_size <= 0 or page_size > MAX_PAGE_SIZE):
64
+ raise ValueError(
65
+ f"'page_size' must be between 1 and {MAX_PAGE_SIZE}, inclusive."
66
+ )
67
+
68
+ def _fetch_page(token: Optional[str],) -> ProjectListResponse:
69
+ return self.client.list_projects(
70
+ name_contains=name_contains,
71
+ creator_id=creator_id,
72
+ parent_cloud_id=parent_cloud_id,
73
+ include_defaults=include_defaults,
74
+ sort_field=str(sort_field) if sort_field else None,
75
+ sort_order=str(sort_order) if sort_order else None,
76
+ paging_token=token,
77
+ count=page_size,
78
+ )
79
+
80
+ def _openapi_project_to_sdk_project(openapi_project: OpenAPIProject) -> Project:
81
+ return Project.from_dict(openapi_project.to_dict())
82
+
83
+ return ResultIterator(
84
+ page_token=None,
85
+ max_items=max_items,
86
+ fetch_page=_fetch_page,
87
+ parse_fn=_openapi_project_to_sdk_project,
88
+ )
89
+
90
+ def create(
91
+ self,
92
+ name: str,
93
+ description: str,
94
+ parent_cloud_id: str,
95
+ *,
96
+ initial_cluster_config: Optional[str] = None,
97
+ ) -> str:
98
+ project = self.client.create_project(
99
+ project=WriteProject(
100
+ name=name,
101
+ description=description,
102
+ parent_cloud_id=parent_cloud_id,
103
+ initial_cluster_config=initial_cluster_config,
104
+ )
105
+ )
106
+ return project.id # type: ignore
107
+
108
+ def delete(
109
+ self, project_id: str,
110
+ ):
111
+ self.client.delete_project(project_id)
112
+
113
+ def get_default(self, parent_cloud_id: str,) -> Project:
114
+ project: OpenAPIProject = self.client.get_default_project(parent_cloud_id)
115
+ return Project.from_dict(project.to_dict())
@@ -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