cyberdesk 1.9.0__py3-none-any.whl → 1.11.0__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.

Potentially problematic release.


This version of cyberdesk might be problematic. Click here for more details.

cyberdesk/__init__.py CHANGED
@@ -23,10 +23,11 @@ from .client import (
23
23
  RunAttachmentCreate,
24
24
  RunAttachmentUpdate,
25
25
  RunAttachmentResponse,
26
+ RunAttachmentDownloadUrlResponse,
26
27
  AttachmentType,
27
28
  )
28
29
 
29
- __version__ = "1.9.0"
30
+ __version__ = "1.11.0"
30
31
 
31
32
  __all__ = [
32
33
  "CyberdeskClient",
@@ -51,5 +52,6 @@ __all__ = [
51
52
  "RunAttachmentCreate",
52
53
  "RunAttachmentUpdate",
53
54
  "RunAttachmentResponse",
55
+ "RunAttachmentDownloadUrlResponse",
54
56
  "AttachmentType",
55
57
  ]
cyberdesk/client.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """Cyberdesk Python SDK Client."""
2
2
  from typing import Optional, Dict, Any, Union
3
3
  from uuid import UUID
4
+ from pathlib import Path
4
5
  import httpx
5
6
  from dataclasses import dataclass
6
7
 
@@ -27,6 +28,7 @@ from openapi_client.cyberdesk_cloud_client.api.runs import (
27
28
  get_run_v1_runs_run_id_get,
28
29
  update_run_v1_runs_run_id_patch,
29
30
  delete_run_v1_runs_run_id_delete,
31
+ bulk_create_runs_v1_runs_bulk_post,
30
32
  )
31
33
  from openapi_client.cyberdesk_cloud_client.api.connections import (
32
34
  list_connections_v1_connections_get,
@@ -45,6 +47,7 @@ from openapi_client.cyberdesk_cloud_client.api.run_attachments import (
45
47
  create_run_attachment_v1_run_attachments_post,
46
48
  get_run_attachment_v1_run_attachments_attachment_id_get,
47
49
  download_run_attachment_v1_run_attachments_attachment_id_download_get,
50
+ get_run_attachment_download_url_v1_run_attachments_attachment_id_download_url_get,
48
51
  update_run_attachment_v1_run_attachments_attachment_id_put,
49
52
  delete_run_attachment_v1_run_attachments_attachment_id_delete,
50
53
  )
@@ -62,6 +65,8 @@ from openapi_client.cyberdesk_cloud_client.models import (
62
65
  RunUpdate,
63
66
  RunResponse,
64
67
  RunStatus,
68
+ RunBulkCreate,
69
+ RunBulkCreateResponse,
65
70
  FileInput,
66
71
  ConnectionCreate,
67
72
  ConnectionResponse,
@@ -72,6 +77,7 @@ from openapi_client.cyberdesk_cloud_client.models import (
72
77
  RunAttachmentCreate,
73
78
  RunAttachmentUpdate,
74
79
  RunAttachmentResponse,
80
+ RunAttachmentDownloadUrlResponse,
75
81
  AttachmentType,
76
82
  PaginatedResponseMachineResponse,
77
83
  PaginatedResponseWorkflowResponse,
@@ -95,6 +101,8 @@ __all__ = [
95
101
  "RunUpdate",
96
102
  "RunResponse",
97
103
  "RunStatus",
104
+ "RunBulkCreate",
105
+ "RunBulkCreateResponse",
98
106
  "FileInput",
99
107
  "ConnectionCreate",
100
108
  "ConnectionResponse",
@@ -105,6 +113,7 @@ __all__ = [
105
113
  "RunAttachmentCreate",
106
114
  "RunAttachmentUpdate",
107
115
  "RunAttachmentResponse",
116
+ "RunAttachmentDownloadUrlResponse",
108
117
  "AttachmentType",
109
118
  ]
110
119
 
@@ -523,6 +532,60 @@ class RunsAPI:
523
532
  return ApiResponse(data={"success": True})
524
533
  except Exception as e:
525
534
  return ApiResponse(error=e)
535
+
536
+ async def bulk_create(self, data: RunBulkCreate) -> ApiResponse:
537
+ """Create multiple runs with the same configuration.
538
+
539
+ This method efficiently creates multiple runs:
540
+ - All runs are created in a single database transaction
541
+ - Temporal workflows are started asynchronously
542
+ - Returns immediately with created run details
543
+
544
+ Args:
545
+ data: RunBulkCreate object containing workflow_id, machine_id,
546
+ input_values, file_inputs, and count (max 1000)
547
+
548
+ Returns:
549
+ ApiResponse with RunBulkCreateResponse containing:
550
+ - created_runs: List of created RunResponse objects
551
+ - failed_count: Number of runs that failed to create
552
+ - errors: List of error messages for failed runs
553
+ """
554
+ try:
555
+ response = await bulk_create_runs_v1_runs_bulk_post.asyncio(
556
+ client=self.client,
557
+ body=data
558
+ )
559
+ return ApiResponse(data=response)
560
+ except Exception as e:
561
+ return ApiResponse(error=e)
562
+
563
+ def bulk_create_sync(self, data: RunBulkCreate) -> ApiResponse:
564
+ """Create multiple runs with the same configuration (synchronous).
565
+
566
+ This method efficiently creates multiple runs:
567
+ - All runs are created in a single database transaction
568
+ - Temporal workflows are started asynchronously
569
+ - Returns immediately with created run details
570
+
571
+ Args:
572
+ data: RunBulkCreate object containing workflow_id, machine_id,
573
+ input_values, file_inputs, and count (max 1000)
574
+
575
+ Returns:
576
+ ApiResponse with RunBulkCreateResponse containing:
577
+ - created_runs: List of created RunResponse objects
578
+ - failed_count: Number of runs that failed to create
579
+ - errors: List of error messages for failed runs
580
+ """
581
+ try:
582
+ response = bulk_create_runs_v1_runs_bulk_post.sync(
583
+ client=self.client,
584
+ body=data
585
+ )
586
+ return ApiResponse(data=response)
587
+ except Exception as e:
588
+ return ApiResponse(error=e)
526
589
 
527
590
 
528
591
  class ConnectionsAPI:
@@ -847,14 +910,75 @@ class RunAttachmentsAPI:
847
910
  except Exception as e:
848
911
  return ApiResponse(error=e)
849
912
 
913
+ async def get_download_url(
914
+ self,
915
+ attachment_id: str,
916
+ expires_in: Optional[int] = None
917
+ ) -> ApiResponse:
918
+ """Get a signed download URL for a run attachment.
919
+
920
+ The returned URL will trigger an automatic download when accessed in a browser.
921
+
922
+ Args:
923
+ attachment_id: The ID of the attachment
924
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
925
+
926
+ Returns:
927
+ ApiResponse with RunAttachmentDownloadUrlResponse containing:
928
+ - url: The signed download URL
929
+ - expires_in: The expiration time in seconds
930
+ """
931
+ try:
932
+ response = await get_run_attachment_download_url_v1_run_attachments_attachment_id_download_url_get.asyncio(
933
+ client=self.client,
934
+ attachment_id=_to_uuid(attachment_id),
935
+ expires_in=_to_unset_or_value(expires_in)
936
+ )
937
+ return ApiResponse(data=response)
938
+ except Exception as e:
939
+ return ApiResponse(error=e)
940
+
941
+ def get_download_url_sync(
942
+ self,
943
+ attachment_id: str,
944
+ expires_in: Optional[int] = None
945
+ ) -> ApiResponse:
946
+ """Get a signed download URL for a run attachment (synchronous).
947
+
948
+ The returned URL will trigger an automatic download when accessed in a browser.
949
+
950
+ Args:
951
+ attachment_id: The ID of the attachment
952
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
953
+
954
+ Returns:
955
+ ApiResponse with RunAttachmentDownloadUrlResponse containing:
956
+ - url: The signed download URL
957
+ - expires_in: The expiration time in seconds
958
+ """
959
+ try:
960
+ response = get_run_attachment_download_url_v1_run_attachments_attachment_id_download_url_get.sync(
961
+ client=self.client,
962
+ attachment_id=_to_uuid(attachment_id),
963
+ expires_in=_to_unset_or_value(expires_in)
964
+ )
965
+ return ApiResponse(data=response)
966
+ except Exception as e:
967
+ return ApiResponse(error=e)
968
+
850
969
  async def download(self, attachment_id: str) -> ApiResponse:
851
- """Download a run attachment file.
970
+ """Download a run attachment file directly.
971
+
972
+ This method returns the raw file content as bytes. For a download URL instead,
973
+ use get_download_url().
974
+
975
+ Args:
976
+ attachment_id: The ID of the attachment to download
852
977
 
853
978
  Returns:
854
- ApiResponse with data containing the file bytes or a download URL
979
+ ApiResponse with data containing the raw file bytes
855
980
  """
856
981
  try:
857
- # The download endpoint typically returns binary data or a redirect URL
858
982
  response = await download_run_attachment_v1_run_attachments_attachment_id_download_get.asyncio(
859
983
  client=self.client,
860
984
  attachment_id=_to_uuid(attachment_id)
@@ -864,10 +988,16 @@ class RunAttachmentsAPI:
864
988
  return ApiResponse(error=e)
865
989
 
866
990
  def download_sync(self, attachment_id: str) -> ApiResponse:
867
- """Download a run attachment file (synchronous).
991
+ """Download a run attachment file directly (synchronous).
992
+
993
+ This method returns the raw file content as bytes. For a download URL instead,
994
+ use get_download_url_sync().
995
+
996
+ Args:
997
+ attachment_id: The ID of the attachment to download
868
998
 
869
999
  Returns:
870
- ApiResponse with data containing the file bytes or a download URL
1000
+ ApiResponse with data containing the raw file bytes
871
1001
  """
872
1002
  try:
873
1003
  response = download_run_attachment_v1_run_attachments_attachment_id_download_get.sync(
@@ -923,6 +1053,104 @@ class RunAttachmentsAPI:
923
1053
  return ApiResponse(data={"success": True})
924
1054
  except Exception as e:
925
1055
  return ApiResponse(error=e)
1056
+
1057
+ async def save_to_file(
1058
+ self,
1059
+ attachment_id: str,
1060
+ output_path: Optional[Union[str, Path]] = None,
1061
+ use_original_filename: bool = True
1062
+ ) -> ApiResponse:
1063
+ """Download and save a run attachment to a file.
1064
+
1065
+ This is a convenience method that combines getting attachment info
1066
+ and downloading the file content.
1067
+
1068
+ Args:
1069
+ attachment_id: The ID of the attachment to download
1070
+ output_path: Path where to save the file. If None and use_original_filename
1071
+ is True, saves to current directory with original filename.
1072
+ use_original_filename: If True and output_path is a directory, uses the
1073
+ attachment's original filename.
1074
+
1075
+ Returns:
1076
+ ApiResponse with data containing the saved file path
1077
+ """
1078
+ try:
1079
+ # Get attachment info for filename
1080
+ info_response = await self.get(attachment_id)
1081
+ if info_response.error:
1082
+ return info_response
1083
+
1084
+ attachment_info = info_response.data
1085
+
1086
+ # Download the file content
1087
+ download_response = await self.download(attachment_id)
1088
+ if download_response.error:
1089
+ return download_response
1090
+
1091
+ # Determine output path
1092
+ if output_path is None:
1093
+ output_path = Path(attachment_info.filename)
1094
+ else:
1095
+ output_path = Path(output_path)
1096
+ if output_path.is_dir() and use_original_filename:
1097
+ output_path = output_path / attachment_info.filename
1098
+
1099
+ # Save to file
1100
+ output_path.write_bytes(download_response.data)
1101
+
1102
+ return ApiResponse(data={"path": str(output_path), "size": len(download_response.data)})
1103
+ except Exception as e:
1104
+ return ApiResponse(error=e)
1105
+
1106
+ def save_to_file_sync(
1107
+ self,
1108
+ attachment_id: str,
1109
+ output_path: Optional[Union[str, Path]] = None,
1110
+ use_original_filename: bool = True
1111
+ ) -> ApiResponse:
1112
+ """Download and save a run attachment to a file (synchronous).
1113
+
1114
+ This is a convenience method that combines getting attachment info
1115
+ and downloading the file content.
1116
+
1117
+ Args:
1118
+ attachment_id: The ID of the attachment to download
1119
+ output_path: Path where to save the file. If None and use_original_filename
1120
+ is True, saves to current directory with original filename.
1121
+ use_original_filename: If True and output_path is a directory, uses the
1122
+ attachment's original filename.
1123
+
1124
+ Returns:
1125
+ ApiResponse with data containing the saved file path
1126
+ """
1127
+ try:
1128
+ # Get attachment info for filename
1129
+ info_response = self.get_sync(attachment_id)
1130
+ if info_response.error:
1131
+ return info_response
1132
+
1133
+ attachment_info = info_response.data
1134
+
1135
+ # Download the file content
1136
+ download_response = self.download_sync(attachment_id)
1137
+ if download_response.error:
1138
+ return download_response
1139
+
1140
+ # Determine output path
1141
+ if output_path is None:
1142
+ output_path = Path(attachment_info.filename)
1143
+ else:
1144
+ output_path = Path(output_path)
1145
+ if output_path.is_dir() and use_original_filename:
1146
+ output_path = output_path / attachment_info.filename
1147
+
1148
+ # Save to file
1149
+ output_path.write_bytes(download_response.data)
1150
+
1151
+ return ApiResponse(data={"path": str(output_path), "size": len(download_response.data)})
1152
+ except Exception as e:
1153
+ return ApiResponse(error=e)
926
1154
 
927
1155
 
928
1156
  class CyberdeskClient:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cyberdesk
3
- Version: 1.9.0
3
+ Version: 1.11.0
4
4
  Summary: The official Python SDK for Cyberdesk
5
5
  Author-email: Cyberdesk Team <dev@cyberdesk.io>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
- cyberdesk/__init__.py,sha256=ZjS5ouIl0k25SujyFhyiuN6Z8YP0qGO7cYvDmAYoT3A,1079
2
- cyberdesk/client.py,sha256=qmPJ7J1fzZaYWDGZ_xrFojLQSjMWWu_NsmRfZROZXAU,35026
3
- cyberdesk-1.9.0.dist-info/licenses/LICENSE,sha256=06Op63FCwGhuUOz__M8IZW5sxd29WxyGC4X5-Uih7IQ,1071
1
+ cyberdesk/__init__.py,sha256=DvzhtlhtYTy3_hWYIrSCHUjI8yX3BeBp-v_agpI_W8s,1158
2
+ cyberdesk/client.py,sha256=UkpItVaLFrhM7VoBndT1vBiZk6RrECy9segb4QCj9j4,44114
3
+ cyberdesk-1.11.0.dist-info/licenses/LICENSE,sha256=06Op63FCwGhuUOz__M8IZW5sxd29WxyGC4X5-Uih7IQ,1071
4
4
  openapi_client/cyberdesk_cloud_client/__init__.py,sha256=r_uVkNUL-SOK8j7-KiGMIKdinES5X8K1Q250ySX2F-A,158
5
5
  openapi_client/cyberdesk_cloud_client/client.py,sha256=o_mdLqyBCQstu5tS1WZFwqIEbGwkvWQ7eQjuCJw_5VY,12419
6
6
  openapi_client/cyberdesk_cloud_client/errors.py,sha256=gO8GBmKqmSNgAg-E5oT-oOyxztvp7V_6XG7OUTT15q0,546
@@ -46,11 +46,13 @@ openapi_client/cyberdesk_cloud_client/api/request_logs/update_request_log_v1_req
46
46
  openapi_client/cyberdesk_cloud_client/api/run_attachments/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
47
47
  openapi_client/cyberdesk_cloud_client/api/run_attachments/create_run_attachment_v1_run_attachments_post.py,sha256=DTcoKhj8uflj1FUJAIKrVhbCXaQIjjWH3ZpijDJZdJI,5216
48
48
  openapi_client/cyberdesk_cloud_client/api/run_attachments/delete_run_attachment_v1_run_attachments_attachment_id_delete.py,sha256=BUamhNNCzRL_irucvhvlOxkqnOxNv0wUUDUrHvmnDc0,4465
49
- openapi_client/cyberdesk_cloud_client/api/run_attachments/download_run_attachment_v1_run_attachments_attachment_id_download_get.py,sha256=boplCuACwpIfPQt32CL-OxII1xKiVbFLWLlGg0WrlZM,4389
49
+ openapi_client/cyberdesk_cloud_client/api/run_attachments/download_run_attachment_v1_run_attachments_attachment_id_download_get.py,sha256=CGqC2lCQK1AbGCsIq2sA5PS8b1oA0VV5ysYvORuF8FY,4405
50
+ openapi_client/cyberdesk_cloud_client/api/run_attachments/get_run_attachment_download_url_v1_run_attachments_attachment_id_download_url_get.py,sha256=99FZWvi6f0Wlwd2SxFoudbH5t9H57lw1LMWFhf4J408,6560
50
51
  openapi_client/cyberdesk_cloud_client/api/run_attachments/get_run_attachment_v1_run_attachments_attachment_id_get.py,sha256=9Rkn4y-3mh-SMEnmvPLeo34Hhp9Bsk_Wb7sWw1xeDhA,4786
51
52
  openapi_client/cyberdesk_cloud_client/api/run_attachments/list_run_attachments_v1_run_attachments_get.py,sha256=LGcoHCLkujfTHgwzapuYV8Ve8y4yw_VZ3jkSK5Rt91o,7783
52
53
  openapi_client/cyberdesk_cloud_client/api/run_attachments/update_run_attachment_v1_run_attachments_attachment_id_put.py,sha256=4jsIek-Z4U5hbKHRMBsnJr0DgfOoY5B2sC22d5Af-UU,5395
53
54
  openapi_client/cyberdesk_cloud_client/api/runs/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
55
+ openapi_client/cyberdesk_cloud_client/api/runs/bulk_create_runs_v1_runs_bulk_post.py,sha256=e89ThcQxPj-PZBzyieS4SC4kswup9aKBSsc3K8btN3U,5809
54
56
  openapi_client/cyberdesk_cloud_client/api/runs/create_run_v1_runs_post.py,sha256=WarcoB_UIzZsTcvFGWAYZhjA0LsIY4wcP89wILtsTZs,5343
55
57
  openapi_client/cyberdesk_cloud_client/api/runs/delete_run_v1_runs_run_id_delete.py,sha256=ux5K74BTi5jarECVfTc5AxgAhDPfuFkt1XmaWWmRdLE,4116
56
58
  openapi_client/cyberdesk_cloud_client/api/runs/get_run_v1_runs_run_id_get.py,sha256=tWXVlLtiWl3XmAPQf4_V0SzPoenVKazWSiL4afDEmwE,4562
@@ -72,7 +74,7 @@ openapi_client/cyberdesk_cloud_client/api/workflows/get_workflow_v1_workflows_wo
72
74
  openapi_client/cyberdesk_cloud_client/api/workflows/get_workflow_versions_v1_workflows_workflow_id_versions_get.py,sha256=jBJJwJQfKBBYTX1FhSe7qWFxK0ZvYD_QKcrxTgo361U,5857
73
75
  openapi_client/cyberdesk_cloud_client/api/workflows/list_workflows_v1_workflows_get.py,sha256=xM1Ex78PdeJK2IrQ10ghKqk93FwNGOnVOPt666hUhwE,5626
74
76
  openapi_client/cyberdesk_cloud_client/api/workflows/update_workflow_v1_workflows_workflow_id_patch.py,sha256=G6l9aClbapqjCmDsjK01447iqRKhRFp9CnJDLHV8OBc,5705
75
- openapi_client/cyberdesk_cloud_client/models/__init__.py,sha256=jchhYiVrBiL2nnpIBY9Zvfhz4D5_NyHKMqq7Bgw747M,7981
77
+ openapi_client/cyberdesk_cloud_client/models/__init__.py,sha256=U7j2ivyaahQBknJMcN6FCPn0ppqnA69qtm98imKxtgk,8373
76
78
  openapi_client/cyberdesk_cloud_client/models/attachment_type.py,sha256=zqPOsSd2AmxGNqb5HQ6ZYBAYL8k-0UbWHhfAJYNHoro,161
77
79
  openapi_client/cyberdesk_cloud_client/models/connection_create.py,sha256=gCI36DmjJDZxzGFPbykyYw9k4QEf_4dVNz9b-xZfLo4,3288
78
80
  openapi_client/cyberdesk_cloud_client/models/connection_response.py,sha256=aFxqJX75wSEw5dZ-kvh3Wgv_haJ6xYJ7o72vSAbEtHY,5247
@@ -112,8 +114,12 @@ openapi_client/cyberdesk_cloud_client/models/request_log_create.py,sha256=6CNnBv
112
114
  openapi_client/cyberdesk_cloud_client/models/request_log_response.py,sha256=mU3lUdbLRFg9XppHnO-GjKcvt4M_BCG5CynWwU7ivZE,7445
113
115
  openapi_client/cyberdesk_cloud_client/models/request_log_update.py,sha256=VcXBNffDOoEYYBjwvdkuSWPz04BW3c8YTcqzlZRb0ns,5677
114
116
  openapi_client/cyberdesk_cloud_client/models/run_attachment_create.py,sha256=w58KmB9lLnE2N2EQJz_DP1PQj5OEL__t9ufdQFryp0A,4965
117
+ openapi_client/cyberdesk_cloud_client/models/run_attachment_download_url_response.py,sha256=CUeh3Zas29uwfpH5oMbQ_hhkpsZ_RH7ZA_RyfRsf8mY,1864
115
118
  openapi_client/cyberdesk_cloud_client/models/run_attachment_response.py,sha256=LZEFltiyC_bBVNlz3LM1H5MXFoBkVzk-CzNuvlTumJ4,5769
116
119
  openapi_client/cyberdesk_cloud_client/models/run_attachment_update.py,sha256=rGXcB21waSTXG0-mt0XhNcwoJI1PhBpBDUkLfp8mM-0,2573
120
+ openapi_client/cyberdesk_cloud_client/models/run_bulk_create.py,sha256=Mlz19LHQTwutkX1rddfSMCgQOZV1mc6SE4kDQyKplao,6350
121
+ openapi_client/cyberdesk_cloud_client/models/run_bulk_create_input_values_type_0.py,sha256=JxGOOYKueFx5NtvnXgf9z_sXbMByQrsjjQ3AmU8qG30,1305
122
+ openapi_client/cyberdesk_cloud_client/models/run_bulk_create_response.py,sha256=N9sMykvm6pC2fMMH_XVQI8wVc6-53qAHMb_qbNBo9-c,2886
117
123
  openapi_client/cyberdesk_cloud_client/models/run_create.py,sha256=hUMuozdNHMQwndTl-mCfQ8hGwPeJ_EkPeZEmAUQWMHc,6083
118
124
  openapi_client/cyberdesk_cloud_client/models/run_create_input_values_type_0.py,sha256=APV4O0GduU3fhHoJHMMOBk-h92Hf21c1ZU-pIsJoZpg,1282
119
125
  openapi_client/cyberdesk_cloud_client/models/run_response.py,sha256=zZUNgMVc8-Lmm_X3t_XzWdY1x_B7f3JixPWebfwl_40,10689
@@ -140,7 +146,7 @@ openapi_client/cyberdesk_cloud_client/models/workflow_create.py,sha256=Z7XG8k1js
140
146
  openapi_client/cyberdesk_cloud_client/models/workflow_response.py,sha256=kC_ZGUweaiogKqyRS1yjByHuYqZW0jzxuEyM9CIfFsc,6937
141
147
  openapi_client/cyberdesk_cloud_client/models/workflow_response_old_versions_type_0_item.py,sha256=W9AxxlBlN3rUwLDcoUx5H7MUiYA9UztfX9iEpNGlgAs,1340
142
148
  openapi_client/cyberdesk_cloud_client/models/workflow_update.py,sha256=_zMo2mJbYdKILygBXwebAD37SJJCUZOTkJkMOCzeNTA,4439
143
- cyberdesk-1.9.0.dist-info/METADATA,sha256=SrCf6y1nUAjvB1t2-I9DQF01Qyd0uiYHyixa2azjDE8,6791
144
- cyberdesk-1.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
145
- cyberdesk-1.9.0.dist-info/top_level.txt,sha256=qTYHZHVHh3VClNPQsiFFA8p8tmJgFGhq9G1COd-pX_A,25
146
- cyberdesk-1.9.0.dist-info/RECORD,,
149
+ cyberdesk-1.11.0.dist-info/METADATA,sha256=hk52QX5D5EjIW-pAoe08_Jywz5nnbfngJsGAdK3efGc,6792
150
+ cyberdesk-1.11.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
151
+ cyberdesk-1.11.0.dist-info/top_level.txt,sha256=qTYHZHVHh3VClNPQsiFFA8p8tmJgFGhq9G1COd-pX_A,25
152
+ cyberdesk-1.11.0.dist-info/RECORD,,
@@ -57,7 +57,7 @@ def sync_detailed(
57
57
 
58
58
  Download a run attachment file.
59
59
 
60
- Returns the file content as a streaming response.
60
+ Returns the raw file content as a streaming response.
61
61
 
62
62
  Args:
63
63
  attachment_id (UUID):
@@ -90,7 +90,7 @@ def sync(
90
90
 
91
91
  Download a run attachment file.
92
92
 
93
- Returns the file content as a streaming response.
93
+ Returns the raw file content as a streaming response.
94
94
 
95
95
  Args:
96
96
  attachment_id (UUID):
@@ -118,7 +118,7 @@ async def asyncio_detailed(
118
118
 
119
119
  Download a run attachment file.
120
120
 
121
- Returns the file content as a streaming response.
121
+ Returns the raw file content as a streaming response.
122
122
 
123
123
  Args:
124
124
  attachment_id (UUID):
@@ -149,7 +149,7 @@ async def asyncio(
149
149
 
150
150
  Download a run attachment file.
151
151
 
152
- Returns the file content as a streaming response.
152
+ Returns the raw file content as a streaming response.
153
153
 
154
154
  Args:
155
155
  attachment_id (UUID):
@@ -0,0 +1,209 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Optional, Union
3
+ from uuid import UUID
4
+
5
+ import httpx
6
+
7
+ from ... import errors
8
+ from ...client import AuthenticatedClient, Client
9
+ from ...models.http_validation_error import HTTPValidationError
10
+ from ...models.run_attachment_download_url_response import RunAttachmentDownloadUrlResponse
11
+ from ...types import UNSET, Response, Unset
12
+
13
+
14
+ def _get_kwargs(
15
+ attachment_id: UUID,
16
+ *,
17
+ expires_in: Union[Unset, int] = 300,
18
+ ) -> dict[str, Any]:
19
+ params: dict[str, Any] = {}
20
+
21
+ params["expires_in"] = expires_in
22
+
23
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
24
+
25
+ _kwargs: dict[str, Any] = {
26
+ "method": "get",
27
+ "url": f"/v1/run-attachments/{attachment_id}/download-url",
28
+ "params": params,
29
+ }
30
+
31
+ return _kwargs
32
+
33
+
34
+ def _parse_response(
35
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
36
+ ) -> Optional[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
37
+ if response.status_code == 200:
38
+ response_200 = RunAttachmentDownloadUrlResponse.from_dict(response.json())
39
+
40
+ return response_200
41
+ if response.status_code == 422:
42
+ response_422 = HTTPValidationError.from_dict(response.json())
43
+
44
+ return response_422
45
+ if client.raise_on_unexpected_status:
46
+ raise errors.UnexpectedStatus(response.status_code, response.content)
47
+ else:
48
+ return None
49
+
50
+
51
+ def _build_response(
52
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
53
+ ) -> Response[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
54
+ return Response(
55
+ status_code=HTTPStatus(response.status_code),
56
+ content=response.content,
57
+ headers=response.headers,
58
+ parsed=_parse_response(client=client, response=response),
59
+ )
60
+
61
+
62
+ def sync_detailed(
63
+ attachment_id: UUID,
64
+ *,
65
+ client: AuthenticatedClient,
66
+ expires_in: Union[Unset, int] = 300,
67
+ ) -> Response[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
68
+ """Get Run Attachment Download Url
69
+
70
+ Get a signed download URL for a run attachment file.
71
+
72
+ Returns a signed URL that triggers automatic download when accessed.
73
+
74
+ Args:
75
+ attachment_id: The ID of the attachment to download
76
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
77
+
78
+ Args:
79
+ attachment_id (UUID):
80
+ expires_in (Union[Unset, int]): URL expiration time in seconds (10-3600) Default: 300.
81
+
82
+ Raises:
83
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
84
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
85
+
86
+ Returns:
87
+ Response[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]
88
+ """
89
+
90
+ kwargs = _get_kwargs(
91
+ attachment_id=attachment_id,
92
+ expires_in=expires_in,
93
+ )
94
+
95
+ response = client.get_httpx_client().request(
96
+ **kwargs,
97
+ )
98
+
99
+ return _build_response(client=client, response=response)
100
+
101
+
102
+ def sync(
103
+ attachment_id: UUID,
104
+ *,
105
+ client: AuthenticatedClient,
106
+ expires_in: Union[Unset, int] = 300,
107
+ ) -> Optional[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
108
+ """Get Run Attachment Download Url
109
+
110
+ Get a signed download URL for a run attachment file.
111
+
112
+ Returns a signed URL that triggers automatic download when accessed.
113
+
114
+ Args:
115
+ attachment_id: The ID of the attachment to download
116
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
117
+
118
+ Args:
119
+ attachment_id (UUID):
120
+ expires_in (Union[Unset, int]): URL expiration time in seconds (10-3600) Default: 300.
121
+
122
+ Raises:
123
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
124
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
125
+
126
+ Returns:
127
+ Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]
128
+ """
129
+
130
+ return sync_detailed(
131
+ attachment_id=attachment_id,
132
+ client=client,
133
+ expires_in=expires_in,
134
+ ).parsed
135
+
136
+
137
+ async def asyncio_detailed(
138
+ attachment_id: UUID,
139
+ *,
140
+ client: AuthenticatedClient,
141
+ expires_in: Union[Unset, int] = 300,
142
+ ) -> Response[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
143
+ """Get Run Attachment Download Url
144
+
145
+ Get a signed download URL for a run attachment file.
146
+
147
+ Returns a signed URL that triggers automatic download when accessed.
148
+
149
+ Args:
150
+ attachment_id: The ID of the attachment to download
151
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
152
+
153
+ Args:
154
+ attachment_id (UUID):
155
+ expires_in (Union[Unset, int]): URL expiration time in seconds (10-3600) Default: 300.
156
+
157
+ Raises:
158
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
159
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
160
+
161
+ Returns:
162
+ Response[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]
163
+ """
164
+
165
+ kwargs = _get_kwargs(
166
+ attachment_id=attachment_id,
167
+ expires_in=expires_in,
168
+ )
169
+
170
+ response = await client.get_async_httpx_client().request(**kwargs)
171
+
172
+ return _build_response(client=client, response=response)
173
+
174
+
175
+ async def asyncio(
176
+ attachment_id: UUID,
177
+ *,
178
+ client: AuthenticatedClient,
179
+ expires_in: Union[Unset, int] = 300,
180
+ ) -> Optional[Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]]:
181
+ """Get Run Attachment Download Url
182
+
183
+ Get a signed download URL for a run attachment file.
184
+
185
+ Returns a signed URL that triggers automatic download when accessed.
186
+
187
+ Args:
188
+ attachment_id: The ID of the attachment to download
189
+ expires_in: URL expiration time in seconds (10-3600). Default: 300 (5 minutes)
190
+
191
+ Args:
192
+ attachment_id (UUID):
193
+ expires_in (Union[Unset, int]): URL expiration time in seconds (10-3600) Default: 300.
194
+
195
+ Raises:
196
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
197
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
198
+
199
+ Returns:
200
+ Union[HTTPValidationError, RunAttachmentDownloadUrlResponse]
201
+ """
202
+
203
+ return (
204
+ await asyncio_detailed(
205
+ attachment_id=attachment_id,
206
+ client=client,
207
+ expires_in=expires_in,
208
+ )
209
+ ).parsed
@@ -0,0 +1,200 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Optional, Union
3
+
4
+ import httpx
5
+
6
+ from ... import errors
7
+ from ...client import AuthenticatedClient, Client
8
+ from ...models.http_validation_error import HTTPValidationError
9
+ from ...models.run_bulk_create import RunBulkCreate
10
+ from ...models.run_bulk_create_response import RunBulkCreateResponse
11
+ from ...types import Response
12
+
13
+
14
+ def _get_kwargs(
15
+ *,
16
+ body: RunBulkCreate,
17
+ ) -> dict[str, Any]:
18
+ headers: dict[str, Any] = {}
19
+
20
+ _kwargs: dict[str, Any] = {
21
+ "method": "post",
22
+ "url": "/v1/runs/bulk",
23
+ }
24
+
25
+ _kwargs["json"] = body.to_dict()
26
+
27
+ headers["Content-Type"] = "application/json"
28
+
29
+ _kwargs["headers"] = headers
30
+ return _kwargs
31
+
32
+
33
+ def _parse_response(
34
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
35
+ ) -> Optional[Union[HTTPValidationError, RunBulkCreateResponse]]:
36
+ if response.status_code == 201:
37
+ response_201 = RunBulkCreateResponse.from_dict(response.json())
38
+
39
+ return response_201
40
+ if response.status_code == 422:
41
+ response_422 = HTTPValidationError.from_dict(response.json())
42
+
43
+ return response_422
44
+ if client.raise_on_unexpected_status:
45
+ raise errors.UnexpectedStatus(response.status_code, response.content)
46
+ else:
47
+ return None
48
+
49
+
50
+ def _build_response(
51
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
52
+ ) -> Response[Union[HTTPValidationError, RunBulkCreateResponse]]:
53
+ return Response(
54
+ status_code=HTTPStatus(response.status_code),
55
+ content=response.content,
56
+ headers=response.headers,
57
+ parsed=_parse_response(client=client, response=response),
58
+ )
59
+
60
+
61
+ def sync_detailed(
62
+ *,
63
+ client: AuthenticatedClient,
64
+ body: RunBulkCreate,
65
+ ) -> Response[Union[HTTPValidationError, RunBulkCreateResponse]]:
66
+ """Bulk Create Runs
67
+
68
+ Create multiple runs with the same configuration.
69
+
70
+ This endpoint creates multiple runs efficiently:
71
+ - All runs are created in a single database transaction
72
+ - Temporal workflows are started asynchronously
73
+ - Returns immediately with created run details
74
+
75
+ Maximum 1000 runs can be created in a single request.
76
+
77
+ Args:
78
+ body (RunBulkCreate): Schema for bulk creating runs
79
+
80
+ Raises:
81
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
82
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
83
+
84
+ Returns:
85
+ Response[Union[HTTPValidationError, RunBulkCreateResponse]]
86
+ """
87
+
88
+ kwargs = _get_kwargs(
89
+ body=body,
90
+ )
91
+
92
+ response = client.get_httpx_client().request(
93
+ **kwargs,
94
+ )
95
+
96
+ return _build_response(client=client, response=response)
97
+
98
+
99
+ def sync(
100
+ *,
101
+ client: AuthenticatedClient,
102
+ body: RunBulkCreate,
103
+ ) -> Optional[Union[HTTPValidationError, RunBulkCreateResponse]]:
104
+ """Bulk Create Runs
105
+
106
+ Create multiple runs with the same configuration.
107
+
108
+ This endpoint creates multiple runs efficiently:
109
+ - All runs are created in a single database transaction
110
+ - Temporal workflows are started asynchronously
111
+ - Returns immediately with created run details
112
+
113
+ Maximum 1000 runs can be created in a single request.
114
+
115
+ Args:
116
+ body (RunBulkCreate): Schema for bulk creating runs
117
+
118
+ Raises:
119
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
120
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
121
+
122
+ Returns:
123
+ Union[HTTPValidationError, RunBulkCreateResponse]
124
+ """
125
+
126
+ return sync_detailed(
127
+ client=client,
128
+ body=body,
129
+ ).parsed
130
+
131
+
132
+ async def asyncio_detailed(
133
+ *,
134
+ client: AuthenticatedClient,
135
+ body: RunBulkCreate,
136
+ ) -> Response[Union[HTTPValidationError, RunBulkCreateResponse]]:
137
+ """Bulk Create Runs
138
+
139
+ Create multiple runs with the same configuration.
140
+
141
+ This endpoint creates multiple runs efficiently:
142
+ - All runs are created in a single database transaction
143
+ - Temporal workflows are started asynchronously
144
+ - Returns immediately with created run details
145
+
146
+ Maximum 1000 runs can be created in a single request.
147
+
148
+ Args:
149
+ body (RunBulkCreate): Schema for bulk creating runs
150
+
151
+ Raises:
152
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
153
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
154
+
155
+ Returns:
156
+ Response[Union[HTTPValidationError, RunBulkCreateResponse]]
157
+ """
158
+
159
+ kwargs = _get_kwargs(
160
+ body=body,
161
+ )
162
+
163
+ response = await client.get_async_httpx_client().request(**kwargs)
164
+
165
+ return _build_response(client=client, response=response)
166
+
167
+
168
+ async def asyncio(
169
+ *,
170
+ client: AuthenticatedClient,
171
+ body: RunBulkCreate,
172
+ ) -> Optional[Union[HTTPValidationError, RunBulkCreateResponse]]:
173
+ """Bulk Create Runs
174
+
175
+ Create multiple runs with the same configuration.
176
+
177
+ This endpoint creates multiple runs efficiently:
178
+ - All runs are created in a single database transaction
179
+ - Temporal workflows are started asynchronously
180
+ - Returns immediately with created run details
181
+
182
+ Maximum 1000 runs can be created in a single request.
183
+
184
+ Args:
185
+ body (RunBulkCreate): Schema for bulk creating runs
186
+
187
+ Raises:
188
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
189
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
190
+
191
+ Returns:
192
+ Union[HTTPValidationError, RunBulkCreateResponse]
193
+ """
194
+
195
+ return (
196
+ await asyncio_detailed(
197
+ client=client,
198
+ body=body,
199
+ )
200
+ ).parsed
@@ -57,8 +57,12 @@ from .request_log_create import RequestLogCreate
57
57
  from .request_log_response import RequestLogResponse
58
58
  from .request_log_update import RequestLogUpdate
59
59
  from .run_attachment_create import RunAttachmentCreate
60
+ from .run_attachment_download_url_response import RunAttachmentDownloadUrlResponse
60
61
  from .run_attachment_response import RunAttachmentResponse
61
62
  from .run_attachment_update import RunAttachmentUpdate
63
+ from .run_bulk_create import RunBulkCreate
64
+ from .run_bulk_create_input_values_type_0 import RunBulkCreateInputValuesType0
65
+ from .run_bulk_create_response import RunBulkCreateResponse
62
66
  from .run_create import RunCreate
63
67
  from .run_create_input_values_type_0 import RunCreateInputValuesType0
64
68
  from .run_response import RunResponse
@@ -126,8 +130,12 @@ __all__ = (
126
130
  "RequestLogResponse",
127
131
  "RequestLogUpdate",
128
132
  "RunAttachmentCreate",
133
+ "RunAttachmentDownloadUrlResponse",
129
134
  "RunAttachmentResponse",
130
135
  "RunAttachmentUpdate",
136
+ "RunBulkCreate",
137
+ "RunBulkCreateInputValuesType0",
138
+ "RunBulkCreateResponse",
131
139
  "RunCreate",
132
140
  "RunCreateInputValuesType0",
133
141
  "RunResponse",
@@ -0,0 +1,68 @@
1
+ from collections.abc import Mapping
2
+ from typing import Any, TypeVar
3
+
4
+ from attrs import define as _attrs_define
5
+ from attrs import field as _attrs_field
6
+
7
+ T = TypeVar("T", bound="RunAttachmentDownloadUrlResponse")
8
+
9
+
10
+ @_attrs_define
11
+ class RunAttachmentDownloadUrlResponse:
12
+ """Response schema for run attachment download URL
13
+
14
+ Attributes:
15
+ url (str): Signed URL for downloading the attachment
16
+ expires_in (int): Seconds until the URL expires
17
+ """
18
+
19
+ url: str
20
+ expires_in: int
21
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
22
+
23
+ def to_dict(self) -> dict[str, Any]:
24
+ url = self.url
25
+
26
+ expires_in = self.expires_in
27
+
28
+ field_dict: dict[str, Any] = {}
29
+ field_dict.update(self.additional_properties)
30
+ field_dict.update(
31
+ {
32
+ "url": url,
33
+ "expires_in": expires_in,
34
+ }
35
+ )
36
+
37
+ return field_dict
38
+
39
+ @classmethod
40
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
41
+ d = dict(src_dict)
42
+ url = d.pop("url")
43
+
44
+ expires_in = d.pop("expires_in")
45
+
46
+ run_attachment_download_url_response = cls(
47
+ url=url,
48
+ expires_in=expires_in,
49
+ )
50
+
51
+ run_attachment_download_url_response.additional_properties = d
52
+ return run_attachment_download_url_response
53
+
54
+ @property
55
+ def additional_keys(self) -> list[str]:
56
+ return list(self.additional_properties.keys())
57
+
58
+ def __getitem__(self, key: str) -> Any:
59
+ return self.additional_properties[key]
60
+
61
+ def __setitem__(self, key: str, value: Any) -> None:
62
+ self.additional_properties[key] = value
63
+
64
+ def __delitem__(self, key: str) -> None:
65
+ del self.additional_properties[key]
66
+
67
+ def __contains__(self, key: str) -> bool:
68
+ return key in self.additional_properties
@@ -0,0 +1,181 @@
1
+ from collections.abc import Mapping
2
+ from typing import TYPE_CHECKING, Any, TypeVar, Union, cast
3
+ from uuid import UUID
4
+
5
+ from attrs import define as _attrs_define
6
+ from attrs import field as _attrs_field
7
+
8
+ from ..types import UNSET, Unset
9
+
10
+ if TYPE_CHECKING:
11
+ from ..models.file_input import FileInput
12
+ from ..models.run_bulk_create_input_values_type_0 import RunBulkCreateInputValuesType0
13
+
14
+
15
+ T = TypeVar("T", bound="RunBulkCreate")
16
+
17
+
18
+ @_attrs_define
19
+ class RunBulkCreate:
20
+ """Schema for bulk creating runs
21
+
22
+ Attributes:
23
+ workflow_id (UUID):
24
+ count (int): Number of runs to create (max 1000)
25
+ machine_id (Union[None, UUID, Unset]): Machine ID. If not provided, an available machine will be automatically
26
+ selected.
27
+ input_values (Union['RunBulkCreateInputValuesType0', None, Unset]): Input values for workflow variables
28
+ file_inputs (Union[None, Unset, list['FileInput']]): Files to upload to the machine
29
+ """
30
+
31
+ workflow_id: UUID
32
+ count: int
33
+ machine_id: Union[None, UUID, Unset] = UNSET
34
+ input_values: Union["RunBulkCreateInputValuesType0", None, Unset] = UNSET
35
+ file_inputs: Union[None, Unset, list["FileInput"]] = UNSET
36
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
37
+
38
+ def to_dict(self) -> dict[str, Any]:
39
+ from ..models.run_bulk_create_input_values_type_0 import RunBulkCreateInputValuesType0
40
+
41
+ workflow_id = str(self.workflow_id)
42
+
43
+ count = self.count
44
+
45
+ machine_id: Union[None, Unset, str]
46
+ if isinstance(self.machine_id, Unset):
47
+ machine_id = UNSET
48
+ elif isinstance(self.machine_id, UUID):
49
+ machine_id = str(self.machine_id)
50
+ else:
51
+ machine_id = self.machine_id
52
+
53
+ input_values: Union[None, Unset, dict[str, Any]]
54
+ if isinstance(self.input_values, Unset):
55
+ input_values = UNSET
56
+ elif isinstance(self.input_values, RunBulkCreateInputValuesType0):
57
+ input_values = self.input_values.to_dict()
58
+ else:
59
+ input_values = self.input_values
60
+
61
+ file_inputs: Union[None, Unset, list[dict[str, Any]]]
62
+ if isinstance(self.file_inputs, Unset):
63
+ file_inputs = UNSET
64
+ elif isinstance(self.file_inputs, list):
65
+ file_inputs = []
66
+ for file_inputs_type_0_item_data in self.file_inputs:
67
+ file_inputs_type_0_item = file_inputs_type_0_item_data.to_dict()
68
+ file_inputs.append(file_inputs_type_0_item)
69
+
70
+ else:
71
+ file_inputs = self.file_inputs
72
+
73
+ field_dict: dict[str, Any] = {}
74
+ field_dict.update(self.additional_properties)
75
+ field_dict.update(
76
+ {
77
+ "workflow_id": workflow_id,
78
+ "count": count,
79
+ }
80
+ )
81
+ if machine_id is not UNSET:
82
+ field_dict["machine_id"] = machine_id
83
+ if input_values is not UNSET:
84
+ field_dict["input_values"] = input_values
85
+ if file_inputs is not UNSET:
86
+ field_dict["file_inputs"] = file_inputs
87
+
88
+ return field_dict
89
+
90
+ @classmethod
91
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
92
+ from ..models.file_input import FileInput
93
+ from ..models.run_bulk_create_input_values_type_0 import RunBulkCreateInputValuesType0
94
+
95
+ d = dict(src_dict)
96
+ workflow_id = UUID(d.pop("workflow_id"))
97
+
98
+ count = d.pop("count")
99
+
100
+ def _parse_machine_id(data: object) -> Union[None, UUID, Unset]:
101
+ if data is None:
102
+ return data
103
+ if isinstance(data, Unset):
104
+ return data
105
+ try:
106
+ if not isinstance(data, str):
107
+ raise TypeError()
108
+ machine_id_type_0 = UUID(data)
109
+
110
+ return machine_id_type_0
111
+ except: # noqa: E722
112
+ pass
113
+ return cast(Union[None, UUID, Unset], data)
114
+
115
+ machine_id = _parse_machine_id(d.pop("machine_id", UNSET))
116
+
117
+ def _parse_input_values(data: object) -> Union["RunBulkCreateInputValuesType0", None, Unset]:
118
+ if data is None:
119
+ return data
120
+ if isinstance(data, Unset):
121
+ return data
122
+ try:
123
+ if not isinstance(data, dict):
124
+ raise TypeError()
125
+ input_values_type_0 = RunBulkCreateInputValuesType0.from_dict(data)
126
+
127
+ return input_values_type_0
128
+ except: # noqa: E722
129
+ pass
130
+ return cast(Union["RunBulkCreateInputValuesType0", None, Unset], data)
131
+
132
+ input_values = _parse_input_values(d.pop("input_values", UNSET))
133
+
134
+ def _parse_file_inputs(data: object) -> Union[None, Unset, list["FileInput"]]:
135
+ if data is None:
136
+ return data
137
+ if isinstance(data, Unset):
138
+ return data
139
+ try:
140
+ if not isinstance(data, list):
141
+ raise TypeError()
142
+ file_inputs_type_0 = []
143
+ _file_inputs_type_0 = data
144
+ for file_inputs_type_0_item_data in _file_inputs_type_0:
145
+ file_inputs_type_0_item = FileInput.from_dict(file_inputs_type_0_item_data)
146
+
147
+ file_inputs_type_0.append(file_inputs_type_0_item)
148
+
149
+ return file_inputs_type_0
150
+ except: # noqa: E722
151
+ pass
152
+ return cast(Union[None, Unset, list["FileInput"]], data)
153
+
154
+ file_inputs = _parse_file_inputs(d.pop("file_inputs", UNSET))
155
+
156
+ run_bulk_create = cls(
157
+ workflow_id=workflow_id,
158
+ count=count,
159
+ machine_id=machine_id,
160
+ input_values=input_values,
161
+ file_inputs=file_inputs,
162
+ )
163
+
164
+ run_bulk_create.additional_properties = d
165
+ return run_bulk_create
166
+
167
+ @property
168
+ def additional_keys(self) -> list[str]:
169
+ return list(self.additional_properties.keys())
170
+
171
+ def __getitem__(self, key: str) -> Any:
172
+ return self.additional_properties[key]
173
+
174
+ def __setitem__(self, key: str, value: Any) -> None:
175
+ self.additional_properties[key] = value
176
+
177
+ def __delitem__(self, key: str) -> None:
178
+ del self.additional_properties[key]
179
+
180
+ def __contains__(self, key: str) -> bool:
181
+ return key in self.additional_properties
@@ -0,0 +1,44 @@
1
+ from collections.abc import Mapping
2
+ from typing import Any, TypeVar
3
+
4
+ from attrs import define as _attrs_define
5
+ from attrs import field as _attrs_field
6
+
7
+ T = TypeVar("T", bound="RunBulkCreateInputValuesType0")
8
+
9
+
10
+ @_attrs_define
11
+ class RunBulkCreateInputValuesType0:
12
+ """ """
13
+
14
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
15
+
16
+ def to_dict(self) -> dict[str, Any]:
17
+ field_dict: dict[str, Any] = {}
18
+ field_dict.update(self.additional_properties)
19
+
20
+ return field_dict
21
+
22
+ @classmethod
23
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
24
+ d = dict(src_dict)
25
+ run_bulk_create_input_values_type_0 = cls()
26
+
27
+ run_bulk_create_input_values_type_0.additional_properties = d
28
+ return run_bulk_create_input_values_type_0
29
+
30
+ @property
31
+ def additional_keys(self) -> list[str]:
32
+ return list(self.additional_properties.keys())
33
+
34
+ def __getitem__(self, key: str) -> Any:
35
+ return self.additional_properties[key]
36
+
37
+ def __setitem__(self, key: str, value: Any) -> None:
38
+ self.additional_properties[key] = value
39
+
40
+ def __delitem__(self, key: str) -> None:
41
+ del self.additional_properties[key]
42
+
43
+ def __contains__(self, key: str) -> bool:
44
+ return key in self.additional_properties
@@ -0,0 +1,96 @@
1
+ from collections.abc import Mapping
2
+ from typing import TYPE_CHECKING, Any, TypeVar, Union, cast
3
+
4
+ from attrs import define as _attrs_define
5
+ from attrs import field as _attrs_field
6
+
7
+ from ..types import UNSET, Unset
8
+
9
+ if TYPE_CHECKING:
10
+ from ..models.run_response import RunResponse
11
+
12
+
13
+ T = TypeVar("T", bound="RunBulkCreateResponse")
14
+
15
+
16
+ @_attrs_define
17
+ class RunBulkCreateResponse:
18
+ """Response for bulk run creation
19
+
20
+ Attributes:
21
+ created_runs (list['RunResponse']):
22
+ failed_count (Union[Unset, int]): Default: 0.
23
+ errors (Union[Unset, list[str]]):
24
+ """
25
+
26
+ created_runs: list["RunResponse"]
27
+ failed_count: Union[Unset, int] = 0
28
+ errors: Union[Unset, list[str]] = UNSET
29
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
30
+
31
+ def to_dict(self) -> dict[str, Any]:
32
+ created_runs = []
33
+ for created_runs_item_data in self.created_runs:
34
+ created_runs_item = created_runs_item_data.to_dict()
35
+ created_runs.append(created_runs_item)
36
+
37
+ failed_count = self.failed_count
38
+
39
+ errors: Union[Unset, list[str]] = UNSET
40
+ if not isinstance(self.errors, Unset):
41
+ errors = self.errors
42
+
43
+ field_dict: dict[str, Any] = {}
44
+ field_dict.update(self.additional_properties)
45
+ field_dict.update(
46
+ {
47
+ "created_runs": created_runs,
48
+ }
49
+ )
50
+ if failed_count is not UNSET:
51
+ field_dict["failed_count"] = failed_count
52
+ if errors is not UNSET:
53
+ field_dict["errors"] = errors
54
+
55
+ return field_dict
56
+
57
+ @classmethod
58
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
59
+ from ..models.run_response import RunResponse
60
+
61
+ d = dict(src_dict)
62
+ created_runs = []
63
+ _created_runs = d.pop("created_runs")
64
+ for created_runs_item_data in _created_runs:
65
+ created_runs_item = RunResponse.from_dict(created_runs_item_data)
66
+
67
+ created_runs.append(created_runs_item)
68
+
69
+ failed_count = d.pop("failed_count", UNSET)
70
+
71
+ errors = cast(list[str], d.pop("errors", UNSET))
72
+
73
+ run_bulk_create_response = cls(
74
+ created_runs=created_runs,
75
+ failed_count=failed_count,
76
+ errors=errors,
77
+ )
78
+
79
+ run_bulk_create_response.additional_properties = d
80
+ return run_bulk_create_response
81
+
82
+ @property
83
+ def additional_keys(self) -> list[str]:
84
+ return list(self.additional_properties.keys())
85
+
86
+ def __getitem__(self, key: str) -> Any:
87
+ return self.additional_properties[key]
88
+
89
+ def __setitem__(self, key: str, value: Any) -> None:
90
+ self.additional_properties[key] = value
91
+
92
+ def __delitem__(self, key: str) -> None:
93
+ del self.additional_properties[key]
94
+
95
+ def __contains__(self, key: str) -> bool:
96
+ return key in self.additional_properties