databricks-sdk 0.40.0__py3-none-any.whl → 0.42.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.

@@ -11,6 +11,8 @@ from ._internal import _enum, _from_dict, _repeated_dict
11
11
 
12
12
  _LOG = logging.getLogger('databricks.sdk')
13
13
 
14
+ from databricks.sdk.service import compute
15
+
14
16
  # all definitions in this file are in alphabetical order
15
17
 
16
18
 
@@ -311,6 +313,44 @@ class BudgetConfigurationFilterWorkspaceIdClause:
311
313
  values=d.get('values', None))
312
314
 
313
315
 
316
+ @dataclass
317
+ class BudgetPolicy:
318
+ """Contains the BudgetPolicy details."""
319
+
320
+ policy_id: str
321
+ """The Id of the policy. This field is generated by Databricks and globally unique."""
322
+
323
+ custom_tags: Optional[List[compute.CustomPolicyTag]] = None
324
+ """A list of tags defined by the customer. At most 20 entries are allowed per policy."""
325
+
326
+ policy_name: Optional[str] = None
327
+ """The name of the policy. - Must be unique among active policies. - Can contain only characters
328
+ from the ISO 8859-1 (latin1) set."""
329
+
330
+ def as_dict(self) -> dict:
331
+ """Serializes the BudgetPolicy into a dictionary suitable for use as a JSON request body."""
332
+ body = {}
333
+ if self.custom_tags: body['custom_tags'] = [v.as_dict() for v in self.custom_tags]
334
+ if self.policy_id is not None: body['policy_id'] = self.policy_id
335
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
336
+ return body
337
+
338
+ def as_shallow_dict(self) -> dict:
339
+ """Serializes the BudgetPolicy into a shallow dictionary of its immediate attributes."""
340
+ body = {}
341
+ if self.custom_tags: body['custom_tags'] = self.custom_tags
342
+ if self.policy_id is not None: body['policy_id'] = self.policy_id
343
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
344
+ return body
345
+
346
+ @classmethod
347
+ def from_dict(cls, d: Dict[str, any]) -> BudgetPolicy:
348
+ """Deserializes the BudgetPolicy from a dictionary."""
349
+ return cls(custom_tags=_repeated_dict(d, 'custom_tags', compute.CustomPolicyTag),
350
+ policy_id=d.get('policy_id', None),
351
+ policy_name=d.get('policy_name', None))
352
+
353
+
314
354
  @dataclass
315
355
  class CreateBillingUsageDashboardRequest:
316
356
  dashboard_type: Optional[UsageDashboardType] = None
@@ -536,6 +576,45 @@ class CreateBudgetConfigurationResponse:
536
576
  return cls(budget=_from_dict(d, 'budget', BudgetConfiguration))
537
577
 
538
578
 
579
+ @dataclass
580
+ class CreateBudgetPolicyRequest:
581
+ """A request to create a BudgetPolicy."""
582
+
583
+ custom_tags: Optional[List[compute.CustomPolicyTag]] = None
584
+ """A list of tags defined by the customer. At most 40 entries are allowed per policy."""
585
+
586
+ policy_name: Optional[str] = None
587
+ """The name of the policy. - Must be unique among active policies. - Can contain only characters of
588
+ 0-9, a-z, A-Z, -, =, ., :, /, @, _, +, whitespace."""
589
+
590
+ request_id: Optional[str] = None
591
+ """A unique identifier for this request. Restricted to 36 ASCII characters. A random UUID is
592
+ recommended. This request is only idempotent if a `request_id` is provided."""
593
+
594
+ def as_dict(self) -> dict:
595
+ """Serializes the CreateBudgetPolicyRequest into a dictionary suitable for use as a JSON request body."""
596
+ body = {}
597
+ if self.custom_tags: body['custom_tags'] = [v.as_dict() for v in self.custom_tags]
598
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
599
+ if self.request_id is not None: body['request_id'] = self.request_id
600
+ return body
601
+
602
+ def as_shallow_dict(self) -> dict:
603
+ """Serializes the CreateBudgetPolicyRequest into a shallow dictionary of its immediate attributes."""
604
+ body = {}
605
+ if self.custom_tags: body['custom_tags'] = self.custom_tags
606
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
607
+ if self.request_id is not None: body['request_id'] = self.request_id
608
+ return body
609
+
610
+ @classmethod
611
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetPolicyRequest:
612
+ """Deserializes the CreateBudgetPolicyRequest from a dictionary."""
613
+ return cls(custom_tags=_repeated_dict(d, 'custom_tags', compute.CustomPolicyTag),
614
+ policy_name=d.get('policy_name', None),
615
+ request_id=d.get('request_id', None))
616
+
617
+
539
618
  @dataclass
540
619
  class CreateLogDeliveryConfigurationParams:
541
620
  log_type: LogType
@@ -670,6 +749,25 @@ class DeleteBudgetConfigurationResponse:
670
749
  return cls()
671
750
 
672
751
 
752
+ @dataclass
753
+ class DeleteResponse:
754
+
755
+ def as_dict(self) -> dict:
756
+ """Serializes the DeleteResponse into a dictionary suitable for use as a JSON request body."""
757
+ body = {}
758
+ return body
759
+
760
+ def as_shallow_dict(self) -> dict:
761
+ """Serializes the DeleteResponse into a shallow dictionary of its immediate attributes."""
762
+ body = {}
763
+ return body
764
+
765
+ @classmethod
766
+ def from_dict(cls, d: Dict[str, any]) -> DeleteResponse:
767
+ """Deserializes the DeleteResponse from a dictionary."""
768
+ return cls()
769
+
770
+
673
771
  class DeliveryStatus(Enum):
674
772
  """The status string for log delivery. Possible values are: * `CREATED`: There were no log delivery
675
773
  attempts since the config was created. * `SUCCEEDED`: The latest attempt of log delivery has
@@ -708,6 +806,44 @@ class DownloadResponse:
708
806
  return cls(contents=d.get('contents', None))
709
807
 
710
808
 
809
+ @dataclass
810
+ class Filter:
811
+ """Structured representation of a filter to be applied to a list of policies. All specified filters
812
+ will be applied in conjunction."""
813
+
814
+ creator_user_id: Optional[int] = None
815
+ """The policy creator user id to be filtered on. If unspecified, all policies will be returned."""
816
+
817
+ creator_user_name: Optional[str] = None
818
+ """The policy creator user name to be filtered on. If unspecified, all policies will be returned."""
819
+
820
+ policy_name: Optional[str] = None
821
+ """The partial name of policies to be filtered on. If unspecified, all policies will be returned."""
822
+
823
+ def as_dict(self) -> dict:
824
+ """Serializes the Filter into a dictionary suitable for use as a JSON request body."""
825
+ body = {}
826
+ if self.creator_user_id is not None: body['creator_user_id'] = self.creator_user_id
827
+ if self.creator_user_name is not None: body['creator_user_name'] = self.creator_user_name
828
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
829
+ return body
830
+
831
+ def as_shallow_dict(self) -> dict:
832
+ """Serializes the Filter into a shallow dictionary of its immediate attributes."""
833
+ body = {}
834
+ if self.creator_user_id is not None: body['creator_user_id'] = self.creator_user_id
835
+ if self.creator_user_name is not None: body['creator_user_name'] = self.creator_user_name
836
+ if self.policy_name is not None: body['policy_name'] = self.policy_name
837
+ return body
838
+
839
+ @classmethod
840
+ def from_dict(cls, d: Dict[str, any]) -> Filter:
841
+ """Deserializes the Filter from a dictionary."""
842
+ return cls(creator_user_id=d.get('creator_user_id', None),
843
+ creator_user_name=d.get('creator_user_name', None),
844
+ policy_name=d.get('policy_name', None))
845
+
846
+
711
847
  @dataclass
712
848
  class GetBillingUsageDashboardResponse:
713
849
  dashboard_id: Optional[str] = None
@@ -787,6 +923,44 @@ class ListBudgetConfigurationsResponse:
787
923
  next_page_token=d.get('next_page_token', None))
788
924
 
789
925
 
926
+ @dataclass
927
+ class ListBudgetPoliciesResponse:
928
+ """A list of policies."""
929
+
930
+ next_page_token: Optional[str] = None
931
+ """A token that can be sent as `page_token` to retrieve the next page. If this field is omitted,
932
+ there are no subsequent pages."""
933
+
934
+ policies: Optional[List[BudgetPolicy]] = None
935
+
936
+ previous_page_token: Optional[str] = None
937
+ """A token that can be sent as `page_token` to retrieve the previous page. In this field is
938
+ omitted, there are no previous pages."""
939
+
940
+ def as_dict(self) -> dict:
941
+ """Serializes the ListBudgetPoliciesResponse into a dictionary suitable for use as a JSON request body."""
942
+ body = {}
943
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
944
+ if self.policies: body['policies'] = [v.as_dict() for v in self.policies]
945
+ if self.previous_page_token is not None: body['previous_page_token'] = self.previous_page_token
946
+ return body
947
+
948
+ def as_shallow_dict(self) -> dict:
949
+ """Serializes the ListBudgetPoliciesResponse into a shallow dictionary of its immediate attributes."""
950
+ body = {}
951
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
952
+ if self.policies: body['policies'] = self.policies
953
+ if self.previous_page_token is not None: body['previous_page_token'] = self.previous_page_token
954
+ return body
955
+
956
+ @classmethod
957
+ def from_dict(cls, d: Dict[str, any]) -> ListBudgetPoliciesResponse:
958
+ """Deserializes the ListBudgetPoliciesResponse from a dictionary."""
959
+ return cls(next_page_token=d.get('next_page_token', None),
960
+ policies=_repeated_dict(d, 'policies', BudgetPolicy),
961
+ previous_page_token=d.get('previous_page_token', None))
962
+
963
+
790
964
  class LogDeliveryConfigStatus(Enum):
791
965
  """Status of log delivery configuration. Set to `ENABLED` (enabled) or `DISABLED` (disabled).
792
966
  Defaults to `ENABLED`. You can [enable or disable the
@@ -1046,6 +1220,39 @@ class PatchStatusResponse:
1046
1220
  return cls()
1047
1221
 
1048
1222
 
1223
+ @dataclass
1224
+ class SortSpec:
1225
+ descending: Optional[bool] = None
1226
+ """Whether to sort in descending order."""
1227
+
1228
+ field: Optional[SortSpecField] = None
1229
+ """The filed to sort by"""
1230
+
1231
+ def as_dict(self) -> dict:
1232
+ """Serializes the SortSpec into a dictionary suitable for use as a JSON request body."""
1233
+ body = {}
1234
+ if self.descending is not None: body['descending'] = self.descending
1235
+ if self.field is not None: body['field'] = self.field.value
1236
+ return body
1237
+
1238
+ def as_shallow_dict(self) -> dict:
1239
+ """Serializes the SortSpec into a shallow dictionary of its immediate attributes."""
1240
+ body = {}
1241
+ if self.descending is not None: body['descending'] = self.descending
1242
+ if self.field is not None: body['field'] = self.field
1243
+ return body
1244
+
1245
+ @classmethod
1246
+ def from_dict(cls, d: Dict[str, any]) -> SortSpec:
1247
+ """Deserializes the SortSpec from a dictionary."""
1248
+ return cls(descending=d.get('descending', None), field=_enum(d, 'field', SortSpecField))
1249
+
1250
+
1251
+ class SortSpecField(Enum):
1252
+
1253
+ POLICY_NAME = 'POLICY_NAME'
1254
+
1255
+
1049
1256
  @dataclass
1050
1257
  class UpdateBudgetConfigurationBudget:
1051
1258
  account_id: Optional[str] = None
@@ -1315,6 +1522,147 @@ class BillableUsageAPI:
1315
1522
  return DownloadResponse.from_dict(res)
1316
1523
 
1317
1524
 
1525
+ class BudgetPolicyAPI:
1526
+ """A service serves REST API about Budget policies"""
1527
+
1528
+ def __init__(self, api_client):
1529
+ self._api = api_client
1530
+
1531
+ def create(self,
1532
+ *,
1533
+ custom_tags: Optional[List[compute.CustomPolicyTag]] = None,
1534
+ policy_name: Optional[str] = None,
1535
+ request_id: Optional[str] = None) -> BudgetPolicy:
1536
+ """Create a budget policy.
1537
+
1538
+ Creates a new policy.
1539
+
1540
+ :param custom_tags: List[:class:`CustomPolicyTag`] (optional)
1541
+ A list of tags defined by the customer. At most 40 entries are allowed per policy.
1542
+ :param policy_name: str (optional)
1543
+ The name of the policy. - Must be unique among active policies. - Can contain only characters of
1544
+ 0-9, a-z, A-Z, -, =, ., :, /, @, _, +, whitespace.
1545
+ :param request_id: str (optional)
1546
+ A unique identifier for this request. Restricted to 36 ASCII characters. A random UUID is
1547
+ recommended. This request is only idempotent if a `request_id` is provided.
1548
+
1549
+ :returns: :class:`BudgetPolicy`
1550
+ """
1551
+ body = {}
1552
+ if custom_tags is not None: body['custom_tags'] = [v.as_dict() for v in custom_tags]
1553
+ if policy_name is not None: body['policy_name'] = policy_name
1554
+ if request_id is not None: body['request_id'] = request_id
1555
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1556
+
1557
+ res = self._api.do('POST',
1558
+ f'/api/2.1/accounts/{self._api.account_id}/budget-policies',
1559
+ body=body,
1560
+ headers=headers)
1561
+ return BudgetPolicy.from_dict(res)
1562
+
1563
+ def delete(self, policy_id: str):
1564
+ """Delete a budget policy.
1565
+
1566
+ Deletes a policy
1567
+
1568
+ :param policy_id: str
1569
+ The Id of the policy.
1570
+
1571
+
1572
+ """
1573
+
1574
+ headers = {'Accept': 'application/json', }
1575
+
1576
+ self._api.do('DELETE',
1577
+ f'/api/2.1/accounts/{self._api.account_id}/budget-policies/{policy_id}',
1578
+ headers=headers)
1579
+
1580
+ def get(self, policy_id: str) -> BudgetPolicy:
1581
+ """Get a budget policy.
1582
+
1583
+ Retrieves a policy by it's ID.
1584
+
1585
+ :param policy_id: str
1586
+ The Id of the policy.
1587
+
1588
+ :returns: :class:`BudgetPolicy`
1589
+ """
1590
+
1591
+ headers = {'Accept': 'application/json', }
1592
+
1593
+ res = self._api.do('GET',
1594
+ f'/api/2.1/accounts/{self._api.account_id}/budget-policies/{policy_id}',
1595
+ headers=headers)
1596
+ return BudgetPolicy.from_dict(res)
1597
+
1598
+ def list(self,
1599
+ *,
1600
+ filter_by: Optional[Filter] = None,
1601
+ page_size: Optional[int] = None,
1602
+ page_token: Optional[str] = None,
1603
+ sort_spec: Optional[SortSpec] = None) -> Iterator[BudgetPolicy]:
1604
+ """List policies.
1605
+
1606
+ Lists all policies. Policies are returned in the alphabetically ascending order of their names.
1607
+
1608
+ :param filter_by: :class:`Filter` (optional)
1609
+ A filter to apply to the list of policies.
1610
+ :param page_size: int (optional)
1611
+ The maximum number of budget policies to return. If unspecified, at most 100 budget policies will be
1612
+ returned. The maximum value is 1000; values above 1000 will be coerced to 1000.
1613
+ :param page_token: str (optional)
1614
+ A page token, received from a previous `ListServerlessPolicies` call. Provide this to retrieve the
1615
+ subsequent page. If unspecified, the first page will be returned.
1616
+
1617
+ When paginating, all other parameters provided to `ListServerlessPoliciesRequest` must match the
1618
+ call that provided the page token.
1619
+ :param sort_spec: :class:`SortSpec` (optional)
1620
+ The sort specification.
1621
+
1622
+ :returns: Iterator over :class:`BudgetPolicy`
1623
+ """
1624
+
1625
+ query = {}
1626
+ if filter_by is not None: query['filter_by'] = filter_by.as_dict()
1627
+ if page_size is not None: query['page_size'] = page_size
1628
+ if page_token is not None: query['page_token'] = page_token
1629
+ if sort_spec is not None: query['sort_spec'] = sort_spec.as_dict()
1630
+ headers = {'Accept': 'application/json', }
1631
+
1632
+ while True:
1633
+ json = self._api.do('GET',
1634
+ f'/api/2.1/accounts/{self._api.account_id}/budget-policies',
1635
+ query=query,
1636
+ headers=headers)
1637
+ if 'policies' in json:
1638
+ for v in json['policies']:
1639
+ yield BudgetPolicy.from_dict(v)
1640
+ if 'next_page_token' not in json or not json['next_page_token']:
1641
+ return
1642
+ query['page_token'] = json['next_page_token']
1643
+
1644
+ def update(self, policy_id: str, *, policy: Optional[BudgetPolicy] = None) -> BudgetPolicy:
1645
+ """Update a budget policy.
1646
+
1647
+ Updates a policy
1648
+
1649
+ :param policy_id: str
1650
+ The Id of the policy. This field is generated by Databricks and globally unique.
1651
+ :param policy: :class:`BudgetPolicy` (optional)
1652
+ Contains the BudgetPolicy details.
1653
+
1654
+ :returns: :class:`BudgetPolicy`
1655
+ """
1656
+ body = policy.as_dict()
1657
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1658
+
1659
+ res = self._api.do('PATCH',
1660
+ f'/api/2.1/accounts/{self._api.account_id}/budget-policies/{policy_id}',
1661
+ body=body,
1662
+ headers=headers)
1663
+ return BudgetPolicy.from_dict(res)
1664
+
1665
+
1318
1666
  class BudgetsAPI:
1319
1667
  """These APIs manage budget configurations for this account. Budgets enable you to monitor usage across your
1320
1668
  account. You can set up budgets to either track account-wide spending, or apply filters to track the
@@ -787,9 +787,6 @@ class CatalogInfo:
787
787
  provisioning_info: Optional[ProvisioningInfo] = None
788
788
  """Status of an asynchronously provisioned resource."""
789
789
 
790
- securable_kind: Optional[CatalogInfoSecurableKind] = None
791
- """Kind of catalog securable."""
792
-
793
790
  securable_type: Optional[str] = None
794
791
 
795
792
  share_name: Optional[str] = None
@@ -831,7 +828,6 @@ class CatalogInfo:
831
828
  if self.properties: body['properties'] = self.properties
832
829
  if self.provider_name is not None: body['provider_name'] = self.provider_name
833
830
  if self.provisioning_info: body['provisioning_info'] = self.provisioning_info.as_dict()
834
- if self.securable_kind is not None: body['securable_kind'] = self.securable_kind.value
835
831
  if self.securable_type is not None: body['securable_type'] = self.securable_type
836
832
  if self.share_name is not None: body['share_name'] = self.share_name
837
833
  if self.storage_location is not None: body['storage_location'] = self.storage_location
@@ -862,7 +858,6 @@ class CatalogInfo:
862
858
  if self.properties: body['properties'] = self.properties
863
859
  if self.provider_name is not None: body['provider_name'] = self.provider_name
864
860
  if self.provisioning_info: body['provisioning_info'] = self.provisioning_info
865
- if self.securable_kind is not None: body['securable_kind'] = self.securable_kind
866
861
  if self.securable_type is not None: body['securable_type'] = self.securable_type
867
862
  if self.share_name is not None: body['share_name'] = self.share_name
868
863
  if self.storage_location is not None: body['storage_location'] = self.storage_location
@@ -893,7 +888,6 @@ class CatalogInfo:
893
888
  properties=d.get('properties', None),
894
889
  provider_name=d.get('provider_name', None),
895
890
  provisioning_info=_from_dict(d, 'provisioning_info', ProvisioningInfo),
896
- securable_kind=_enum(d, 'securable_kind', CatalogInfoSecurableKind),
897
891
  securable_type=d.get('securable_type', None),
898
892
  share_name=d.get('share_name', None),
899
893
  storage_location=d.get('storage_location', None),
@@ -902,24 +896,6 @@ class CatalogInfo:
902
896
  updated_by=d.get('updated_by', None))
903
897
 
904
898
 
905
- class CatalogInfoSecurableKind(Enum):
906
- """Kind of catalog securable."""
907
-
908
- CATALOG_DELTASHARING = 'CATALOG_DELTASHARING'
909
- CATALOG_FOREIGN_BIGQUERY = 'CATALOG_FOREIGN_BIGQUERY'
910
- CATALOG_FOREIGN_DATABRICKS = 'CATALOG_FOREIGN_DATABRICKS'
911
- CATALOG_FOREIGN_MYSQL = 'CATALOG_FOREIGN_MYSQL'
912
- CATALOG_FOREIGN_POSTGRESQL = 'CATALOG_FOREIGN_POSTGRESQL'
913
- CATALOG_FOREIGN_REDSHIFT = 'CATALOG_FOREIGN_REDSHIFT'
914
- CATALOG_FOREIGN_SNOWFLAKE = 'CATALOG_FOREIGN_SNOWFLAKE'
915
- CATALOG_FOREIGN_SQLDW = 'CATALOG_FOREIGN_SQLDW'
916
- CATALOG_FOREIGN_SQLSERVER = 'CATALOG_FOREIGN_SQLSERVER'
917
- CATALOG_INTERNAL = 'CATALOG_INTERNAL'
918
- CATALOG_STANDARD = 'CATALOG_STANDARD'
919
- CATALOG_SYSTEM = 'CATALOG_SYSTEM'
920
- CATALOG_SYSTEM_DELTASHARING = 'CATALOG_SYSTEM_DELTASHARING'
921
-
922
-
923
899
  class CatalogIsolationMode(Enum):
924
900
  """Whether the current securable is accessible from all workspaces or a specific set of workspaces."""
925
901
 
@@ -1158,9 +1134,6 @@ class ConnectionInfo:
1158
1134
  read_only: Optional[bool] = None
1159
1135
  """If the connection is read only."""
1160
1136
 
1161
- securable_kind: Optional[ConnectionInfoSecurableKind] = None
1162
- """Kind of connection securable."""
1163
-
1164
1137
  securable_type: Optional[str] = None
1165
1138
 
1166
1139
  updated_at: Optional[int] = None
@@ -1189,7 +1162,6 @@ class ConnectionInfo:
1189
1162
  if self.properties: body['properties'] = self.properties
1190
1163
  if self.provisioning_info: body['provisioning_info'] = self.provisioning_info.as_dict()
1191
1164
  if self.read_only is not None: body['read_only'] = self.read_only
1192
- if self.securable_kind is not None: body['securable_kind'] = self.securable_kind.value
1193
1165
  if self.securable_type is not None: body['securable_type'] = self.securable_type
1194
1166
  if self.updated_at is not None: body['updated_at'] = self.updated_at
1195
1167
  if self.updated_by is not None: body['updated_by'] = self.updated_by
@@ -1213,7 +1185,6 @@ class ConnectionInfo:
1213
1185
  if self.properties: body['properties'] = self.properties
1214
1186
  if self.provisioning_info: body['provisioning_info'] = self.provisioning_info
1215
1187
  if self.read_only is not None: body['read_only'] = self.read_only
1216
- if self.securable_kind is not None: body['securable_kind'] = self.securable_kind
1217
1188
  if self.securable_type is not None: body['securable_type'] = self.securable_type
1218
1189
  if self.updated_at is not None: body['updated_at'] = self.updated_at
1219
1190
  if self.updated_by is not None: body['updated_by'] = self.updated_by
@@ -1237,31 +1208,12 @@ class ConnectionInfo:
1237
1208
  properties=d.get('properties', None),
1238
1209
  provisioning_info=_from_dict(d, 'provisioning_info', ProvisioningInfo),
1239
1210
  read_only=d.get('read_only', None),
1240
- securable_kind=_enum(d, 'securable_kind', ConnectionInfoSecurableKind),
1241
1211
  securable_type=d.get('securable_type', None),
1242
1212
  updated_at=d.get('updated_at', None),
1243
1213
  updated_by=d.get('updated_by', None),
1244
1214
  url=d.get('url', None))
1245
1215
 
1246
1216
 
1247
- class ConnectionInfoSecurableKind(Enum):
1248
- """Kind of connection securable."""
1249
-
1250
- CONNECTION_BIGQUERY = 'CONNECTION_BIGQUERY'
1251
- CONNECTION_BUILTIN_HIVE_METASTORE = 'CONNECTION_BUILTIN_HIVE_METASTORE'
1252
- CONNECTION_DATABRICKS = 'CONNECTION_DATABRICKS'
1253
- CONNECTION_EXTERNAL_HIVE_METASTORE = 'CONNECTION_EXTERNAL_HIVE_METASTORE'
1254
- CONNECTION_GLUE = 'CONNECTION_GLUE'
1255
- CONNECTION_HTTP_BEARER = 'CONNECTION_HTTP_BEARER'
1256
- CONNECTION_MYSQL = 'CONNECTION_MYSQL'
1257
- CONNECTION_ONLINE_CATALOG = 'CONNECTION_ONLINE_CATALOG'
1258
- CONNECTION_POSTGRESQL = 'CONNECTION_POSTGRESQL'
1259
- CONNECTION_REDSHIFT = 'CONNECTION_REDSHIFT'
1260
- CONNECTION_SNOWFLAKE = 'CONNECTION_SNOWFLAKE'
1261
- CONNECTION_SQLDW = 'CONNECTION_SQLDW'
1262
- CONNECTION_SQLSERVER = 'CONNECTION_SQLSERVER'
1263
-
1264
-
1265
1217
  class ConnectionType(Enum):
1266
1218
  """The type of connection."""
1267
1219
 
@@ -5810,6 +5762,7 @@ class ProvisioningInfo:
5810
5762
  class ProvisioningInfoState(Enum):
5811
5763
 
5812
5764
  ACTIVE = 'ACTIVE'
5765
+ DEGRADED = 'DEGRADED'
5813
5766
  DELETING = 'DELETING'
5814
5767
  FAILED = 'FAILED'
5815
5768
  PROVISIONING = 'PROVISIONING'
@@ -6268,20 +6221,21 @@ SecurablePropertiesMap = Dict[str, str]
6268
6221
  class SecurableType(Enum):
6269
6222
  """The type of Unity Catalog securable"""
6270
6223
 
6271
- CATALOG = 'catalog'
6272
- CONNECTION = 'connection'
6273
- CREDENTIAL = 'credential'
6274
- EXTERNAL_LOCATION = 'external_location'
6275
- FUNCTION = 'function'
6276
- METASTORE = 'metastore'
6277
- PIPELINE = 'pipeline'
6278
- PROVIDER = 'provider'
6279
- RECIPIENT = 'recipient'
6280
- SCHEMA = 'schema'
6281
- SHARE = 'share'
6282
- STORAGE_CREDENTIAL = 'storage_credential'
6283
- TABLE = 'table'
6284
- VOLUME = 'volume'
6224
+ CATALOG = 'CATALOG'
6225
+ CLEAN_ROOM = 'CLEAN_ROOM'
6226
+ CONNECTION = 'CONNECTION'
6227
+ CREDENTIAL = 'CREDENTIAL'
6228
+ EXTERNAL_LOCATION = 'EXTERNAL_LOCATION'
6229
+ FUNCTION = 'FUNCTION'
6230
+ METASTORE = 'METASTORE'
6231
+ PIPELINE = 'PIPELINE'
6232
+ PROVIDER = 'PROVIDER'
6233
+ RECIPIENT = 'RECIPIENT'
6234
+ SCHEMA = 'SCHEMA'
6235
+ SHARE = 'SHARE'
6236
+ STORAGE_CREDENTIAL = 'STORAGE_CREDENTIAL'
6237
+ TABLE = 'TABLE'
6238
+ VOLUME = 'VOLUME'
6285
6239
 
6286
6240
 
6287
6241
  @dataclass
@@ -289,11 +289,24 @@ class CleanRoomAssetNotebook:
289
289
  """Base 64 representation of the notebook contents. This is the same format as returned by
290
290
  :method:workspace/export with the format of **HTML**."""
291
291
 
292
+ review_state: Optional[CleanRoomNotebookReviewNotebookReviewState] = None
293
+ """top-level status derived from all reviews"""
294
+
295
+ reviews: Optional[List[CleanRoomNotebookReview]] = None
296
+ """All existing approvals or rejections"""
297
+
298
+ runner_collaborators: Optional[List[CleanRoomCollaborator]] = None
299
+ """collaborators that can run the notebook"""
300
+
292
301
  def as_dict(self) -> dict:
293
302
  """Serializes the CleanRoomAssetNotebook into a dictionary suitable for use as a JSON request body."""
294
303
  body = {}
295
304
  if self.etag is not None: body['etag'] = self.etag
296
305
  if self.notebook_content is not None: body['notebook_content'] = self.notebook_content
306
+ if self.review_state is not None: body['review_state'] = self.review_state.value
307
+ if self.reviews: body['reviews'] = [v.as_dict() for v in self.reviews]
308
+ if self.runner_collaborators:
309
+ body['runner_collaborators'] = [v.as_dict() for v in self.runner_collaborators]
297
310
  return body
298
311
 
299
312
  def as_shallow_dict(self) -> dict:
@@ -301,17 +314,25 @@ class CleanRoomAssetNotebook:
301
314
  body = {}
302
315
  if self.etag is not None: body['etag'] = self.etag
303
316
  if self.notebook_content is not None: body['notebook_content'] = self.notebook_content
317
+ if self.review_state is not None: body['review_state'] = self.review_state
318
+ if self.reviews: body['reviews'] = self.reviews
319
+ if self.runner_collaborators: body['runner_collaborators'] = self.runner_collaborators
304
320
  return body
305
321
 
306
322
  @classmethod
307
323
  def from_dict(cls, d: Dict[str, any]) -> CleanRoomAssetNotebook:
308
324
  """Deserializes the CleanRoomAssetNotebook from a dictionary."""
309
- return cls(etag=d.get('etag', None), notebook_content=d.get('notebook_content', None))
325
+ return cls(etag=d.get('etag', None),
326
+ notebook_content=d.get('notebook_content', None),
327
+ review_state=_enum(d, 'review_state', CleanRoomNotebookReviewNotebookReviewState),
328
+ reviews=_repeated_dict(d, 'reviews', CleanRoomNotebookReview),
329
+ runner_collaborators=_repeated_dict(d, 'runner_collaborators', CleanRoomCollaborator))
310
330
 
311
331
 
312
332
  class CleanRoomAssetStatusEnum(Enum):
313
333
 
314
334
  ACTIVE = 'ACTIVE'
335
+ PENDING = 'PENDING'
315
336
  PERMISSION_DENIED = 'PERMISSION_DENIED'
316
337
 
317
338
 
@@ -443,7 +464,7 @@ class CleanRoomAssetVolumeLocalDetails:
443
464
  class CleanRoomCollaborator:
444
465
  """Publicly visible clean room collaborator."""
445
466
 
446
- collaborator_alias: Optional[str] = None
467
+ collaborator_alias: str
447
468
  """Collaborator alias specified by the clean room creator. It is unique across all collaborators of
448
469
  this clean room, and used to derive multiple values internally such as catalog alias and clean
449
470
  room name for single metastore clean rooms. It should follow [UC securable naming requirements].
@@ -510,6 +531,56 @@ class CleanRoomCollaborator:
510
531
  organization_name=d.get('organization_name', None))
511
532
 
512
533
 
534
+ @dataclass
535
+ class CleanRoomNotebookReview:
536
+ comment: Optional[str] = None
537
+ """review comment"""
538
+
539
+ created_at_millis: Optional[int] = None
540
+ """timestamp of when the review was submitted"""
541
+
542
+ review_state: Optional[CleanRoomNotebookReviewNotebookReviewState] = None
543
+ """review outcome"""
544
+
545
+ reviewer_collaborator_alias: Optional[str] = None
546
+ """collaborator alias of the reviewer"""
547
+
548
+ def as_dict(self) -> dict:
549
+ """Serializes the CleanRoomNotebookReview into a dictionary suitable for use as a JSON request body."""
550
+ body = {}
551
+ if self.comment is not None: body['comment'] = self.comment
552
+ if self.created_at_millis is not None: body['created_at_millis'] = self.created_at_millis
553
+ if self.review_state is not None: body['review_state'] = self.review_state.value
554
+ if self.reviewer_collaborator_alias is not None:
555
+ body['reviewer_collaborator_alias'] = self.reviewer_collaborator_alias
556
+ return body
557
+
558
+ def as_shallow_dict(self) -> dict:
559
+ """Serializes the CleanRoomNotebookReview into a shallow dictionary of its immediate attributes."""
560
+ body = {}
561
+ if self.comment is not None: body['comment'] = self.comment
562
+ if self.created_at_millis is not None: body['created_at_millis'] = self.created_at_millis
563
+ if self.review_state is not None: body['review_state'] = self.review_state
564
+ if self.reviewer_collaborator_alias is not None:
565
+ body['reviewer_collaborator_alias'] = self.reviewer_collaborator_alias
566
+ return body
567
+
568
+ @classmethod
569
+ def from_dict(cls, d: Dict[str, any]) -> CleanRoomNotebookReview:
570
+ """Deserializes the CleanRoomNotebookReview from a dictionary."""
571
+ return cls(comment=d.get('comment', None),
572
+ created_at_millis=d.get('created_at_millis', None),
573
+ review_state=_enum(d, 'review_state', CleanRoomNotebookReviewNotebookReviewState),
574
+ reviewer_collaborator_alias=d.get('reviewer_collaborator_alias', None))
575
+
576
+
577
+ class CleanRoomNotebookReviewNotebookReviewState(Enum):
578
+
579
+ APPROVED = 'APPROVED'
580
+ PENDING = 'PENDING'
581
+ REJECTED = 'REJECTED'
582
+
583
+
513
584
  @dataclass
514
585
  class CleanRoomNotebookTaskRun:
515
586
  """Stores information about a single task run."""