anyscale 0.26.15__py3-none-any.whl → 0.26.17__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 (66) hide show
  1. anyscale/_private/anyscale_client/anyscale_client.py +4 -2
  2. anyscale/_private/anyscale_client/common.py +6 -4
  3. anyscale/_private/anyscale_client/fake_anyscale_client.py +15 -6
  4. anyscale/_private/docgen/__main__.py +4 -4
  5. anyscale/_private/docgen/generator.py +2 -2
  6. anyscale/_private/sdk/__init__.py +2 -2
  7. anyscale/_private/workload/workload_sdk.py +6 -4
  8. anyscale/aggregated_instance_usage/commands.py +6 -2
  9. anyscale/anyscale-cloud-setup-gcp.yaml +2 -0
  10. anyscale/client/README.md +11 -6
  11. anyscale/client/openapi_client/__init__.py +8 -4
  12. anyscale/client/openapi_client/api/default_api.py +402 -270
  13. anyscale/client/openapi_client/models/__init__.py +8 -4
  14. anyscale/client/openapi_client/models/alert_type.py +11 -2
  15. anyscale/client/openapi_client/models/create_job_queue_requests.py +3 -32
  16. anyscale/client/openapi_client/models/i_know_response.py +174 -0
  17. anyscale/client/openapi_client/models/i_know_time_series_event.py +148 -0
  18. anyscale/client/openapi_client/models/job_report.py +199 -0
  19. anyscale/client/openapi_client/models/job_with_report.py +254 -0
  20. anyscale/client/openapi_client/models/jobwithreport_list_response.py +147 -0
  21. anyscale/client/openapi_client/models/{product_autoscaler_flag.py → list_ray_sessions_response.py} +22 -23
  22. anyscale/client/openapi_client/models/{productautoscalerflag_response.py → listraysessionsresponse_response.py} +11 -11
  23. anyscale/client/openapi_client/models/metric.py +133 -3
  24. anyscale/client/openapi_client/models/ray_session.py +121 -0
  25. anyscale/cloud/__init__.py +2 -2
  26. anyscale/cloud/_private/cloud_sdk.py +2 -2
  27. anyscale/cloud/commands.py +9 -6
  28. anyscale/cloud_utils.py +5 -4
  29. anyscale/cluster_compute.py +2 -2
  30. anyscale/cluster_env.py +2 -0
  31. anyscale/commands/cloud_commands.py +43 -0
  32. anyscale/commands/login_commands.py +24 -3
  33. anyscale/commands/schedule_commands.py +2 -1
  34. anyscale/compute_config/commands.py +15 -7
  35. anyscale/controllers/cloud_controller.py +151 -8
  36. anyscale/controllers/cluster_controller.py +1 -0
  37. anyscale/controllers/job_controller.py +1 -1
  38. anyscale/controllers/service_controller.py +1 -0
  39. anyscale/image/commands.py +6 -6
  40. anyscale/job/_private/job_sdk.py +22 -24
  41. anyscale/job/commands.py +12 -12
  42. anyscale/organization_invitation/commands.py +11 -7
  43. anyscale/project/__init__.py +2 -2
  44. anyscale/project/_private/project_sdk.py +2 -2
  45. anyscale/project/commands.py +3 -3
  46. anyscale/project_utils.py +1 -1
  47. anyscale/resource_quota/commands.py +18 -10
  48. anyscale/schedule/commands.py +12 -8
  49. anyscale/sdk/anyscale_client/sdk.py +1 -0
  50. anyscale/service/commands.py +17 -17
  51. anyscale/service_account/commands.py +12 -10
  52. anyscale/user/commands.py +5 -3
  53. anyscale/utils/gcp_utils.py +25 -9
  54. anyscale/version.py +1 -1
  55. anyscale/workspace/__init__.py +1 -1
  56. anyscale/workspace/_private/workspace_sdk.py +5 -3
  57. anyscale/workspace/commands.py +26 -24
  58. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/METADATA +1 -1
  59. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/RECORD +64 -60
  60. anyscale/client/openapi_client/models/aviary_model_config_v2.py +0 -358
  61. anyscale/client/openapi_client/models/finish_ft_job_request_v2.py +0 -183
  62. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/LICENSE +0 -0
  63. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/NOTICE +0 -0
  64. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/WHEEL +0 -0
  65. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/entry_points.txt +0 -0
  66. {anyscale-0.26.15.dist-info → anyscale-0.26.17.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ Fetches data required and formats output for `anyscale cloud` commands.
3
3
  """
4
4
 
5
5
  import copy
6
+ from datetime import datetime, timedelta
6
7
  import json
7
8
  from os import getenv
8
9
  import pathlib
@@ -16,6 +17,7 @@ import boto3
16
17
  from botocore.exceptions import ClientError, NoCredentialsError
17
18
  import click
18
19
  from click import Abort, ClickException
20
+ from rich.progress import Progress, track
19
21
  import yaml
20
22
 
21
23
  from anyscale import __version__ as anyscale_version
@@ -72,8 +74,12 @@ from anyscale.controllers.cloud_functional_verification_controller import (
72
74
  CloudFunctionalVerificationType,
73
75
  )
74
76
  from anyscale.formatters import clouds_formatter
77
+ from anyscale.job._private.job_sdk import (
78
+ HA_JOB_STATE_TO_JOB_STATE,
79
+ TERMINAL_HA_JOB_STATES,
80
+ )
75
81
  from anyscale.shared_anyscale_utils.aws import AwsRoleArn
76
- from anyscale.shared_anyscale_utils.conf import ANYSCALE_ENV
82
+ from anyscale.shared_anyscale_utils.conf import ANYSCALE_ENV, ANYSCALE_HOST
77
83
  from anyscale.util import ( # pylint:disable=private-import
78
84
  _client,
79
85
  _get_aws_efs_mount_target_ip,
@@ -1411,7 +1417,7 @@ class CloudController(BaseController):
1411
1417
  )
1412
1418
  if enable_log_ingestion is not None:
1413
1419
  self._update_customer_aggregated_logs_config(
1414
- cloud_id=cloud_id, is_enabled=enable_log_ingestion,
1420
+ cloud_id=cloud_id, is_enabled=enable_log_ingestion, # type: ignore
1415
1421
  )
1416
1422
  self.log.info(
1417
1423
  f"Successfully updated log ingestion configuration for cloud, "
@@ -1552,7 +1558,7 @@ class CloudController(BaseController):
1552
1558
  cloud_resource=cloud_resource,
1553
1559
  boto3_session=boto3_session,
1554
1560
  region=cloud.region,
1555
- cloud_id=cloud_id,
1561
+ cloud_id=cloud_id, # type: ignore
1556
1562
  is_bring_your_own_resource=cloud.is_bring_your_own_resource,
1557
1563
  is_private_network=cloud.is_private_cloud
1558
1564
  if cloud.is_private_cloud
@@ -1575,7 +1581,7 @@ class CloudController(BaseController):
1575
1581
  project_id=project_id,
1576
1582
  host_project_id=host_project_id,
1577
1583
  region=cloud.region,
1578
- cloud_id=cloud_id,
1584
+ cloud_id=cloud_id, # type: ignore
1579
1585
  yes=False,
1580
1586
  strict=strict,
1581
1587
  is_private_service_cloud=cloud.is_private_service_cloud,
@@ -3539,8 +3545,8 @@ class CloudController(BaseController):
3539
3545
  )
3540
3546
  try:
3541
3547
  self._edit_aws_cloud(
3542
- cloud_id=cloud_id,
3543
- cloud_name=cloud_name,
3548
+ cloud_id=cloud_id, # type: ignore
3549
+ cloud_name=cloud_name, # type: ignore
3544
3550
  cloud=cloud,
3545
3551
  cloud_resource=cloud_resource,
3546
3552
  aws_s3_id=aws_s3_id,
@@ -3593,8 +3599,8 @@ class CloudController(BaseController):
3593
3599
  )
3594
3600
  try:
3595
3601
  self._edit_gcp_cloud(
3596
- cloud_id=cloud_id,
3597
- cloud_name=cloud_name,
3602
+ cloud_id=cloud_id, # type: ignore
3603
+ cloud_name=cloud_name, # type: ignore
3598
3604
  cloud=cloud,
3599
3605
  cloud_resource=cloud_resource,
3600
3606
  gcp_filestore_instance_id=gcp_filestore_instance_id,
@@ -3643,3 +3649,140 @@ class CloudController(BaseController):
3643
3649
  )
3644
3650
 
3645
3651
  ### End of edit cloud ###
3652
+
3653
+ def generate_jobs_report(self, cloud_id: str, csv: bool, out_path: str) -> None:
3654
+ end_time = datetime.now()
3655
+ start_time = end_time - timedelta(days=7)
3656
+
3657
+ full_results = []
3658
+ paging_token: Optional[str] = None
3659
+ count_per_page = 20
3660
+ curr_page_results = None
3661
+ total_jobs: Optional[int] = None
3662
+
3663
+ with Progress() as progress:
3664
+ download_task = progress.add_task("Downloading jobs...", total=None)
3665
+
3666
+ while curr_page_results is None or len(curr_page_results) == count_per_page:
3667
+ response = self.api_client.list_job_reports_api_v2_job_reports_get(
3668
+ cloud_id,
3669
+ start_time=start_time,
3670
+ end_time=end_time,
3671
+ paging_token=paging_token,
3672
+ count=count_per_page,
3673
+ )
3674
+ curr_page_results = response.results
3675
+ full_results.extend(curr_page_results)
3676
+ paging_token = response.metadata.next_paging_token
3677
+ total_jobs = response.metadata.total
3678
+ progress.update(
3679
+ download_task, total=total_jobs, advance=len(curr_page_results)
3680
+ )
3681
+
3682
+ progress.update(download_task, completed=total_jobs)
3683
+
3684
+ if not full_results:
3685
+ self.log.info("No jobs found in the last 7 days.")
3686
+ return
3687
+
3688
+ filtered_results = [
3689
+ job
3690
+ for job in full_results
3691
+ if job.job_state in TERMINAL_HA_JOB_STATES and job.job_report is not None
3692
+ ]
3693
+ filtered_results.sort(key=lambda x: x.created_at)
3694
+
3695
+ with open(out_path, "w") as out_file:
3696
+ if csv:
3697
+ out_file.write(
3698
+ "Job ID,Job name,Job state,Created at,Finished at,Duration,Unused CPU hours,Unused GPU hours,Max concurrent instances\n"
3699
+ )
3700
+ for job in track(filtered_results, description="Generating report..."):
3701
+ job_state = HA_JOB_STATE_TO_JOB_STATE[job.job_state]
3702
+ if job.finished_at is not None:
3703
+ duration = str(job.finished_at - job.created_at)
3704
+ finished_at = str(job.finished_at)
3705
+ else:
3706
+ duration = ""
3707
+ finished_at = ""
3708
+ unused_cpu_hours = job.job_report.unused_cpu_hours or ""
3709
+ unused_gpu_hours = job.job_report.unused_gpu_hours or ""
3710
+ max_instances_launched = job.job_report.max_instances_launched or ""
3711
+
3712
+ out_file.write(
3713
+ f"{job.job_id},{job.job_name},{job_state},{str(job.created_at)},{finished_at},{duration},{unused_cpu_hours},{unused_gpu_hours},{max_instances_launched}\n"
3714
+ )
3715
+ else:
3716
+ out_file.write(
3717
+ f"""
3718
+ <html>
3719
+ <head>
3720
+ <title>Jobs Report - {str(end_time)}</title>
3721
+ <style>
3722
+ table {{
3723
+ border: 1px solid black;
3724
+ border-collapse: collapse;
3725
+ }}
3726
+ th, td {{
3727
+ border: 1px solid black;
3728
+ border-collapse: collapse;
3729
+ padding: 8px;
3730
+ }}
3731
+ </style>
3732
+ </head>
3733
+ <body>
3734
+ <h1>Job Report - {str(end_time)}</h1>
3735
+ <p>Total jobs reported (finished jobs): {len(filtered_results)}</p>
3736
+ <p>Total jobs in the last 7 days: {total_jobs}</p>
3737
+ <table>
3738
+ <thead>
3739
+ <tr>
3740
+ <th>Job ID</th>
3741
+ <th>Job name</th>
3742
+ <th>Job state</th>
3743
+ <th>Created at</th>
3744
+ <th>Finished at</th>
3745
+ <th>Duration</th>
3746
+ <th>Unused CPU hours</th>
3747
+ <th>Unused GPU hours</th>
3748
+ <th>Max concurrent instances</th>
3749
+ </tr>
3750
+ </thead>
3751
+ <tbody>
3752
+ """
3753
+ )
3754
+
3755
+ for job in track(filtered_results, description="Generating report..."):
3756
+ job_state = HA_JOB_STATE_TO_JOB_STATE[job.job_state]
3757
+ if job.finished_at is not None:
3758
+ duration = str(job.finished_at - job.created_at)
3759
+ finished_at = str(job.finished_at)
3760
+ else:
3761
+ duration = ""
3762
+ finished_at = ""
3763
+ unused_cpu_hours = job.job_report.unused_cpu_hours or ""
3764
+ unused_gpu_hours = job.job_report.unused_gpu_hours or ""
3765
+ max_instances_launched = job.job_report.max_instances_launched or ""
3766
+
3767
+ out_file.write(
3768
+ f"""
3769
+ <tr>
3770
+ <td><a target="_blank" rel="noreferrer" href="{ANYSCALE_HOST}/jobs/{job.job_id}">{job.job_id}</a></td>
3771
+ <td>{job.job_name}</td>
3772
+ <td>{job_state}</td>
3773
+ <td>{str(job.created_at)}</td>
3774
+ <td>{finished_at}</td>
3775
+ <td>{duration}</td>
3776
+ <td>{unused_cpu_hours}</td>
3777
+ <td>{unused_gpu_hours}</td>
3778
+ <td>{max_instances_launched}</td>
3779
+ </tr>
3780
+ """
3781
+ )
3782
+
3783
+ out_file.write(
3784
+ """
3785
+ </tbody>
3786
+ </table>
3787
+ """
3788
+ )
@@ -522,6 +522,7 @@ class ClusterController(BaseController):
522
522
  api_client=self.api_client,
523
523
  anyscale_api_client=self.anyscale_api_client,
524
524
  )
525
+ assert project_id is not None
525
526
  cluster_name = self._get_or_generate_cluster_name(project_id, cluster_name)
526
527
  return project_id, cluster_name
527
528
 
@@ -80,7 +80,7 @@ class JobController(BaseController):
80
80
  log: Optional[LogsLogger] = None,
81
81
  initialize_auth_api_client: bool = True,
82
82
  raise_structured_exception: bool = False,
83
- auth_token: str = None,
83
+ auth_token: Optional[str] = None,
84
84
  ):
85
85
  if log is None:
86
86
  log = LogsLogger()
@@ -354,6 +354,7 @@ class ServiceController(BaseController):
354
354
  )
355
355
 
356
356
  else:
357
+ assert ray_serve_config is not None
357
358
  ray_serve_config["runtime_env"] = override_runtime_env_config(
358
359
  runtime_env=ray_serve_config.get("runtime_env"),
359
360
  anyscale_api_client=self.sdk,
@@ -36,13 +36,13 @@ def build(
36
36
  *,
37
37
  name: str,
38
38
  ray_version: Optional[str] = None,
39
- _sdk: PrivateImageSDK
39
+ _private_sdk: Optional[PrivateImageSDK] = None,
40
40
  ) -> str:
41
41
  """Build an image from a Containerfile.
42
42
 
43
43
  Returns the URI of the image.
44
44
  """
45
- return _sdk.build_image_from_containerfile_with_image_uri(
45
+ return _private_sdk.build_image_from_containerfile_with_image_uri( # type: ignore
46
46
  name, containerfile, ray_version=ray_version
47
47
  )
48
48
 
@@ -68,12 +68,12 @@ _GET_ARG_DOCSTRINGS = {
68
68
  doc_py_example=_GET_EXAMPLE,
69
69
  arg_docstrings=_GET_ARG_DOCSTRINGS,
70
70
  )
71
- def get(*, name: str, _sdk: PrivateImageSDK) -> ImageBuild:
71
+ def get(*, name: str, _private_sdk: Optional[PrivateImageSDK] = None) -> ImageBuild:
72
72
  """The name can contain an optional version tag, i.e., 'name:version'.
73
73
 
74
74
  If no version is provided, the latest one will be returned.
75
75
  """
76
- return _sdk.get(name)
76
+ return _private_sdk.get(name) # type: ignore
77
77
 
78
78
 
79
79
  _REGISTER_EXAMPLE = """
@@ -102,14 +102,14 @@ def register(
102
102
  name: str,
103
103
  ray_version: Optional[str] = None,
104
104
  registry_login_secret: Optional[str] = None,
105
- _sdk: PrivateImageSDK
105
+ _private_sdk: Optional[PrivateImageSDK] = None,
106
106
  ) -> str:
107
107
  """
108
108
  Registers a BYOD image with a container image name.
109
109
 
110
110
  Returns the URI of the image.
111
111
  """
112
- return _sdk.register_byod_image_with_name(
112
+ return _private_sdk.register_byod_image_with_name( # type: ignore
113
113
  image_uri,
114
114
  registry_login_secret=registry_login_secret,
115
115
  ray_version=ray_version,
@@ -33,6 +33,26 @@ from anyscale.utils.runtime_env import parse_requirements_file
33
33
 
34
34
  logger = BlockLogger()
35
35
 
36
+ HA_JOB_STATE_TO_JOB_STATE = {
37
+ HaJobStates.UPDATING: JobState.RUNNING,
38
+ HaJobStates.RUNNING: JobState.RUNNING,
39
+ HaJobStates.RESTARTING: JobState.RUNNING,
40
+ HaJobStates.CLEANING_UP: JobState.RUNNING,
41
+ HaJobStates.PENDING: JobState.STARTING,
42
+ HaJobStates.AWAITING_CLUSTER_START: JobState.STARTING,
43
+ HaJobStates.SUCCESS: JobState.SUCCEEDED,
44
+ HaJobStates.ERRORED: JobState.FAILED,
45
+ HaJobStates.TERMINATED: JobState.FAILED,
46
+ HaJobStates.BROKEN: JobState.FAILED,
47
+ HaJobStates.OUT_OF_RETRIES: JobState.FAILED,
48
+ }
49
+
50
+ TERMINAL_HA_JOB_STATES = [
51
+ HaJobStates.SUCCESS,
52
+ HaJobStates.TERMINATED,
53
+ HaJobStates.OUT_OF_RETRIES,
54
+ ]
55
+
36
56
 
37
57
  class PrivateJobSDK(WorkloadSDK):
38
58
  _POLLING_INTERVAL_SECONDS = 10.0
@@ -215,20 +235,6 @@ class PrivateJobSDK(WorkloadSDK):
215
235
  )
216
236
  return job.id
217
237
 
218
- _HA_JOB_STATE_TO_JOB_STATE = {
219
- HaJobStates.UPDATING: JobState.RUNNING,
220
- HaJobStates.RUNNING: JobState.RUNNING,
221
- HaJobStates.RESTARTING: JobState.RUNNING,
222
- HaJobStates.CLEANING_UP: JobState.RUNNING,
223
- HaJobStates.PENDING: JobState.STARTING,
224
- HaJobStates.AWAITING_CLUSTER_START: JobState.STARTING,
225
- HaJobStates.SUCCESS: JobState.SUCCEEDED,
226
- HaJobStates.ERRORED: JobState.FAILED,
227
- HaJobStates.TERMINATED: JobState.FAILED,
228
- HaJobStates.BROKEN: JobState.FAILED,
229
- HaJobStates.OUT_OF_RETRIES: JobState.FAILED,
230
- }
231
-
232
238
  _BACKEND_JOB_STATUS_TO_JOB_RUN_STATE = {
233
239
  BackendJobStatus.RUNNING: JobRunState.RUNNING,
234
240
  BackendJobStatus.COMPLETED: JobRunState.SUCCEEDED,
@@ -241,9 +247,7 @@ class PrivateJobSDK(WorkloadSDK):
241
247
 
242
248
  def _job_state_from_job_model(self, model: ProductionJob) -> JobState:
243
249
  ha_state = model.state.current_state if model.state else None
244
- return cast(
245
- JobState, self._HA_JOB_STATE_TO_JOB_STATE.get(ha_state, JobState.UNKNOWN)
246
- )
250
+ return cast(JobState, HA_JOB_STATE_TO_JOB_STATE.get(ha_state, JobState.UNKNOWN))
247
251
 
248
252
  def _job_run_model_to_job_run_status(self, run: Job) -> JobRunStatus:
249
253
  state = self._BACKEND_JOB_STATUS_TO_JOB_RUN_STATE.get(
@@ -358,12 +362,6 @@ class PrivateJobSDK(WorkloadSDK):
358
362
  self.logger.info(f"Marked job '{job_model.name}' for termination")
359
363
  return job_model.id
360
364
 
361
- _TERMINAL_HA_JOB_STATES = [
362
- HaJobStates.SUCCESS,
363
- HaJobStates.TERMINATED,
364
- HaJobStates.OUT_OF_RETRIES,
365
- ]
366
-
367
365
  def archive(
368
366
  self,
369
367
  *,
@@ -377,7 +375,7 @@ class PrivateJobSDK(WorkloadSDK):
377
375
  )
378
376
 
379
377
  ha_state = job_model.state.current_state if job_model.state else None
380
- if ha_state not in self._TERMINAL_HA_JOB_STATES:
378
+ if ha_state not in TERMINAL_HA_JOB_STATES:
381
379
  raise RuntimeError(
382
380
  f"Job with ID '{job_model.id}' has not reached a terminal state and cannot be archived."
383
381
  )
anyscale/job/commands.py CHANGED
@@ -54,12 +54,12 @@ _SUBMIT_ARG_DOCSTRINGS = {"config": "The config options defining the job."}
54
54
  doc_py_example=_SUBMIT_EXAMPLE,
55
55
  arg_docstrings=_SUBMIT_ARG_DOCSTRINGS,
56
56
  )
57
- def submit(config: JobConfig, *, _sdk: PrivateJobSDK) -> str:
57
+ def submit(config: JobConfig, *, _private_sdk: Optional[PrivateJobSDK] = None) -> str:
58
58
  """Submit a job.
59
59
 
60
60
  Returns the id of the submitted job.
61
61
  """
62
- return _sdk.submit(config)
62
+ return _private_sdk.submit(config) # type: ignore
63
63
 
64
64
 
65
65
  _STATUS_EXAMPLE = """
@@ -89,12 +89,12 @@ def status(
89
89
  id: Optional[str] = None, # noqa: A002
90
90
  cloud: Optional[str] = None,
91
91
  project: Optional[str] = None,
92
- _sdk: PrivateJobSDK,
92
+ _private_sdk: Optional[PrivateJobSDK] = None,
93
93
  **_kwargs: Dict[str, Any],
94
94
  ) -> JobStatus:
95
95
  """Get the status of a job."""
96
96
  id = _resolve_id_from_args(id, _kwargs) # noqa: A001
97
- return _sdk.status(name=name, job_id=id, cloud=cloud, project=project)
97
+ return _private_sdk.status(name=name, job_id=id, cloud=cloud, project=project) # type: ignore
98
98
 
99
99
 
100
100
  _TERMINATE_EXAMPLE = """
@@ -123,7 +123,7 @@ def terminate(
123
123
  id: Optional[str] = None, # noqa: A002
124
124
  cloud: Optional[str] = None,
125
125
  project: Optional[str] = None,
126
- _sdk: PrivateJobSDK,
126
+ _private_sdk: Optional[PrivateJobSDK] = None,
127
127
  **_kwargs: Dict[str, Any],
128
128
  ) -> str:
129
129
  """Terminate a job.
@@ -133,7 +133,7 @@ def terminate(
133
133
  Returns the id of the terminated job.
134
134
  """
135
135
  id = _resolve_id_from_args(id, _kwargs) # noqa: A001
136
- return _sdk.terminate(name=name, job_id=id, cloud=cloud, project=project)
136
+ return _private_sdk.terminate(name=name, job_id=id, cloud=cloud, project=project) # type: ignore
137
137
 
138
138
 
139
139
  _ARCHIVE_EXAMPLE = """
@@ -162,7 +162,7 @@ def archive(
162
162
  id: Optional[str] = None, # noqa: A002
163
163
  cloud: Optional[str] = None,
164
164
  project: Optional[str] = None,
165
- _sdk: PrivateJobSDK,
165
+ _private_sdk: Optional[PrivateJobSDK] = None,
166
166
  **_kwargs: Dict[str, Any],
167
167
  ) -> str:
168
168
  """Archive a job.
@@ -172,7 +172,7 @@ def archive(
172
172
  Returns the id of the archived job.
173
173
  """
174
174
  id = _resolve_id_from_args(id, _kwargs) # noqa: A001
175
- return _sdk.archive(name=name, job_id=id, cloud=cloud, project=project)
175
+ return _private_sdk.archive(name=name, job_id=id, cloud=cloud, project=project) # type: ignore
176
176
 
177
177
 
178
178
  _WAIT_EXAMPLE = """\
@@ -204,12 +204,12 @@ def wait(
204
204
  project: Optional[str] = None,
205
205
  state: Union[JobState, str] = JobState.SUCCEEDED,
206
206
  timeout_s: float = 1800,
207
- _sdk: PrivateJobSDK,
207
+ _private_sdk: Optional[PrivateJobSDK] = None,
208
208
  **_kwargs: Dict[str, Any],
209
209
  ):
210
210
  """"Wait for a job to enter a specific state."""
211
211
  id = _resolve_id_from_args(id, _kwargs) # noqa: A001
212
- _sdk.wait(
212
+ _private_sdk.wait( # type: ignore
213
213
  name=name,
214
214
  job_id=id,
215
215
  cloud=cloud,
@@ -251,12 +251,12 @@ def get_logs(
251
251
  run: Optional[str] = None,
252
252
  mode: Union[str, JobLogMode] = JobLogMode.TAIL,
253
253
  max_lines: Optional[int] = None,
254
- _sdk: PrivateJobSDK,
254
+ _private_sdk: Optional[PrivateJobSDK] = None,
255
255
  **_kwargs: Dict[str, Any],
256
256
  ) -> str:
257
257
  """Query the jobs for a job run."""
258
258
  id = _resolve_id_from_args(id, _kwargs) # noqa: A001
259
- return _sdk.get_logs(
259
+ return _private_sdk.get_logs( # type: ignore
260
260
  job_id=id,
261
261
  name=name,
262
262
  cloud=cloud,
@@ -1,4 +1,4 @@
1
- from typing import Dict, List, Tuple
1
+ from typing import Dict, List, Optional, Tuple
2
2
 
3
3
  from anyscale._private.sdk import sdk_command
4
4
  from anyscale.organization_invitation._private.organization_invitation_sdk import (
@@ -45,13 +45,15 @@ _DELETE_ARG_DOCSTRINGS = {
45
45
  arg_docstrings=_CREATE_ARG_DOCSTRINGS,
46
46
  )
47
47
  def create(
48
- emails: List[str], *, _sdk: PrivateOrganizationInvitationSDK
48
+ emails: List[str],
49
+ *,
50
+ _private_sdk: Optional[PrivateOrganizationInvitationSDK] = None
49
51
  ) -> Tuple[List[str], List[str]]:
50
52
  """Creates organization invitations for the provided emails.
51
53
 
52
54
  Returns a tuple of successful emails and error messages.
53
55
  """
54
- return _sdk.create(emails=emails)
56
+ return _private_sdk.create(emails=emails) # type: ignore
55
57
 
56
58
 
57
59
  @sdk_command(
@@ -61,13 +63,13 @@ def create(
61
63
  arg_docstrings=_LIST_ARG_DOCSTRINGS,
62
64
  )
63
65
  def list( # noqa: A001
64
- *, _sdk: PrivateOrganizationInvitationSDK
66
+ *, _private_sdk: Optional[PrivateOrganizationInvitationSDK] = None
65
67
  ) -> List[OrganizationInvitation]:
66
68
  """Lists organization invitations.
67
69
 
68
70
  Returns a list of organization invitations.
69
71
  """
70
- return _sdk.list()
72
+ return _private_sdk.list() # type: ignore
71
73
 
72
74
 
73
75
  @sdk_command(
@@ -76,9 +78,11 @@ def list( # noqa: A001
76
78
  doc_py_example=_DELETE_EXAMPLE,
77
79
  arg_docstrings=_DELETE_ARG_DOCSTRINGS,
78
80
  )
79
- def delete(email: str, *, _sdk: PrivateOrganizationInvitationSDK) -> str:
81
+ def delete(
82
+ email: str, *, _private_sdk: Optional[PrivateOrganizationInvitationSDK] = None
83
+ ) -> str:
80
84
  """Deletes an organization invitation.
81
85
 
82
86
  Returns the email of the deleted organization invitation.
83
87
  """
84
- return _sdk.delete(email)
88
+ return _private_sdk.delete(email) # type: ignore
@@ -29,7 +29,7 @@ class ProjectSDK:
29
29
  )
30
30
  def add_collaborators( # noqa: F811
31
31
  self, cloud: str, project: str, collaborators: List[CreateProjectCollaborator],
32
- ) -> str:
32
+ ) -> None:
33
33
  """Batch add collaborators to a project.
34
34
  """
35
- return self._private_sdk.add_collaborators(cloud, project, collaborators)
35
+ self._private_sdk.add_collaborators(cloud, project, collaborators)
@@ -11,11 +11,11 @@ from anyscale.project.models import CreateProjectCollaborator
11
11
  class PrivateProjectSDK(BaseSDK):
12
12
  def add_collaborators(
13
13
  self, cloud: str, project: str, collaborators: List[CreateProjectCollaborator]
14
- ) -> str:
14
+ ) -> None:
15
15
  cloud_id = self.client.get_cloud_id(cloud_name=cloud, compute_config_id=None)
16
16
  project_id = self.client.get_project_id(parent_cloud_id=cloud_id, name=project)
17
17
 
18
- return self.client.add_project_collaborators(
18
+ self.client.add_project_collaborators(
19
19
  project_id=project_id,
20
20
  collaborators=[
21
21
  CreateUserProjectCollaborator(
@@ -1,4 +1,4 @@
1
- from typing import List
1
+ from typing import List, Optional
2
2
 
3
3
  from anyscale._private.sdk import sdk_command
4
4
  from anyscale.project._private.project_sdk import PrivateProjectSDK
@@ -49,8 +49,8 @@ def add_collaborators(
49
49
  project: str,
50
50
  collaborators: List[CreateProjectCollaborator],
51
51
  *,
52
- _sdk: PrivateProjectSDK
52
+ _private_sdk: Optional[PrivateProjectSDK] = None
53
53
  ) -> str:
54
54
  """Batch add collaborators to a project.
55
55
  """
56
- return _sdk.add_collaborators(cloud, project, collaborators)
56
+ return _private_sdk.add_collaborators(cloud, project, collaborators) # type: ignore
anyscale/project_utils.py CHANGED
@@ -442,7 +442,7 @@ def get_default_project(
442
442
  "Please specify a cloud for this command either through the cloud or "
443
443
  "compute config arguments."
444
444
  )
445
- default_project = anyscale_api_client.get_default_project(
445
+ default_project = anyscale_api_client.get_default_project( # type: ignore
446
446
  parent_cloud_id=parent_cloud_id
447
447
  ).result
448
448
  return default_project
@@ -87,11 +87,13 @@ _DISABLE_DOCSTRINGS = {
87
87
  arg_docstrings=_CREATE_DOCSTRINGS,
88
88
  )
89
89
  def create(
90
- create_resource_quota: CreateResourceQuota, *, _sdk: PrivateResourceQuotaSDK
90
+ create_resource_quota: CreateResourceQuota,
91
+ *,
92
+ _private_sdk: Optional[PrivateResourceQuotaSDK] = None
91
93
  ) -> ResourceQuota:
92
94
  """Create a resource quota.
93
95
  """
94
- return _sdk.create(create_resource_quota)
96
+ return _private_sdk.create(create_resource_quota) # type: ignore
95
97
 
96
98
 
97
99
  @sdk_command(
@@ -107,10 +109,10 @@ def list( # noqa: A001
107
109
  is_enabled: Optional[bool] = None,
108
110
  max_items: int = 20,
109
111
  *,
110
- _sdk: PrivateResourceQuotaSDK
112
+ _private_sdk: Optional[PrivateResourceQuotaSDK] = None
111
113
  ) -> List[ResourceQuota]:
112
114
  """List resource quotas. """
113
- return _sdk.list(name, cloud, creator_id, is_enabled, max_items,)
115
+ return _private_sdk.list(name, cloud, creator_id, is_enabled, max_items,) # type: ignore
114
116
 
115
117
 
116
118
  @sdk_command(
@@ -119,10 +121,12 @@ def list( # noqa: A001
119
121
  doc_py_example=_DELETE_EXAMPLE,
120
122
  arg_docstrings=_DELETE_DOCSTRINGS,
121
123
  )
122
- def delete(resource_quota_id: str, *, _sdk: PrivateResourceQuotaSDK):
124
+ def delete(
125
+ resource_quota_id: str, *, _private_sdk: Optional[PrivateResourceQuotaSDK] = None
126
+ ):
123
127
  """Delete a resource quota.
124
128
  """
125
- return _sdk.delete(resource_quota_id)
129
+ return _private_sdk.delete(resource_quota_id) # type: ignore
126
130
 
127
131
 
128
132
  @sdk_command(
@@ -131,10 +135,12 @@ def delete(resource_quota_id: str, *, _sdk: PrivateResourceQuotaSDK):
131
135
  doc_py_example=_ENABLE_EXAMPLE,
132
136
  arg_docstrings=_ENABLE_DOCSTRINGS,
133
137
  )
134
- def enable(resource_quota_id: str, *, _sdk: PrivateResourceQuotaSDK):
138
+ def enable(
139
+ resource_quota_id: str, *, _private_sdk: Optional[PrivateResourceQuotaSDK] = None
140
+ ):
135
141
  """Enable a resource quota.
136
142
  """
137
- return _sdk.set_status(resource_quota_id, True)
143
+ return _private_sdk.set_status(resource_quota_id, True) # type: ignore
138
144
 
139
145
 
140
146
  @sdk_command(
@@ -143,7 +149,9 @@ def enable(resource_quota_id: str, *, _sdk: PrivateResourceQuotaSDK):
143
149
  doc_py_example=_DISABLE_EXAMPLE,
144
150
  arg_docstrings=_DISABLE_DOCSTRINGS,
145
151
  )
146
- def disable(resource_quota_id: str, *, _sdk: PrivateResourceQuotaSDK):
152
+ def disable(
153
+ resource_quota_id: str, *, _private_sdk: Optional[PrivateResourceQuotaSDK] = None
154
+ ):
147
155
  """Disable a resource quota.
148
156
  """
149
- return _sdk.set_status(resource_quota_id, False)
157
+ return _private_sdk.set_status(resource_quota_id, False) # type: ignore