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.
- databricks/sdk/__init__.py +24 -2
- databricks/sdk/_base_client.py +61 -14
- databricks/sdk/config.py +10 -9
- databricks/sdk/credentials_provider.py +6 -5
- databricks/sdk/mixins/jobs.py +49 -0
- databricks/sdk/mixins/open_ai_client.py +2 -2
- databricks/sdk/service/apps.py +185 -4
- databricks/sdk/service/billing.py +248 -1
- databricks/sdk/service/catalog.py +1943 -46
- databricks/sdk/service/cleanrooms.py +1281 -0
- databricks/sdk/service/compute.py +1486 -8
- databricks/sdk/service/dashboards.py +336 -11
- databricks/sdk/service/files.py +162 -2
- databricks/sdk/service/iam.py +353 -2
- databricks/sdk/service/jobs.py +1281 -16
- databricks/sdk/service/marketplace.py +688 -0
- databricks/sdk/service/ml.py +1038 -2
- databricks/sdk/service/oauth2.py +176 -0
- databricks/sdk/service/pipelines.py +602 -15
- databricks/sdk/service/provisioning.py +402 -0
- databricks/sdk/service/serving.py +615 -0
- databricks/sdk/service/settings.py +1190 -3
- databricks/sdk/service/sharing.py +328 -2
- databricks/sdk/service/sql.py +1186 -2
- databricks/sdk/service/vectorsearch.py +290 -0
- databricks/sdk/service/workspace.py +453 -1
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/METADATA +26 -26
- {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/RECORD +33 -31
- {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/WHEEL +1 -1
- {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/LICENSE +0 -0
- {databricks_sdk-0.37.0.dist-info → databricks_sdk-0.39.0.dist-info}/NOTICE +0 -0
- {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)
|