databricks-sdk 0.37.0__py3-none-any.whl → 0.39.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 databricks-sdk might be problematic. Click here for more details.

Files changed (33) hide show
  1. databricks/sdk/__init__.py +24 -2
  2. databricks/sdk/_base_client.py +61 -14
  3. databricks/sdk/config.py +10 -9
  4. databricks/sdk/credentials_provider.py +6 -5
  5. databricks/sdk/mixins/jobs.py +49 -0
  6. databricks/sdk/mixins/open_ai_client.py +2 -2
  7. databricks/sdk/service/apps.py +185 -4
  8. databricks/sdk/service/billing.py +248 -1
  9. databricks/sdk/service/catalog.py +1943 -46
  10. databricks/sdk/service/cleanrooms.py +1281 -0
  11. databricks/sdk/service/compute.py +1486 -8
  12. databricks/sdk/service/dashboards.py +336 -11
  13. databricks/sdk/service/files.py +162 -2
  14. databricks/sdk/service/iam.py +353 -2
  15. databricks/sdk/service/jobs.py +1281 -16
  16. databricks/sdk/service/marketplace.py +688 -0
  17. databricks/sdk/service/ml.py +1038 -2
  18. databricks/sdk/service/oauth2.py +176 -0
  19. databricks/sdk/service/pipelines.py +602 -15
  20. databricks/sdk/service/provisioning.py +402 -0
  21. databricks/sdk/service/serving.py +615 -0
  22. databricks/sdk/service/settings.py +1190 -3
  23. databricks/sdk/service/sharing.py +328 -2
  24. databricks/sdk/service/sql.py +1186 -2
  25. databricks/sdk/service/vectorsearch.py +290 -0
  26. databricks/sdk/service/workspace.py +453 -1
  27. databricks/sdk/version.py +1 -1
  28. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/METADATA +26 -26
  29. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/RECORD +33 -31
  30. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/WHEEL +1 -1
  31. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/LICENSE +0 -0
  32. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/NOTICE +0 -0
  33. {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1281 @@
1
+ # Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from dataclasses import dataclass
7
+ from enum import Enum
8
+ from typing import Dict, Iterator, List, Optional
9
+
10
+ from ._internal import _enum, _from_dict, _repeated_dict
11
+
12
+ _LOG = logging.getLogger('databricks.sdk')
13
+
14
+ from databricks.sdk.service import catalog, jobs, settings, sharing
15
+
16
+ # all definitions in this file are in alphabetical order
17
+
18
+
19
+ @dataclass
20
+ class CleanRoom:
21
+ access_restricted: Optional[CleanRoomAccessRestricted] = None
22
+ """Whether clean room access is restricted due to [CSP]
23
+
24
+ [CSP]: https://docs.databricks.com/en/security/privacy/security-profile.html"""
25
+
26
+ comment: Optional[str] = None
27
+
28
+ created_at: Optional[int] = None
29
+ """When the clean room was created, in epoch milliseconds."""
30
+
31
+ local_collaborator_alias: Optional[str] = None
32
+ """The alias of the collaborator tied to the local clean room."""
33
+
34
+ name: Optional[str] = None
35
+ """The name of the clean room. It should follow [UC securable naming requirements].
36
+
37
+ [UC securable naming requirements]: https://docs.databricks.com/en/data-governance/unity-catalog/index.html#securable-object-naming-requirements"""
38
+
39
+ output_catalog: Optional[CleanRoomOutputCatalog] = None
40
+ """Output catalog of the clean room. It is an output only field. Output catalog is manipulated
41
+ using the separate CreateCleanRoomOutputCatalog API."""
42
+
43
+ owner: Optional[str] = None
44
+ """This is Databricks username of the owner of the local clean room securable for permission
45
+ management."""
46
+
47
+ remote_detailed_info: Optional[CleanRoomRemoteDetail] = None
48
+ """Central clean room details. During creation, users need to specify cloud_vendor, region, and
49
+ collaborators.global_metastore_id. This field will not be filled in the ListCleanRooms call."""
50
+
51
+ status: Optional[CleanRoomStatusEnum] = None
52
+ """Clean room status."""
53
+
54
+ updated_at: Optional[int] = None
55
+ """When the clean room was last updated, in epoch milliseconds."""
56
+
57
+ def as_dict(self) -> dict:
58
+ """Serializes the CleanRoom into a dictionary suitable for use as a JSON request body."""
59
+ body = {}
60
+ if self.access_restricted is not None: body['access_restricted'] = self.access_restricted.value
61
+ if self.comment is not None: body['comment'] = self.comment
62
+ if self.created_at is not None: body['created_at'] = self.created_at
63
+ if self.local_collaborator_alias is not None:
64
+ body['local_collaborator_alias'] = self.local_collaborator_alias
65
+ if self.name is not None: body['name'] = self.name
66
+ if self.output_catalog: body['output_catalog'] = self.output_catalog.as_dict()
67
+ if self.owner is not None: body['owner'] = self.owner
68
+ if self.remote_detailed_info: body['remote_detailed_info'] = self.remote_detailed_info.as_dict()
69
+ if self.status is not None: body['status'] = self.status.value
70
+ if self.updated_at is not None: body['updated_at'] = self.updated_at
71
+ return body
72
+
73
+ def as_shallow_dict(self) -> dict:
74
+ """Serializes the CleanRoom into a shallow dictionary of its immediate attributes."""
75
+ body = {}
76
+ if self.access_restricted is not None: body['access_restricted'] = self.access_restricted
77
+ if self.comment is not None: body['comment'] = self.comment
78
+ if self.created_at is not None: body['created_at'] = self.created_at
79
+ if self.local_collaborator_alias is not None:
80
+ body['local_collaborator_alias'] = self.local_collaborator_alias
81
+ if self.name is not None: body['name'] = self.name
82
+ if self.output_catalog: body['output_catalog'] = self.output_catalog
83
+ if self.owner is not None: body['owner'] = self.owner
84
+ if self.remote_detailed_info: body['remote_detailed_info'] = self.remote_detailed_info
85
+ if self.status is not None: body['status'] = self.status
86
+ if self.updated_at is not None: body['updated_at'] = self.updated_at
87
+ return body
88
+
89
+ @classmethod
90
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoom:
91
+ """Deserializes the CleanRoom from a dictionary."""
92
+ return cls(access_restricted=_enum(d, 'access_restricted', CleanRoomAccessRestricted),
93
+ comment=d.get('comment', None),
94
+ created_at=d.get('created_at', None),
95
+ local_collaborator_alias=d.get('local_collaborator_alias', None),
96
+ name=d.get('name', None),
97
+ output_catalog=_from_dict(d, 'output_catalog', CleanRoomOutputCatalog),
98
+ owner=d.get('owner', None),
99
+ remote_detailed_info=_from_dict(d, 'remote_detailed_info', CleanRoomRemoteDetail),
100
+ status=_enum(d, 'status', CleanRoomStatusEnum),
101
+ updated_at=d.get('updated_at', None))
102
+
103
+
104
+ class CleanRoomAccessRestricted(Enum):
105
+
106
+ CSP_MISMATCH = 'CSP_MISMATCH'
107
+ NO_RESTRICTION = 'NO_RESTRICTION'
108
+
109
+
110
+ @dataclass
111
+ class CleanRoomAsset:
112
+ """Metadata of the clean room asset"""
113
+
114
+ added_at: Optional[int] = None
115
+ """When the asset is added to the clean room, in epoch milliseconds."""
116
+
117
+ asset_type: Optional[CleanRoomAssetAssetType] = None
118
+ """The type of the asset."""
119
+
120
+ foreign_table: Optional[CleanRoomAssetForeignTable] = None
121
+ """Foreign table details available to all collaborators of the clean room. Present if and only if
122
+ **asset_type** is **FOREIGN_TABLE**"""
123
+
124
+ foreign_table_local_details: Optional[CleanRoomAssetForeignTableLocalDetails] = None
125
+ """Local details for a foreign that are only available to its owner. Present if and only if
126
+ **asset_type** is **FOREIGN_TABLE**"""
127
+
128
+ name: Optional[str] = None
129
+ """A fully qualified name that uniquely identifies the asset within the clean room. This is also
130
+ the name displayed in the clean room UI.
131
+
132
+ For UC securable assets (tables, volumes, etc.), the format is
133
+ *shared_catalog*.*shared_schema*.*asset_name*
134
+
135
+ For notebooks, the name is the notebook file name."""
136
+
137
+ notebook: Optional[CleanRoomAssetNotebook] = None
138
+ """Notebook details available to all collaborators of the clean room. Present if and only if
139
+ **asset_type** is **NOTEBOOK_FILE**"""
140
+
141
+ owner_collaborator_alias: Optional[str] = None
142
+ """The alias of the collaborator who owns this asset"""
143
+
144
+ status: Optional[CleanRoomAssetStatusEnum] = None
145
+ """Status of the asset"""
146
+
147
+ table: Optional[CleanRoomAssetTable] = None
148
+ """Table details available to all collaborators of the clean room. Present if and only if
149
+ **asset_type** is **TABLE**"""
150
+
151
+ table_local_details: Optional[CleanRoomAssetTableLocalDetails] = None
152
+ """Local details for a table that are only available to its owner. Present if and only if
153
+ **asset_type** is **TABLE**"""
154
+
155
+ view: Optional[CleanRoomAssetView] = None
156
+ """View details available to all collaborators of the clean room. Present if and only if
157
+ **asset_type** is **VIEW**"""
158
+
159
+ view_local_details: Optional[CleanRoomAssetViewLocalDetails] = None
160
+ """Local details for a view that are only available to its owner. Present if and only if
161
+ **asset_type** is **VIEW**"""
162
+
163
+ volume_local_details: Optional[CleanRoomAssetVolumeLocalDetails] = None
164
+ """Local details for a volume that are only available to its owner. Present if and only if
165
+ **asset_type** is **VOLUME**"""
166
+
167
+ def as_dict(self) -> dict:
168
+ """Serializes the CleanRoomAsset into a dictionary suitable for use as a JSON request body."""
169
+ body = {}
170
+ if self.added_at is not None: body['added_at'] = self.added_at
171
+ if self.asset_type is not None: body['asset_type'] = self.asset_type.value
172
+ if self.foreign_table: body['foreign_table'] = self.foreign_table.as_dict()
173
+ if self.foreign_table_local_details:
174
+ body['foreign_table_local_details'] = self.foreign_table_local_details.as_dict()
175
+ if self.name is not None: body['name'] = self.name
176
+ if self.notebook: body['notebook'] = self.notebook.as_dict()
177
+ if self.owner_collaborator_alias is not None:
178
+ body['owner_collaborator_alias'] = self.owner_collaborator_alias
179
+ if self.status is not None: body['status'] = self.status.value
180
+ if self.table: body['table'] = self.table.as_dict()
181
+ if self.table_local_details: body['table_local_details'] = self.table_local_details.as_dict()
182
+ if self.view: body['view'] = self.view.as_dict()
183
+ if self.view_local_details: body['view_local_details'] = self.view_local_details.as_dict()
184
+ if self.volume_local_details: body['volume_local_details'] = self.volume_local_details.as_dict()
185
+ return body
186
+
187
+ def as_shallow_dict(self) -> dict:
188
+ """Serializes the CleanRoomAsset into a shallow dictionary of its immediate attributes."""
189
+ body = {}
190
+ if self.added_at is not None: body['added_at'] = self.added_at
191
+ if self.asset_type is not None: body['asset_type'] = self.asset_type
192
+ if self.foreign_table: body['foreign_table'] = self.foreign_table
193
+ if self.foreign_table_local_details:
194
+ body['foreign_table_local_details'] = self.foreign_table_local_details
195
+ if self.name is not None: body['name'] = self.name
196
+ if self.notebook: body['notebook'] = self.notebook
197
+ if self.owner_collaborator_alias is not None:
198
+ body['owner_collaborator_alias'] = self.owner_collaborator_alias
199
+ if self.status is not None: body['status'] = self.status
200
+ if self.table: body['table'] = self.table
201
+ if self.table_local_details: body['table_local_details'] = self.table_local_details
202
+ if self.view: body['view'] = self.view
203
+ if self.view_local_details: body['view_local_details'] = self.view_local_details
204
+ if self.volume_local_details: body['volume_local_details'] = self.volume_local_details
205
+ return body
206
+
207
+ @classmethod
208
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAsset:
209
+ """Deserializes the CleanRoomAsset from a dictionary."""
210
+ return cls(added_at=d.get('added_at', None),
211
+ asset_type=_enum(d, 'asset_type', CleanRoomAssetAssetType),
212
+ foreign_table=_from_dict(d, 'foreign_table', CleanRoomAssetForeignTable),
213
+ foreign_table_local_details=_from_dict(d, 'foreign_table_local_details',
214
+ CleanRoomAssetForeignTableLocalDetails),
215
+ name=d.get('name', None),
216
+ notebook=_from_dict(d, 'notebook', CleanRoomAssetNotebook),
217
+ owner_collaborator_alias=d.get('owner_collaborator_alias', None),
218
+ status=_enum(d, 'status', CleanRoomAssetStatusEnum),
219
+ table=_from_dict(d, 'table', CleanRoomAssetTable),
220
+ table_local_details=_from_dict(d, 'table_local_details', CleanRoomAssetTableLocalDetails),
221
+ view=_from_dict(d, 'view', CleanRoomAssetView),
222
+ view_local_details=_from_dict(d, 'view_local_details', CleanRoomAssetViewLocalDetails),
223
+ volume_local_details=_from_dict(d, 'volume_local_details',
224
+ CleanRoomAssetVolumeLocalDetails))
225
+
226
+
227
+ class CleanRoomAssetAssetType(Enum):
228
+
229
+ FOREIGN_TABLE = 'FOREIGN_TABLE'
230
+ NOTEBOOK_FILE = 'NOTEBOOK_FILE'
231
+ TABLE = 'TABLE'
232
+ VIEW = 'VIEW'
233
+ VOLUME = 'VOLUME'
234
+
235
+
236
+ @dataclass
237
+ class CleanRoomAssetForeignTable:
238
+ columns: Optional[List[catalog.ColumnInfo]] = None
239
+ """The metadata information of the columns in the foreign table"""
240
+
241
+ def as_dict(self) -> dict:
242
+ """Serializes the CleanRoomAssetForeignTable into a dictionary suitable for use as a JSON request body."""
243
+ body = {}
244
+ if self.columns: body['columns'] = [v.as_dict() for v in self.columns]
245
+ return body
246
+
247
+ def as_shallow_dict(self) -> dict:
248
+ """Serializes the CleanRoomAssetForeignTable into a shallow dictionary of its immediate attributes."""
249
+ body = {}
250
+ if self.columns: body['columns'] = self.columns
251
+ return body
252
+
253
+ @classmethod
254
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetForeignTable:
255
+ """Deserializes the CleanRoomAssetForeignTable from a dictionary."""
256
+ return cls(columns=_repeated_dict(d, 'columns', catalog.ColumnInfo))
257
+
258
+
259
+ @dataclass
260
+ class CleanRoomAssetForeignTableLocalDetails:
261
+ local_name: Optional[str] = None
262
+ """The fully qualified name of the foreign table in its owner's local metastore, in the format of
263
+ *catalog*.*schema*.*foreign_table_name*"""
264
+
265
+ def as_dict(self) -> dict:
266
+ """Serializes the CleanRoomAssetForeignTableLocalDetails into a dictionary suitable for use as a JSON request body."""
267
+ body = {}
268
+ if self.local_name is not None: body['local_name'] = self.local_name
269
+ return body
270
+
271
+ def as_shallow_dict(self) -> dict:
272
+ """Serializes the CleanRoomAssetForeignTableLocalDetails into a shallow dictionary of its immediate attributes."""
273
+ body = {}
274
+ if self.local_name is not None: body['local_name'] = self.local_name
275
+ return body
276
+
277
+ @classmethod
278
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetForeignTableLocalDetails:
279
+ """Deserializes the CleanRoomAssetForeignTableLocalDetails from a dictionary."""
280
+ return cls(local_name=d.get('local_name', None))
281
+
282
+
283
+ @dataclass
284
+ class CleanRoomAssetNotebook:
285
+ etag: Optional[str] = None
286
+ """Server generated checksum that represents the notebook version."""
287
+
288
+ notebook_content: Optional[str] = None
289
+ """Base 64 representation of the notebook contents. This is the same format as returned by
290
+ :method:workspace/export with the format of **HTML**."""
291
+
292
+ def as_dict(self) -> dict:
293
+ """Serializes the CleanRoomAssetNotebook into a dictionary suitable for use as a JSON request body."""
294
+ body = {}
295
+ if self.etag is not None: body['etag'] = self.etag
296
+ if self.notebook_content is not None: body['notebook_content'] = self.notebook_content
297
+ return body
298
+
299
+ def as_shallow_dict(self) -> dict:
300
+ """Serializes the CleanRoomAssetNotebook into a shallow dictionary of its immediate attributes."""
301
+ body = {}
302
+ if self.etag is not None: body['etag'] = self.etag
303
+ if self.notebook_content is not None: body['notebook_content'] = self.notebook_content
304
+ return body
305
+
306
+ @classmethod
307
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetNotebook:
308
+ """Deserializes the CleanRoomAssetNotebook from a dictionary."""
309
+ return cls(etag=d.get('etag', None), notebook_content=d.get('notebook_content', None))
310
+
311
+
312
+ class CleanRoomAssetStatusEnum(Enum):
313
+
314
+ ACTIVE = 'ACTIVE'
315
+ PERMISSION_DENIED = 'PERMISSION_DENIED'
316
+
317
+
318
+ @dataclass
319
+ class CleanRoomAssetTable:
320
+ columns: Optional[List[catalog.ColumnInfo]] = None
321
+ """The metadata information of the columns in the table"""
322
+
323
+ def as_dict(self) -> dict:
324
+ """Serializes the CleanRoomAssetTable into a dictionary suitable for use as a JSON request body."""
325
+ body = {}
326
+ if self.columns: body['columns'] = [v.as_dict() for v in self.columns]
327
+ return body
328
+
329
+ def as_shallow_dict(self) -> dict:
330
+ """Serializes the CleanRoomAssetTable into a shallow dictionary of its immediate attributes."""
331
+ body = {}
332
+ if self.columns: body['columns'] = self.columns
333
+ return body
334
+
335
+ @classmethod
336
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetTable:
337
+ """Deserializes the CleanRoomAssetTable from a dictionary."""
338
+ return cls(columns=_repeated_dict(d, 'columns', catalog.ColumnInfo))
339
+
340
+
341
+ @dataclass
342
+ class CleanRoomAssetTableLocalDetails:
343
+ local_name: Optional[str] = None
344
+ """The fully qualified name of the table in its owner's local metastore, in the format of
345
+ *catalog*.*schema*.*table_name*"""
346
+
347
+ partitions: Optional[List[sharing.PartitionSpecificationPartition]] = None
348
+ """Partition filtering specification for a shared table."""
349
+
350
+ def as_dict(self) -> dict:
351
+ """Serializes the CleanRoomAssetTableLocalDetails into a dictionary suitable for use as a JSON request body."""
352
+ body = {}
353
+ if self.local_name is not None: body['local_name'] = self.local_name
354
+ if self.partitions: body['partitions'] = [v.as_dict() for v in self.partitions]
355
+ return body
356
+
357
+ def as_shallow_dict(self) -> dict:
358
+ """Serializes the CleanRoomAssetTableLocalDetails into a shallow dictionary of its immediate attributes."""
359
+ body = {}
360
+ if self.local_name is not None: body['local_name'] = self.local_name
361
+ if self.partitions: body['partitions'] = self.partitions
362
+ return body
363
+
364
+ @classmethod
365
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetTableLocalDetails:
366
+ """Deserializes the CleanRoomAssetTableLocalDetails from a dictionary."""
367
+ return cls(local_name=d.get('local_name', None),
368
+ partitions=_repeated_dict(d, 'partitions', sharing.PartitionSpecificationPartition))
369
+
370
+
371
+ @dataclass
372
+ class CleanRoomAssetView:
373
+ columns: Optional[List[catalog.ColumnInfo]] = None
374
+ """The metadata information of the columns in the view"""
375
+
376
+ def as_dict(self) -> dict:
377
+ """Serializes the CleanRoomAssetView into a dictionary suitable for use as a JSON request body."""
378
+ body = {}
379
+ if self.columns: body['columns'] = [v.as_dict() for v in self.columns]
380
+ return body
381
+
382
+ def as_shallow_dict(self) -> dict:
383
+ """Serializes the CleanRoomAssetView into a shallow dictionary of its immediate attributes."""
384
+ body = {}
385
+ if self.columns: body['columns'] = self.columns
386
+ return body
387
+
388
+ @classmethod
389
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetView:
390
+ """Deserializes the CleanRoomAssetView from a dictionary."""
391
+ return cls(columns=_repeated_dict(d, 'columns', catalog.ColumnInfo))
392
+
393
+
394
+ @dataclass
395
+ class CleanRoomAssetViewLocalDetails:
396
+ local_name: Optional[str] = None
397
+ """The fully qualified name of the view in its owner's local metastore, in the format of
398
+ *catalog*.*schema*.*view_name*"""
399
+
400
+ def as_dict(self) -> dict:
401
+ """Serializes the CleanRoomAssetViewLocalDetails into a dictionary suitable for use as a JSON request body."""
402
+ body = {}
403
+ if self.local_name is not None: body['local_name'] = self.local_name
404
+ return body
405
+
406
+ def as_shallow_dict(self) -> dict:
407
+ """Serializes the CleanRoomAssetViewLocalDetails into a shallow dictionary of its immediate attributes."""
408
+ body = {}
409
+ if self.local_name is not None: body['local_name'] = self.local_name
410
+ return body
411
+
412
+ @classmethod
413
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetViewLocalDetails:
414
+ """Deserializes the CleanRoomAssetViewLocalDetails from a dictionary."""
415
+ return cls(local_name=d.get('local_name', None))
416
+
417
+
418
+ @dataclass
419
+ class CleanRoomAssetVolumeLocalDetails:
420
+ local_name: Optional[str] = None
421
+ """The fully qualified name of the volume in its owner's local metastore, in the format of
422
+ *catalog*.*schema*.*volume_name*"""
423
+
424
+ def as_dict(self) -> dict:
425
+ """Serializes the CleanRoomAssetVolumeLocalDetails into a dictionary suitable for use as a JSON request body."""
426
+ body = {}
427
+ if self.local_name is not None: body['local_name'] = self.local_name
428
+ return body
429
+
430
+ def as_shallow_dict(self) -> dict:
431
+ """Serializes the CleanRoomAssetVolumeLocalDetails into a shallow dictionary of its immediate attributes."""
432
+ body = {}
433
+ if self.local_name is not None: body['local_name'] = self.local_name
434
+ return body
435
+
436
+ @classmethod
437
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetVolumeLocalDetails:
438
+ """Deserializes the CleanRoomAssetVolumeLocalDetails from a dictionary."""
439
+ return cls(local_name=d.get('local_name', None))
440
+
441
+
442
+ @dataclass
443
+ class CleanRoomCollaborator:
444
+ """Publicly visible clean room collaborator."""
445
+
446
+ collaborator_alias: Optional[str] = None
447
+ """Collaborator alias specified by the clean room creator. It is unique across all collaborators of
448
+ this clean room, and used to derive multiple values internally such as catalog alias and clean
449
+ room name for single metastore clean rooms. It should follow [UC securable naming requirements].
450
+
451
+ [UC securable naming requirements]: https://docs.databricks.com/en/data-governance/unity-catalog/index.html#securable-object-naming-requirements"""
452
+
453
+ display_name: Optional[str] = None
454
+ """Generated display name for the collaborator. In the case of a single metastore clean room, it is
455
+ the clean room name. For x-metastore clean rooms, it is the organization name of the metastore.
456
+ It is not restricted to these values and could change in the future"""
457
+
458
+ global_metastore_id: Optional[str] = None
459
+ """The global Unity Catalog metastore id of the collaborator. The identifier is of format
460
+ cloud:region:metastore-uuid."""
461
+
462
+ invite_recipient_email: Optional[str] = None
463
+ """Email of the user who is receiving the clean room "invitation". It should be empty for the
464
+ creator of the clean room, and non-empty for the invitees of the clean room. It is only returned
465
+ in the output when clean room creator calls GET"""
466
+
467
+ invite_recipient_workspace_id: Optional[int] = None
468
+ """Workspace ID of the user who is receiving the clean room "invitation". Must be specified if
469
+ invite_recipient_email is specified. It should be empty when the collaborator is the creator of
470
+ the clean room."""
471
+
472
+ organization_name: Optional[str] = None
473
+ """[Organization name](:method:metastores/list#metastores-delta_sharing_organization_name)
474
+ configured in the metastore"""
475
+
476
+ def as_dict(self) -> dict:
477
+ """Serializes the CleanRoomCollaborator into a dictionary suitable for use as a JSON request body."""
478
+ body = {}
479
+ if self.collaborator_alias is not None: body['collaborator_alias'] = self.collaborator_alias
480
+ if self.display_name is not None: body['display_name'] = self.display_name
481
+ if self.global_metastore_id is not None: body['global_metastore_id'] = self.global_metastore_id
482
+ if self.invite_recipient_email is not None:
483
+ body['invite_recipient_email'] = self.invite_recipient_email
484
+ if self.invite_recipient_workspace_id is not None:
485
+ body['invite_recipient_workspace_id'] = self.invite_recipient_workspace_id
486
+ if self.organization_name is not None: body['organization_name'] = self.organization_name
487
+ return body
488
+
489
+ def as_shallow_dict(self) -> dict:
490
+ """Serializes the CleanRoomCollaborator into a shallow dictionary of its immediate attributes."""
491
+ body = {}
492
+ if self.collaborator_alias is not None: body['collaborator_alias'] = self.collaborator_alias
493
+ if self.display_name is not None: body['display_name'] = self.display_name
494
+ if self.global_metastore_id is not None: body['global_metastore_id'] = self.global_metastore_id
495
+ if self.invite_recipient_email is not None:
496
+ body['invite_recipient_email'] = self.invite_recipient_email
497
+ if self.invite_recipient_workspace_id is not None:
498
+ body['invite_recipient_workspace_id'] = self.invite_recipient_workspace_id
499
+ if self.organization_name is not None: body['organization_name'] = self.organization_name
500
+ return body
501
+
502
+ @classmethod
503
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomCollaborator:
504
+ """Deserializes the CleanRoomCollaborator from a dictionary."""
505
+ return cls(collaborator_alias=d.get('collaborator_alias', None),
506
+ display_name=d.get('display_name', None),
507
+ global_metastore_id=d.get('global_metastore_id', None),
508
+ invite_recipient_email=d.get('invite_recipient_email', None),
509
+ invite_recipient_workspace_id=d.get('invite_recipient_workspace_id', None),
510
+ organization_name=d.get('organization_name', None))
511
+
512
+
513
+ @dataclass
514
+ class CleanRoomNotebookTaskRun:
515
+ """Stores information about a single task run."""
516
+
517
+ collaborator_job_run_info: Optional[CollaboratorJobRunInfo] = None
518
+ """Job run info of the task in the runner's local workspace. This field is only included in the
519
+ LIST API. if the task was run within the same workspace the API is being called. If the task run
520
+ was in a different workspace under the same metastore, only the workspace_id is included."""
521
+
522
+ notebook_job_run_state: Optional[jobs.CleanRoomTaskRunState] = None
523
+ """State of the task run."""
524
+
525
+ notebook_name: Optional[str] = None
526
+ """Asset name of the notebook executed in this task run."""
527
+
528
+ output_schema_expiration_time: Optional[int] = None
529
+ """Expiration time of the output schema of the task run (if any), in epoch milliseconds."""
530
+
531
+ output_schema_name: Optional[str] = None
532
+ """Name of the output schema associated with the clean rooms notebook task run."""
533
+
534
+ run_duration: Optional[int] = None
535
+ """Duration of the task run, in milliseconds."""
536
+
537
+ start_time: Optional[int] = None
538
+ """When the task run started, in epoch milliseconds."""
539
+
540
+ def as_dict(self) -> dict:
541
+ """Serializes the CleanRoomNotebookTaskRun into a dictionary suitable for use as a JSON request body."""
542
+ body = {}
543
+ if self.collaborator_job_run_info:
544
+ body['collaborator_job_run_info'] = self.collaborator_job_run_info.as_dict()
545
+ if self.notebook_job_run_state: body['notebook_job_run_state'] = self.notebook_job_run_state.as_dict()
546
+ if self.notebook_name is not None: body['notebook_name'] = self.notebook_name
547
+ if self.output_schema_expiration_time is not None:
548
+ body['output_schema_expiration_time'] = self.output_schema_expiration_time
549
+ if self.output_schema_name is not None: body['output_schema_name'] = self.output_schema_name
550
+ if self.run_duration is not None: body['run_duration'] = self.run_duration
551
+ if self.start_time is not None: body['start_time'] = self.start_time
552
+ return body
553
+
554
+ def as_shallow_dict(self) -> dict:
555
+ """Serializes the CleanRoomNotebookTaskRun into a shallow dictionary of its immediate attributes."""
556
+ body = {}
557
+ if self.collaborator_job_run_info: body['collaborator_job_run_info'] = self.collaborator_job_run_info
558
+ if self.notebook_job_run_state: body['notebook_job_run_state'] = self.notebook_job_run_state
559
+ if self.notebook_name is not None: body['notebook_name'] = self.notebook_name
560
+ if self.output_schema_expiration_time is not None:
561
+ body['output_schema_expiration_time'] = self.output_schema_expiration_time
562
+ if self.output_schema_name is not None: body['output_schema_name'] = self.output_schema_name
563
+ if self.run_duration is not None: body['run_duration'] = self.run_duration
564
+ if self.start_time is not None: body['start_time'] = self.start_time
565
+ return body
566
+
567
+ @classmethod
568
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomNotebookTaskRun:
569
+ """Deserializes the CleanRoomNotebookTaskRun from a dictionary."""
570
+ return cls(collaborator_job_run_info=_from_dict(d, 'collaborator_job_run_info',
571
+ CollaboratorJobRunInfo),
572
+ notebook_job_run_state=_from_dict(d, 'notebook_job_run_state', jobs.CleanRoomTaskRunState),
573
+ notebook_name=d.get('notebook_name', None),
574
+ output_schema_expiration_time=d.get('output_schema_expiration_time', None),
575
+ output_schema_name=d.get('output_schema_name', None),
576
+ run_duration=d.get('run_duration', None),
577
+ start_time=d.get('start_time', None))
578
+
579
+
580
+ @dataclass
581
+ class CleanRoomOutputCatalog:
582
+ catalog_name: Optional[str] = None
583
+ """The name of the output catalog in UC. It should follow [UC securable naming requirements]. The
584
+ field will always exist if status is CREATED.
585
+
586
+ [UC securable naming requirements]: https://docs.databricks.com/en/data-governance/unity-catalog/index.html#securable-object-naming-requirements"""
587
+
588
+ status: Optional[CleanRoomOutputCatalogOutputCatalogStatus] = None
589
+
590
+ def as_dict(self) -> dict:
591
+ """Serializes the CleanRoomOutputCatalog into a dictionary suitable for use as a JSON request body."""
592
+ body = {}
593
+ if self.catalog_name is not None: body['catalog_name'] = self.catalog_name
594
+ if self.status is not None: body['status'] = self.status.value
595
+ return body
596
+
597
+ def as_shallow_dict(self) -> dict:
598
+ """Serializes the CleanRoomOutputCatalog into a shallow dictionary of its immediate attributes."""
599
+ body = {}
600
+ if self.catalog_name is not None: body['catalog_name'] = self.catalog_name
601
+ if self.status is not None: body['status'] = self.status
602
+ return body
603
+
604
+ @classmethod
605
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomOutputCatalog:
606
+ """Deserializes the CleanRoomOutputCatalog from a dictionary."""
607
+ return cls(catalog_name=d.get('catalog_name', None),
608
+ status=_enum(d, 'status', CleanRoomOutputCatalogOutputCatalogStatus))
609
+
610
+
611
+ class CleanRoomOutputCatalogOutputCatalogStatus(Enum):
612
+
613
+ CREATED = 'CREATED'
614
+ NOT_CREATED = 'NOT_CREATED'
615
+ NOT_ELIGIBLE = 'NOT_ELIGIBLE'
616
+
617
+
618
+ @dataclass
619
+ class CleanRoomRemoteDetail:
620
+ """Publicly visible central clean room details."""
621
+
622
+ central_clean_room_id: Optional[str] = None
623
+ """Central clean room ID."""
624
+
625
+ cloud_vendor: Optional[str] = None
626
+ """Cloud vendor (aws,azure,gcp) of the central clean room."""
627
+
628
+ collaborators: Optional[List[CleanRoomCollaborator]] = None
629
+ """Collaborators in the central clean room. There should one and only one collaborator in the list
630
+ that satisfies the owner condition:
631
+
632
+ 1. It has the creator's global_metastore_id (determined by caller of CreateCleanRoom).
633
+
634
+ 2. Its invite_recipient_email is empty."""
635
+
636
+ compliance_security_profile: Optional[ComplianceSecurityProfile] = None
637
+ """The compliance security profile used to process regulated data following compliance standards."""
638
+
639
+ creator: Optional[CleanRoomCollaborator] = None
640
+ """Collaborator who creates the clean room."""
641
+
642
+ egress_network_policy: Optional[settings.EgressNetworkPolicy] = None
643
+ """Egress network policy to apply to the central clean room workspace."""
644
+
645
+ region: Optional[str] = None
646
+ """Region of the central clean room."""
647
+
648
+ def as_dict(self) -> dict:
649
+ """Serializes the CleanRoomRemoteDetail into a dictionary suitable for use as a JSON request body."""
650
+ body = {}
651
+ if self.central_clean_room_id is not None: body['central_clean_room_id'] = self.central_clean_room_id
652
+ if self.cloud_vendor is not None: body['cloud_vendor'] = self.cloud_vendor
653
+ if self.collaborators: body['collaborators'] = [v.as_dict() for v in self.collaborators]
654
+ if self.compliance_security_profile:
655
+ body['compliance_security_profile'] = self.compliance_security_profile.as_dict()
656
+ if self.creator: body['creator'] = self.creator.as_dict()
657
+ if self.egress_network_policy: body['egress_network_policy'] = self.egress_network_policy.as_dict()
658
+ if self.region is not None: body['region'] = self.region
659
+ return body
660
+
661
+ def as_shallow_dict(self) -> dict:
662
+ """Serializes the CleanRoomRemoteDetail into a shallow dictionary of its immediate attributes."""
663
+ body = {}
664
+ if self.central_clean_room_id is not None: body['central_clean_room_id'] = self.central_clean_room_id
665
+ if self.cloud_vendor is not None: body['cloud_vendor'] = self.cloud_vendor
666
+ if self.collaborators: body['collaborators'] = self.collaborators
667
+ if self.compliance_security_profile:
668
+ body['compliance_security_profile'] = self.compliance_security_profile
669
+ if self.creator: body['creator'] = self.creator
670
+ if self.egress_network_policy: body['egress_network_policy'] = self.egress_network_policy
671
+ if self.region is not None: body['region'] = self.region
672
+ return body
673
+
674
+ @classmethod
675
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomRemoteDetail:
676
+ """Deserializes the CleanRoomRemoteDetail from a dictionary."""
677
+ return cls(central_clean_room_id=d.get('central_clean_room_id', None),
678
+ cloud_vendor=d.get('cloud_vendor', None),
679
+ collaborators=_repeated_dict(d, 'collaborators', CleanRoomCollaborator),
680
+ compliance_security_profile=_from_dict(d, 'compliance_security_profile',
681
+ ComplianceSecurityProfile),
682
+ creator=_from_dict(d, 'creator', CleanRoomCollaborator),
683
+ egress_network_policy=_from_dict(d, 'egress_network_policy', settings.EgressNetworkPolicy),
684
+ region=d.get('region', None))
685
+
686
+
687
+ class CleanRoomStatusEnum(Enum):
688
+
689
+ ACTIVE = 'ACTIVE'
690
+ DELETED = 'DELETED'
691
+ FAILED = 'FAILED'
692
+ PROVISIONING = 'PROVISIONING'
693
+
694
+
695
+ @dataclass
696
+ class CollaboratorJobRunInfo:
697
+ collaborator_alias: Optional[str] = None
698
+ """Alias of the collaborator that triggered the task run."""
699
+
700
+ collaborator_job_id: Optional[int] = None
701
+ """Job ID of the task run in the collaborator's workspace."""
702
+
703
+ collaborator_job_run_id: Optional[int] = None
704
+ """Job run ID of the task run in the collaborator's workspace."""
705
+
706
+ collaborator_task_run_id: Optional[int] = None
707
+ """Task run ID of the task run in the collaborator's workspace."""
708
+
709
+ collaborator_workspace_id: Optional[int] = None
710
+ """ID of the collaborator's workspace that triggered the task run."""
711
+
712
+ def as_dict(self) -> dict:
713
+ """Serializes the CollaboratorJobRunInfo into a dictionary suitable for use as a JSON request body."""
714
+ body = {}
715
+ if self.collaborator_alias is not None: body['collaborator_alias'] = self.collaborator_alias
716
+ if self.collaborator_job_id is not None: body['collaborator_job_id'] = self.collaborator_job_id
717
+ if self.collaborator_job_run_id is not None:
718
+ body['collaborator_job_run_id'] = self.collaborator_job_run_id
719
+ if self.collaborator_task_run_id is not None:
720
+ body['collaborator_task_run_id'] = self.collaborator_task_run_id
721
+ if self.collaborator_workspace_id is not None:
722
+ body['collaborator_workspace_id'] = self.collaborator_workspace_id
723
+ return body
724
+
725
+ def as_shallow_dict(self) -> dict:
726
+ """Serializes the CollaboratorJobRunInfo into a shallow dictionary of its immediate attributes."""
727
+ body = {}
728
+ if self.collaborator_alias is not None: body['collaborator_alias'] = self.collaborator_alias
729
+ if self.collaborator_job_id is not None: body['collaborator_job_id'] = self.collaborator_job_id
730
+ if self.collaborator_job_run_id is not None:
731
+ body['collaborator_job_run_id'] = self.collaborator_job_run_id
732
+ if self.collaborator_task_run_id is not None:
733
+ body['collaborator_task_run_id'] = self.collaborator_task_run_id
734
+ if self.collaborator_workspace_id is not None:
735
+ body['collaborator_workspace_id'] = self.collaborator_workspace_id
736
+ return body
737
+
738
+ @classmethod
739
+ def from_dict(cls, d: Dict[str, any]) -> CollaboratorJobRunInfo:
740
+ """Deserializes the CollaboratorJobRunInfo from a dictionary."""
741
+ return cls(collaborator_alias=d.get('collaborator_alias', None),
742
+ collaborator_job_id=d.get('collaborator_job_id', None),
743
+ collaborator_job_run_id=d.get('collaborator_job_run_id', None),
744
+ collaborator_task_run_id=d.get('collaborator_task_run_id', None),
745
+ collaborator_workspace_id=d.get('collaborator_workspace_id', None))
746
+
747
+
748
+ @dataclass
749
+ class ComplianceSecurityProfile:
750
+ """The compliance security profile used to process regulated data following compliance standards."""
751
+
752
+ compliance_standards: Optional[List[settings.ComplianceStandard]] = None
753
+ """The list of compliance standards that the compliance security profile is configured to enforce."""
754
+
755
+ is_enabled: Optional[bool] = None
756
+ """Whether the compliance security profile is enabled."""
757
+
758
+ def as_dict(self) -> dict:
759
+ """Serializes the ComplianceSecurityProfile into a dictionary suitable for use as a JSON request body."""
760
+ body = {}
761
+ if self.compliance_standards:
762
+ body['compliance_standards'] = [v.as_dict() for v in self.compliance_standards]
763
+ if self.is_enabled is not None: body['is_enabled'] = self.is_enabled
764
+ return body
765
+
766
+ def as_shallow_dict(self) -> dict:
767
+ """Serializes the ComplianceSecurityProfile into a shallow dictionary of its immediate attributes."""
768
+ body = {}
769
+ if self.compliance_standards: body['compliance_standards'] = self.compliance_standards
770
+ if self.is_enabled is not None: body['is_enabled'] = self.is_enabled
771
+ return body
772
+
773
+ @classmethod
774
+ def from_dict(cls, d: Dict[str, any]) -> ComplianceSecurityProfile:
775
+ """Deserializes the ComplianceSecurityProfile from a dictionary."""
776
+ return cls(compliance_standards=_repeated_dict(d, 'compliance_standards',
777
+ settings.ComplianceStandard),
778
+ is_enabled=d.get('is_enabled', None))
779
+
780
+
781
+ @dataclass
782
+ class CreateCleanRoomOutputCatalogResponse:
783
+ output_catalog: Optional[CleanRoomOutputCatalog] = None
784
+
785
+ def as_dict(self) -> dict:
786
+ """Serializes the CreateCleanRoomOutputCatalogResponse into a dictionary suitable for use as a JSON request body."""
787
+ body = {}
788
+ if self.output_catalog: body['output_catalog'] = self.output_catalog.as_dict()
789
+ return body
790
+
791
+ def as_shallow_dict(self) -> dict:
792
+ """Serializes the CreateCleanRoomOutputCatalogResponse into a shallow dictionary of its immediate attributes."""
793
+ body = {}
794
+ if self.output_catalog: body['output_catalog'] = self.output_catalog
795
+ return body
796
+
797
+ @classmethod
798
+ def from_dict(cls, d: Dict[str, any]) -> CreateCleanRoomOutputCatalogResponse:
799
+ """Deserializes the CreateCleanRoomOutputCatalogResponse from a dictionary."""
800
+ return cls(output_catalog=_from_dict(d, 'output_catalog', CleanRoomOutputCatalog))
801
+
802
+
803
+ @dataclass
804
+ class DeleteCleanRoomAssetResponse:
805
+ """Response for delete clean room request. Using an empty message since the generic Empty proto
806
+ does not externd UnshadedMessageMarker."""
807
+
808
+ def as_dict(self) -> dict:
809
+ """Serializes the DeleteCleanRoomAssetResponse into a dictionary suitable for use as a JSON request body."""
810
+ body = {}
811
+ return body
812
+
813
+ def as_shallow_dict(self) -> dict:
814
+ """Serializes the DeleteCleanRoomAssetResponse into a shallow dictionary of its immediate attributes."""
815
+ body = {}
816
+ return body
817
+
818
+ @classmethod
819
+ def from_dict(cls, d: Dict[str, any]) -> DeleteCleanRoomAssetResponse:
820
+ """Deserializes the DeleteCleanRoomAssetResponse from a dictionary."""
821
+ return cls()
822
+
823
+
824
+ @dataclass
825
+ class DeleteResponse:
826
+
827
+ def as_dict(self) -> dict:
828
+ """Serializes the DeleteResponse into a dictionary suitable for use as a JSON request body."""
829
+ body = {}
830
+ return body
831
+
832
+ def as_shallow_dict(self) -> dict:
833
+ """Serializes the DeleteResponse into a shallow dictionary of its immediate attributes."""
834
+ body = {}
835
+ return body
836
+
837
+ @classmethod
838
+ def from_dict(cls, d: Dict[str, any]) -> DeleteResponse:
839
+ """Deserializes the DeleteResponse from a dictionary."""
840
+ return cls()
841
+
842
+
843
+ @dataclass
844
+ class ListCleanRoomAssetsResponse:
845
+ assets: Optional[List[CleanRoomAsset]] = None
846
+ """Assets in the clean room."""
847
+
848
+ next_page_token: Optional[str] = None
849
+ """Opaque token to retrieve the next page of results. Absent if there are no more pages. page_token
850
+ should be set to this value for the next request (for the next page of results)."""
851
+
852
+ def as_dict(self) -> dict:
853
+ """Serializes the ListCleanRoomAssetsResponse into a dictionary suitable for use as a JSON request body."""
854
+ body = {}
855
+ if self.assets: body['assets'] = [v.as_dict() for v in self.assets]
856
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
857
+ return body
858
+
859
+ def as_shallow_dict(self) -> dict:
860
+ """Serializes the ListCleanRoomAssetsResponse into a shallow dictionary of its immediate attributes."""
861
+ body = {}
862
+ if self.assets: body['assets'] = self.assets
863
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
864
+ return body
865
+
866
+ @classmethod
867
+ def from_dict(cls, d: Dict[str, any]) -> ListCleanRoomAssetsResponse:
868
+ """Deserializes the ListCleanRoomAssetsResponse from a dictionary."""
869
+ return cls(assets=_repeated_dict(d, 'assets', CleanRoomAsset),
870
+ next_page_token=d.get('next_page_token', None))
871
+
872
+
873
+ @dataclass
874
+ class ListCleanRoomNotebookTaskRunsResponse:
875
+ next_page_token: Optional[str] = None
876
+ """Opaque token to retrieve the next page of results. Absent if there are no more pages. page_token
877
+ should be set to this value for the next request (for the next page of results)."""
878
+
879
+ runs: Optional[List[CleanRoomNotebookTaskRun]] = None
880
+ """Name of the clean room."""
881
+
882
+ def as_dict(self) -> dict:
883
+ """Serializes the ListCleanRoomNotebookTaskRunsResponse into a dictionary suitable for use as a JSON request body."""
884
+ body = {}
885
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
886
+ if self.runs: body['runs'] = [v.as_dict() for v in self.runs]
887
+ return body
888
+
889
+ def as_shallow_dict(self) -> dict:
890
+ """Serializes the ListCleanRoomNotebookTaskRunsResponse into a shallow dictionary of its immediate attributes."""
891
+ body = {}
892
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
893
+ if self.runs: body['runs'] = self.runs
894
+ return body
895
+
896
+ @classmethod
897
+ def from_dict(cls, d: Dict[str, any]) -> ListCleanRoomNotebookTaskRunsResponse:
898
+ """Deserializes the ListCleanRoomNotebookTaskRunsResponse from a dictionary."""
899
+ return cls(next_page_token=d.get('next_page_token', None),
900
+ runs=_repeated_dict(d, 'runs', CleanRoomNotebookTaskRun))
901
+
902
+
903
+ @dataclass
904
+ class ListCleanRoomsResponse:
905
+ clean_rooms: Optional[List[CleanRoom]] = None
906
+
907
+ next_page_token: Optional[str] = None
908
+ """Opaque token to retrieve the next page of results. Absent if there are no more pages. page_token
909
+ should be set to this value for the next request (for the next page of results)."""
910
+
911
+ def as_dict(self) -> dict:
912
+ """Serializes the ListCleanRoomsResponse into a dictionary suitable for use as a JSON request body."""
913
+ body = {}
914
+ if self.clean_rooms: body['clean_rooms'] = [v.as_dict() for v in self.clean_rooms]
915
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
916
+ return body
917
+
918
+ def as_shallow_dict(self) -> dict:
919
+ """Serializes the ListCleanRoomsResponse into a shallow dictionary of its immediate attributes."""
920
+ body = {}
921
+ if self.clean_rooms: body['clean_rooms'] = self.clean_rooms
922
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
923
+ return body
924
+
925
+ @classmethod
926
+ def from_dict(cls, d: Dict[str, any]) -> ListCleanRoomsResponse:
927
+ """Deserializes the ListCleanRoomsResponse from a dictionary."""
928
+ return cls(clean_rooms=_repeated_dict(d, 'clean_rooms', CleanRoom),
929
+ next_page_token=d.get('next_page_token', None))
930
+
931
+
932
+ @dataclass
933
+ class UpdateCleanRoomRequest:
934
+ clean_room: Optional[CleanRoom] = None
935
+
936
+ name: Optional[str] = None
937
+ """Name of the clean room."""
938
+
939
+ def as_dict(self) -> dict:
940
+ """Serializes the UpdateCleanRoomRequest into a dictionary suitable for use as a JSON request body."""
941
+ body = {}
942
+ if self.clean_room: body['clean_room'] = self.clean_room.as_dict()
943
+ if self.name is not None: body['name'] = self.name
944
+ return body
945
+
946
+ def as_shallow_dict(self) -> dict:
947
+ """Serializes the UpdateCleanRoomRequest into a shallow dictionary of its immediate attributes."""
948
+ body = {}
949
+ if self.clean_room: body['clean_room'] = self.clean_room
950
+ if self.name is not None: body['name'] = self.name
951
+ return body
952
+
953
+ @classmethod
954
+ def from_dict(cls, d: Dict[str, any]) -> UpdateCleanRoomRequest:
955
+ """Deserializes the UpdateCleanRoomRequest from a dictionary."""
956
+ return cls(clean_room=_from_dict(d, 'clean_room', CleanRoom), name=d.get('name', None))
957
+
958
+
959
+ class CleanRoomAssetsAPI:
960
+ """Clean room assets are data and code objects — Tables, volumes, and notebooks that are shared with the
961
+ clean room."""
962
+
963
+ def __init__(self, api_client):
964
+ self._api = api_client
965
+
966
+ def create(self, clean_room_name: str, *, asset: Optional[CleanRoomAsset] = None) -> CleanRoomAsset:
967
+ """Create an asset.
968
+
969
+ Create a clean room asset —share an asset like a notebook or table into the clean room. For each UC
970
+ asset that is added through this method, the clean room owner must also have enough privilege on the
971
+ asset to consume it. The privilege must be maintained indefinitely for the clean room to be able to
972
+ access the asset. Typically, you should use a group as the clean room owner.
973
+
974
+ :param clean_room_name: str
975
+ Name of the clean room.
976
+ :param asset: :class:`CleanRoomAsset` (optional)
977
+ Metadata of the clean room asset
978
+
979
+ :returns: :class:`CleanRoomAsset`
980
+ """
981
+ body = asset.as_dict()
982
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
983
+
984
+ res = self._api.do('POST',
985
+ f'/api/2.0/clean-rooms/{clean_room_name}/assets',
986
+ body=body,
987
+ headers=headers)
988
+ return CleanRoomAsset.from_dict(res)
989
+
990
+ def delete(self, clean_room_name: str, asset_type: CleanRoomAssetAssetType, asset_full_name: str):
991
+ """Delete an asset.
992
+
993
+ Delete a clean room asset - unshare/remove the asset from the clean room
994
+
995
+ :param clean_room_name: str
996
+ Name of the clean room.
997
+ :param asset_type: :class:`CleanRoomAssetAssetType`
998
+ The type of the asset.
999
+ :param asset_full_name: str
1000
+ The fully qualified name of the asset, it is same as the name field in CleanRoomAsset.
1001
+
1002
+
1003
+ """
1004
+
1005
+ headers = {'Accept': 'application/json', }
1006
+
1007
+ self._api.do('DELETE',
1008
+ f'/api/2.0/clean-rooms/{clean_room_name}/assets/{asset_type.value}/{asset_full_name}',
1009
+ headers=headers)
1010
+
1011
+ def get(self, clean_room_name: str, asset_type: CleanRoomAssetAssetType,
1012
+ asset_full_name: str) -> CleanRoomAsset:
1013
+ """Get an asset.
1014
+
1015
+ Get the details of a clean room asset by its type and full name.
1016
+
1017
+ :param clean_room_name: str
1018
+ Name of the clean room.
1019
+ :param asset_type: :class:`CleanRoomAssetAssetType`
1020
+ The type of the asset.
1021
+ :param asset_full_name: str
1022
+ The fully qualified name of the asset, it is same as the name field in CleanRoomAsset.
1023
+
1024
+ :returns: :class:`CleanRoomAsset`
1025
+ """
1026
+
1027
+ headers = {'Accept': 'application/json', }
1028
+
1029
+ res = self._api.do(
1030
+ 'GET',
1031
+ f'/api/2.0/clean-rooms/{clean_room_name}/assets/{asset_type.value}/{asset_full_name}',
1032
+ headers=headers)
1033
+ return CleanRoomAsset.from_dict(res)
1034
+
1035
+ def list(self, clean_room_name: str, *, page_token: Optional[str] = None) -> Iterator[CleanRoomAsset]:
1036
+ """List assets.
1037
+
1038
+ :param clean_room_name: str
1039
+ Name of the clean room.
1040
+ :param page_token: str (optional)
1041
+ Opaque pagination token to go to next page based on previous query.
1042
+
1043
+ :returns: Iterator over :class:`CleanRoomAsset`
1044
+ """
1045
+
1046
+ query = {}
1047
+ if page_token is not None: query['page_token'] = page_token
1048
+ headers = {'Accept': 'application/json', }
1049
+
1050
+ while True:
1051
+ json = self._api.do('GET',
1052
+ f'/api/2.0/clean-rooms/{clean_room_name}/assets',
1053
+ query=query,
1054
+ headers=headers)
1055
+ if 'assets' in json:
1056
+ for v in json['assets']:
1057
+ yield CleanRoomAsset.from_dict(v)
1058
+ if 'next_page_token' not in json or not json['next_page_token']:
1059
+ return
1060
+ query['page_token'] = json['next_page_token']
1061
+
1062
+ def update(self,
1063
+ clean_room_name: str,
1064
+ asset_type: CleanRoomAssetAssetType,
1065
+ name: str,
1066
+ *,
1067
+ asset: Optional[CleanRoomAsset] = None) -> CleanRoomAsset:
1068
+ """Update an asset.
1069
+
1070
+ Update a clean room asset. For example, updating the content of a notebook; changing the shared
1071
+ partitions of a table; etc.
1072
+
1073
+ :param clean_room_name: str
1074
+ Name of the clean room.
1075
+ :param asset_type: :class:`CleanRoomAssetAssetType`
1076
+ The type of the asset.
1077
+ :param name: str
1078
+ A fully qualified name that uniquely identifies the asset within the clean room. This is also the
1079
+ name displayed in the clean room UI.
1080
+
1081
+ For UC securable assets (tables, volumes, etc.), the format is
1082
+ *shared_catalog*.*shared_schema*.*asset_name*
1083
+
1084
+ For notebooks, the name is the notebook file name.
1085
+ :param asset: :class:`CleanRoomAsset` (optional)
1086
+ Metadata of the clean room asset
1087
+
1088
+ :returns: :class:`CleanRoomAsset`
1089
+ """
1090
+ body = asset.as_dict()
1091
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1092
+
1093
+ res = self._api.do('PATCH',
1094
+ f'/api/2.0/clean-rooms/{clean_room_name}/assets/{asset_type.value}/{name}',
1095
+ body=body,
1096
+ headers=headers)
1097
+ return CleanRoomAsset.from_dict(res)
1098
+
1099
+
1100
+ class CleanRoomTaskRunsAPI:
1101
+ """Clean room task runs are the executions of notebooks in a clean room."""
1102
+
1103
+ def __init__(self, api_client):
1104
+ self._api = api_client
1105
+
1106
+ def list(self,
1107
+ clean_room_name: str,
1108
+ *,
1109
+ notebook_name: Optional[str] = None,
1110
+ page_size: Optional[int] = None,
1111
+ page_token: Optional[str] = None) -> Iterator[CleanRoomNotebookTaskRun]:
1112
+ """List notebook task runs.
1113
+
1114
+ List all the historical notebook task runs in a clean room.
1115
+
1116
+ :param clean_room_name: str
1117
+ Name of the clean room.
1118
+ :param notebook_name: str (optional)
1119
+ Notebook name
1120
+ :param page_size: int (optional)
1121
+ The maximum number of task runs to return
1122
+ :param page_token: str (optional)
1123
+ Opaque pagination token to go to next page based on previous query.
1124
+
1125
+ :returns: Iterator over :class:`CleanRoomNotebookTaskRun`
1126
+ """
1127
+
1128
+ query = {}
1129
+ if notebook_name is not None: query['notebook_name'] = notebook_name
1130
+ if page_size is not None: query['page_size'] = page_size
1131
+ if page_token is not None: query['page_token'] = page_token
1132
+ headers = {'Accept': 'application/json', }
1133
+
1134
+ while True:
1135
+ json = self._api.do('GET',
1136
+ f'/api/2.0/clean-rooms/{clean_room_name}/runs',
1137
+ query=query,
1138
+ headers=headers)
1139
+ if 'runs' in json:
1140
+ for v in json['runs']:
1141
+ yield CleanRoomNotebookTaskRun.from_dict(v)
1142
+ if 'next_page_token' not in json or not json['next_page_token']:
1143
+ return
1144
+ query['page_token'] = json['next_page_token']
1145
+
1146
+
1147
+ class CleanRoomsAPI:
1148
+ """A clean room uses Delta Sharing and serverless compute to provide a secure and privacy-protecting
1149
+ environment where multiple parties can work together on sensitive enterprise data without direct access to
1150
+ each other’s data."""
1151
+
1152
+ def __init__(self, api_client):
1153
+ self._api = api_client
1154
+
1155
+ def create(self, *, clean_room: Optional[CleanRoom] = None) -> CleanRoom:
1156
+ """Create a clean room.
1157
+
1158
+ Create a new clean room with the specified collaborators. This method is asynchronous; the returned
1159
+ name field inside the clean_room field can be used to poll the clean room status, using the
1160
+ :method:cleanrooms/get method. When this method returns, the cluster will be in a PROVISIONING state.
1161
+ The cluster will be usable once it enters an ACTIVE state.
1162
+
1163
+ The caller must be a metastore admin or have the **CREATE_CLEAN_ROOM** privilege on the metastore.
1164
+
1165
+ :param clean_room: :class:`CleanRoom` (optional)
1166
+
1167
+ :returns: :class:`CleanRoom`
1168
+ """
1169
+ body = clean_room.as_dict()
1170
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1171
+
1172
+ res = self._api.do('POST', '/api/2.0/clean-rooms', body=body, headers=headers)
1173
+ return CleanRoom.from_dict(res)
1174
+
1175
+ def create_output_catalog(
1176
+ self,
1177
+ clean_room_name: str,
1178
+ *,
1179
+ output_catalog: Optional[CleanRoomOutputCatalog] = None) -> CreateCleanRoomOutputCatalogResponse:
1180
+ """Create an output catalog.
1181
+
1182
+ Create the output catalog of the clean room.
1183
+
1184
+ :param clean_room_name: str
1185
+ Name of the clean room.
1186
+ :param output_catalog: :class:`CleanRoomOutputCatalog` (optional)
1187
+
1188
+ :returns: :class:`CreateCleanRoomOutputCatalogResponse`
1189
+ """
1190
+ body = output_catalog.as_dict()
1191
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1192
+
1193
+ res = self._api.do('POST',
1194
+ f'/api/2.0/clean-rooms/{clean_room_name}/output-catalogs',
1195
+ body=body,
1196
+ headers=headers)
1197
+ return CreateCleanRoomOutputCatalogResponse.from_dict(res)
1198
+
1199
+ def delete(self, name: str):
1200
+ """Delete a clean room.
1201
+
1202
+ Delete a clean room. After deletion, the clean room will be removed from the metastore. If the other
1203
+ collaborators have not deleted the clean room, they will still have the clean room in their metastore,
1204
+ but it will be in a DELETED state and no operations other than deletion can be performed on it.
1205
+
1206
+ :param name: str
1207
+ Name of the clean room.
1208
+
1209
+
1210
+ """
1211
+
1212
+ headers = {'Accept': 'application/json', }
1213
+
1214
+ self._api.do('DELETE', f'/api/2.0/clean-rooms/{name}', headers=headers)
1215
+
1216
+ def get(self, name: str) -> CleanRoom:
1217
+ """Get a clean room.
1218
+
1219
+ Get the details of a clean room given its name.
1220
+
1221
+ :param name: str
1222
+
1223
+ :returns: :class:`CleanRoom`
1224
+ """
1225
+
1226
+ headers = {'Accept': 'application/json', }
1227
+
1228
+ res = self._api.do('GET', f'/api/2.0/clean-rooms/{name}', headers=headers)
1229
+ return CleanRoom.from_dict(res)
1230
+
1231
+ def list(self,
1232
+ *,
1233
+ page_size: Optional[int] = None,
1234
+ page_token: Optional[str] = None) -> Iterator[CleanRoom]:
1235
+ """List clean rooms.
1236
+
1237
+ Get a list of all clean rooms of the metastore. Only clean rooms the caller has access to are
1238
+ returned.
1239
+
1240
+ :param page_size: int (optional)
1241
+ Maximum number of clean rooms to return (i.e., the page length). Defaults to 100.
1242
+ :param page_token: str (optional)
1243
+ Opaque pagination token to go to next page based on previous query.
1244
+
1245
+ :returns: Iterator over :class:`CleanRoom`
1246
+ """
1247
+
1248
+ query = {}
1249
+ if page_size is not None: query['page_size'] = page_size
1250
+ if page_token is not None: query['page_token'] = page_token
1251
+ headers = {'Accept': 'application/json', }
1252
+
1253
+ while True:
1254
+ json = self._api.do('GET', '/api/2.0/clean-rooms', query=query, headers=headers)
1255
+ if 'clean_rooms' in json:
1256
+ for v in json['clean_rooms']:
1257
+ yield CleanRoom.from_dict(v)
1258
+ if 'next_page_token' not in json or not json['next_page_token']:
1259
+ return
1260
+ query['page_token'] = json['next_page_token']
1261
+
1262
+ def update(self, name: str, *, clean_room: Optional[CleanRoom] = None) -> CleanRoom:
1263
+ """Update a clean room.
1264
+
1265
+ Update a clean room. The caller must be the owner of the clean room, have **MODIFY_CLEAN_ROOM**
1266
+ privilege, or be metastore admin.
1267
+
1268
+ When the caller is a metastore admin, only the __owner__ field can be updated.
1269
+
1270
+ :param name: str
1271
+ Name of the clean room.
1272
+ :param clean_room: :class:`CleanRoom` (optional)
1273
+
1274
+ :returns: :class:`CleanRoom`
1275
+ """
1276
+ body = {}
1277
+ if clean_room is not None: body['clean_room'] = clean_room.as_dict()
1278
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1279
+
1280
+ res = self._api.do('PATCH', f'/api/2.0/clean-rooms/{name}', body=body, headers=headers)
1281
+ return CleanRoom.from_dict(res)