Files
zenml/venv/lib/python3.9/site-packages/databricks/sdk/service/sharing.py
Christian Mantha 2ca0b9ef7c star
2026-03-02 19:10:52 -05:00

3535 lines
139 KiB
Python

# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
from __future__ import annotations
import logging
from dataclasses import dataclass
from enum import Enum
from typing import Any, Dict, Iterator, List, Optional
from databricks.sdk.client_types import HostType
from databricks.sdk.service import catalog
from databricks.sdk.service._internal import (_enum, _from_dict,
_repeated_dict, _repeated_enum)
_LOG = logging.getLogger("databricks.sdk")
# all definitions in this file are in alphabetical order
class AuthenticationType(Enum):
"""The delta sharing authentication type."""
DATABRICKS = "DATABRICKS"
OAUTH_CLIENT_CREDENTIALS = "OAUTH_CLIENT_CREDENTIALS"
OIDC_FEDERATION = "OIDC_FEDERATION"
TOKEN = "TOKEN"
class ColumnTypeName(Enum):
"""UC supported column types Copied from
https://src.dev.databricks.com/databricks/universe@23a85902bb58695ab9293adc9f327b0714b55e72/-/blob/managed-catalog/api/messages/table.proto?L68
"""
ARRAY = "ARRAY"
BINARY = "BINARY"
BOOLEAN = "BOOLEAN"
BYTE = "BYTE"
CHAR = "CHAR"
DATE = "DATE"
DECIMAL = "DECIMAL"
DOUBLE = "DOUBLE"
FLOAT = "FLOAT"
INT = "INT"
INTERVAL = "INTERVAL"
LONG = "LONG"
MAP = "MAP"
NULL = "NULL"
SHORT = "SHORT"
STRING = "STRING"
STRUCT = "STRUCT"
TABLE_TYPE = "TABLE_TYPE"
TIMESTAMP = "TIMESTAMP"
TIMESTAMP_NTZ = "TIMESTAMP_NTZ"
USER_DEFINED_TYPE = "USER_DEFINED_TYPE"
VARIANT = "VARIANT"
@dataclass
class DeltaSharingDependency:
"""Represents a UC dependency."""
function: Optional[DeltaSharingFunctionDependency] = None
table: Optional[DeltaSharingTableDependency] = None
def as_dict(self) -> dict:
"""Serializes the DeltaSharingDependency into a dictionary suitable for use as a JSON request body."""
body = {}
if self.function:
body["function"] = self.function.as_dict()
if self.table:
body["table"] = self.table.as_dict()
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeltaSharingDependency into a shallow dictionary of its immediate attributes."""
body = {}
if self.function:
body["function"] = self.function
if self.table:
body["table"] = self.table
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeltaSharingDependency:
"""Deserializes the DeltaSharingDependency from a dictionary."""
return cls(
function=_from_dict(d, "function", DeltaSharingFunctionDependency),
table=_from_dict(d, "table", DeltaSharingTableDependency),
)
@dataclass
class DeltaSharingDependencyList:
"""Represents a list of dependencies."""
dependencies: Optional[List[DeltaSharingDependency]] = None
"""An array of Dependency."""
def as_dict(self) -> dict:
"""Serializes the DeltaSharingDependencyList into a dictionary suitable for use as a JSON request body."""
body = {}
if self.dependencies:
body["dependencies"] = [v.as_dict() for v in self.dependencies]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeltaSharingDependencyList into a shallow dictionary of its immediate attributes."""
body = {}
if self.dependencies:
body["dependencies"] = self.dependencies
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeltaSharingDependencyList:
"""Deserializes the DeltaSharingDependencyList from a dictionary."""
return cls(dependencies=_repeated_dict(d, "dependencies", DeltaSharingDependency))
@dataclass
class DeltaSharingFunction:
aliases: Optional[List[RegisteredModelAlias]] = None
"""The aliass of registered model."""
comment: Optional[str] = None
"""The comment of the function."""
data_type: Optional[ColumnTypeName] = None
"""The data type of the function."""
dependency_list: Optional[DeltaSharingDependencyList] = None
"""The dependency list of the function."""
full_data_type: Optional[str] = None
"""The full data type of the function."""
id: Optional[str] = None
"""The id of the function."""
input_params: Optional[FunctionParameterInfos] = None
"""The function parameter information."""
name: Optional[str] = None
"""The name of the function."""
properties: Optional[str] = None
"""The properties of the function."""
routine_definition: Optional[str] = None
"""The routine definition of the function."""
schema: Optional[str] = None
"""The name of the schema that the function belongs to."""
securable_kind: Optional[SharedSecurableKind] = None
"""The securable kind of the function."""
share: Optional[str] = None
"""The name of the share that the function belongs to."""
share_id: Optional[str] = None
"""The id of the share that the function belongs to."""
storage_location: Optional[str] = None
"""The storage location of the function."""
tags: Optional[List[catalog.TagKeyValue]] = None
"""The tags of the function."""
def as_dict(self) -> dict:
"""Serializes the DeltaSharingFunction into a dictionary suitable for use as a JSON request body."""
body = {}
if self.aliases:
body["aliases"] = [v.as_dict() for v in self.aliases]
if self.comment is not None:
body["comment"] = self.comment
if self.data_type is not None:
body["data_type"] = self.data_type.value
if self.dependency_list:
body["dependency_list"] = self.dependency_list.as_dict()
if self.full_data_type is not None:
body["full_data_type"] = self.full_data_type
if self.id is not None:
body["id"] = self.id
if self.input_params:
body["input_params"] = self.input_params.as_dict()
if self.name is not None:
body["name"] = self.name
if self.properties is not None:
body["properties"] = self.properties
if self.routine_definition is not None:
body["routine_definition"] = self.routine_definition
if self.schema is not None:
body["schema"] = self.schema
if self.securable_kind is not None:
body["securable_kind"] = self.securable_kind.value
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.storage_location is not None:
body["storage_location"] = self.storage_location
if self.tags:
body["tags"] = [v.as_dict() for v in self.tags]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeltaSharingFunction into a shallow dictionary of its immediate attributes."""
body = {}
if self.aliases:
body["aliases"] = self.aliases
if self.comment is not None:
body["comment"] = self.comment
if self.data_type is not None:
body["data_type"] = self.data_type
if self.dependency_list:
body["dependency_list"] = self.dependency_list
if self.full_data_type is not None:
body["full_data_type"] = self.full_data_type
if self.id is not None:
body["id"] = self.id
if self.input_params:
body["input_params"] = self.input_params
if self.name is not None:
body["name"] = self.name
if self.properties is not None:
body["properties"] = self.properties
if self.routine_definition is not None:
body["routine_definition"] = self.routine_definition
if self.schema is not None:
body["schema"] = self.schema
if self.securable_kind is not None:
body["securable_kind"] = self.securable_kind
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.storage_location is not None:
body["storage_location"] = self.storage_location
if self.tags:
body["tags"] = self.tags
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeltaSharingFunction:
"""Deserializes the DeltaSharingFunction from a dictionary."""
return cls(
aliases=_repeated_dict(d, "aliases", RegisteredModelAlias),
comment=d.get("comment", None),
data_type=_enum(d, "data_type", ColumnTypeName),
dependency_list=_from_dict(d, "dependency_list", DeltaSharingDependencyList),
full_data_type=d.get("full_data_type", None),
id=d.get("id", None),
input_params=_from_dict(d, "input_params", FunctionParameterInfos),
name=d.get("name", None),
properties=d.get("properties", None),
routine_definition=d.get("routine_definition", None),
schema=d.get("schema", None),
securable_kind=_enum(d, "securable_kind", SharedSecurableKind),
share=d.get("share", None),
share_id=d.get("share_id", None),
storage_location=d.get("storage_location", None),
tags=_repeated_dict(d, "tags", catalog.TagKeyValue),
)
@dataclass
class DeltaSharingFunctionDependency:
"""A Function in UC as a dependency."""
function_name: Optional[str] = None
schema_name: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the DeltaSharingFunctionDependency into a dictionary suitable for use as a JSON request body."""
body = {}
if self.function_name is not None:
body["function_name"] = self.function_name
if self.schema_name is not None:
body["schema_name"] = self.schema_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeltaSharingFunctionDependency into a shallow dictionary of its immediate attributes."""
body = {}
if self.function_name is not None:
body["function_name"] = self.function_name
if self.schema_name is not None:
body["schema_name"] = self.schema_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeltaSharingFunctionDependency:
"""Deserializes the DeltaSharingFunctionDependency from a dictionary."""
return cls(function_name=d.get("function_name", None), schema_name=d.get("schema_name", None))
@dataclass
class DeltaSharingTableDependency:
"""A Table in UC as a dependency."""
schema_name: Optional[str] = None
table_name: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the DeltaSharingTableDependency into a dictionary suitable for use as a JSON request body."""
body = {}
if self.schema_name is not None:
body["schema_name"] = self.schema_name
if self.table_name is not None:
body["table_name"] = self.table_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeltaSharingTableDependency into a shallow dictionary of its immediate attributes."""
body = {}
if self.schema_name is not None:
body["schema_name"] = self.schema_name
if self.table_name is not None:
body["table_name"] = self.table_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeltaSharingTableDependency:
"""Deserializes the DeltaSharingTableDependency from a dictionary."""
return cls(schema_name=d.get("schema_name", None), table_name=d.get("table_name", None))
@dataclass
class FederationPolicy:
comment: Optional[str] = None
"""Description of the policy. This is a user-provided description."""
create_time: Optional[str] = None
"""System-generated timestamp indicating when the policy was created."""
id: Optional[str] = None
"""Unique, immutable system-generated identifier for the federation policy."""
name: Optional[str] = None
"""Name of the federation policy. A recipient can have multiple policies with different names. The
name must contain only lowercase alphanumeric characters, numbers, and hyphens."""
oidc_policy: Optional[OidcFederationPolicy] = None
"""Specifies the policy to use for validating OIDC claims in the federated tokens."""
update_time: Optional[str] = None
"""System-generated timestamp indicating when the policy was last updated."""
def as_dict(self) -> dict:
"""Serializes the FederationPolicy into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.create_time is not None:
body["create_time"] = self.create_time
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.oidc_policy:
body["oidc_policy"] = self.oidc_policy.as_dict()
if self.update_time is not None:
body["update_time"] = self.update_time
return body
def as_shallow_dict(self) -> dict:
"""Serializes the FederationPolicy into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.create_time is not None:
body["create_time"] = self.create_time
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.oidc_policy:
body["oidc_policy"] = self.oidc_policy
if self.update_time is not None:
body["update_time"] = self.update_time
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> FederationPolicy:
"""Deserializes the FederationPolicy from a dictionary."""
return cls(
comment=d.get("comment", None),
create_time=d.get("create_time", None),
id=d.get("id", None),
name=d.get("name", None),
oidc_policy=_from_dict(d, "oidc_policy", OidcFederationPolicy),
update_time=d.get("update_time", None),
)
@dataclass
class FunctionParameterInfo:
"""Represents a parameter of a function. The same message is used for both input and output
columns."""
comment: Optional[str] = None
"""The comment of the parameter."""
name: Optional[str] = None
"""The name of the parameter."""
parameter_default: Optional[str] = None
"""The default value of the parameter."""
parameter_mode: Optional[FunctionParameterMode] = None
"""The mode of the function parameter."""
parameter_type: Optional[FunctionParameterType] = None
"""The type of the function parameter."""
position: Optional[int] = None
"""The position of the parameter."""
type_interval_type: Optional[str] = None
"""The interval type of the parameter type."""
type_json: Optional[str] = None
"""The type of the parameter in JSON format."""
type_name: Optional[ColumnTypeName] = None
"""The type of the parameter in Enum format."""
type_precision: Optional[int] = None
"""The precision of the parameter type."""
type_scale: Optional[int] = None
"""The scale of the parameter type."""
type_text: Optional[str] = None
"""The type of the parameter in text format."""
def as_dict(self) -> dict:
"""Serializes the FunctionParameterInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.name is not None:
body["name"] = self.name
if self.parameter_default is not None:
body["parameter_default"] = self.parameter_default
if self.parameter_mode is not None:
body["parameter_mode"] = self.parameter_mode.value
if self.parameter_type is not None:
body["parameter_type"] = self.parameter_type.value
if self.position is not None:
body["position"] = self.position
if self.type_interval_type is not None:
body["type_interval_type"] = self.type_interval_type
if self.type_json is not None:
body["type_json"] = self.type_json
if self.type_name is not None:
body["type_name"] = self.type_name.value
if self.type_precision is not None:
body["type_precision"] = self.type_precision
if self.type_scale is not None:
body["type_scale"] = self.type_scale
if self.type_text is not None:
body["type_text"] = self.type_text
return body
def as_shallow_dict(self) -> dict:
"""Serializes the FunctionParameterInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.name is not None:
body["name"] = self.name
if self.parameter_default is not None:
body["parameter_default"] = self.parameter_default
if self.parameter_mode is not None:
body["parameter_mode"] = self.parameter_mode
if self.parameter_type is not None:
body["parameter_type"] = self.parameter_type
if self.position is not None:
body["position"] = self.position
if self.type_interval_type is not None:
body["type_interval_type"] = self.type_interval_type
if self.type_json is not None:
body["type_json"] = self.type_json
if self.type_name is not None:
body["type_name"] = self.type_name
if self.type_precision is not None:
body["type_precision"] = self.type_precision
if self.type_scale is not None:
body["type_scale"] = self.type_scale
if self.type_text is not None:
body["type_text"] = self.type_text
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> FunctionParameterInfo:
"""Deserializes the FunctionParameterInfo from a dictionary."""
return cls(
comment=d.get("comment", None),
name=d.get("name", None),
parameter_default=d.get("parameter_default", None),
parameter_mode=_enum(d, "parameter_mode", FunctionParameterMode),
parameter_type=_enum(d, "parameter_type", FunctionParameterType),
position=d.get("position", None),
type_interval_type=d.get("type_interval_type", None),
type_json=d.get("type_json", None),
type_name=_enum(d, "type_name", ColumnTypeName),
type_precision=d.get("type_precision", None),
type_scale=d.get("type_scale", None),
type_text=d.get("type_text", None),
)
@dataclass
class FunctionParameterInfos:
parameters: Optional[List[FunctionParameterInfo]] = None
"""The list of parameters of the function."""
def as_dict(self) -> dict:
"""Serializes the FunctionParameterInfos into a dictionary suitable for use as a JSON request body."""
body = {}
if self.parameters:
body["parameters"] = [v.as_dict() for v in self.parameters]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the FunctionParameterInfos into a shallow dictionary of its immediate attributes."""
body = {}
if self.parameters:
body["parameters"] = self.parameters
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> FunctionParameterInfos:
"""Deserializes the FunctionParameterInfos from a dictionary."""
return cls(parameters=_repeated_dict(d, "parameters", FunctionParameterInfo))
class FunctionParameterMode(Enum):
IN = "IN"
INOUT = "INOUT"
OUT = "OUT"
class FunctionParameterType(Enum):
COLUMN = "COLUMN"
PARAM = "PARAM"
@dataclass
class GetActivationUrlInfoResponse:
def as_dict(self) -> dict:
"""Serializes the GetActivationUrlInfoResponse into a dictionary suitable for use as a JSON request body."""
body = {}
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetActivationUrlInfoResponse into a shallow dictionary of its immediate attributes."""
body = {}
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetActivationUrlInfoResponse:
"""Deserializes the GetActivationUrlInfoResponse from a dictionary."""
return cls()
@dataclass
class GetRecipientSharePermissionsResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
permissions_out: Optional[List[ShareToPrivilegeAssignment]] = None
"""An array of data share permissions for a recipient."""
def as_dict(self) -> dict:
"""Serializes the GetRecipientSharePermissionsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.permissions_out:
body["permissions_out"] = [v.as_dict() for v in self.permissions_out]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetRecipientSharePermissionsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.permissions_out:
body["permissions_out"] = self.permissions_out
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetRecipientSharePermissionsResponse:
"""Deserializes the GetRecipientSharePermissionsResponse from a dictionary."""
return cls(
next_page_token=d.get("next_page_token", None),
permissions_out=_repeated_dict(d, "permissions_out", ShareToPrivilegeAssignment),
)
@dataclass
class GetSharePermissionsResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
privilege_assignments: Optional[List[PrivilegeAssignment]] = None
"""The privileges assigned to each principal"""
def as_dict(self) -> dict:
"""Serializes the GetSharePermissionsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.privilege_assignments:
body["privilege_assignments"] = [v.as_dict() for v in self.privilege_assignments]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetSharePermissionsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.privilege_assignments:
body["privilege_assignments"] = self.privilege_assignments
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetSharePermissionsResponse:
"""Deserializes the GetSharePermissionsResponse from a dictionary."""
return cls(
next_page_token=d.get("next_page_token", None),
privilege_assignments=_repeated_dict(d, "privilege_assignments", PrivilegeAssignment),
)
@dataclass
class IpAccessList:
allowed_ip_addresses: Optional[List[str]] = None
"""Allowed IP Addresses in CIDR notation. Limit of 100."""
def as_dict(self) -> dict:
"""Serializes the IpAccessList into a dictionary suitable for use as a JSON request body."""
body = {}
if self.allowed_ip_addresses:
body["allowed_ip_addresses"] = [v for v in self.allowed_ip_addresses]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the IpAccessList into a shallow dictionary of its immediate attributes."""
body = {}
if self.allowed_ip_addresses:
body["allowed_ip_addresses"] = self.allowed_ip_addresses
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> IpAccessList:
"""Deserializes the IpAccessList from a dictionary."""
return cls(allowed_ip_addresses=d.get("allowed_ip_addresses", None))
@dataclass
class ListFederationPoliciesResponse:
next_page_token: Optional[str] = None
policies: Optional[List[FederationPolicy]] = None
def as_dict(self) -> dict:
"""Serializes the ListFederationPoliciesResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.policies:
body["policies"] = [v.as_dict() for v in self.policies]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListFederationPoliciesResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.policies:
body["policies"] = self.policies
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListFederationPoliciesResponse:
"""Deserializes the ListFederationPoliciesResponse from a dictionary."""
return cls(
next_page_token=d.get("next_page_token", None), policies=_repeated_dict(d, "policies", FederationPolicy)
)
@dataclass
class ListProviderShareAssetsResponse:
"""Response to ListProviderShareAssets, which contains the list of assets of a share."""
functions: Optional[List[DeltaSharingFunction]] = None
"""The list of functions in the share."""
notebooks: Optional[List[NotebookFile]] = None
"""The list of notebooks in the share."""
share: Optional[Share] = None
"""The metadata of the share."""
tables: Optional[List[Table]] = None
"""The list of tables in the share."""
volumes: Optional[List[Volume]] = None
"""The list of volumes in the share."""
def as_dict(self) -> dict:
"""Serializes the ListProviderShareAssetsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.functions:
body["functions"] = [v.as_dict() for v in self.functions]
if self.notebooks:
body["notebooks"] = [v.as_dict() for v in self.notebooks]
if self.share:
body["share"] = self.share.as_dict()
if self.tables:
body["tables"] = [v.as_dict() for v in self.tables]
if self.volumes:
body["volumes"] = [v.as_dict() for v in self.volumes]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListProviderShareAssetsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.functions:
body["functions"] = self.functions
if self.notebooks:
body["notebooks"] = self.notebooks
if self.share:
body["share"] = self.share
if self.tables:
body["tables"] = self.tables
if self.volumes:
body["volumes"] = self.volumes
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListProviderShareAssetsResponse:
"""Deserializes the ListProviderShareAssetsResponse from a dictionary."""
return cls(
functions=_repeated_dict(d, "functions", DeltaSharingFunction),
notebooks=_repeated_dict(d, "notebooks", NotebookFile),
share=_from_dict(d, "share", Share),
tables=_repeated_dict(d, "tables", Table),
volumes=_repeated_dict(d, "volumes", Volume),
)
@dataclass
class ListProviderSharesResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
shares: Optional[List[ProviderShare]] = None
"""An array of provider shares."""
def as_dict(self) -> dict:
"""Serializes the ListProviderSharesResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.shares:
body["shares"] = [v.as_dict() for v in self.shares]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListProviderSharesResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.shares:
body["shares"] = self.shares
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListProviderSharesResponse:
"""Deserializes the ListProviderSharesResponse from a dictionary."""
return cls(next_page_token=d.get("next_page_token", None), shares=_repeated_dict(d, "shares", ProviderShare))
@dataclass
class ListProvidersResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
providers: Optional[List[ProviderInfo]] = None
"""An array of provider information objects."""
def as_dict(self) -> dict:
"""Serializes the ListProvidersResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.providers:
body["providers"] = [v.as_dict() for v in self.providers]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListProvidersResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.providers:
body["providers"] = self.providers
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListProvidersResponse:
"""Deserializes the ListProvidersResponse from a dictionary."""
return cls(
next_page_token=d.get("next_page_token", None), providers=_repeated_dict(d, "providers", ProviderInfo)
)
@dataclass
class ListRecipientsResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
recipients: Optional[List[RecipientInfo]] = None
"""An array of recipient information objects."""
def as_dict(self) -> dict:
"""Serializes the ListRecipientsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.recipients:
body["recipients"] = [v.as_dict() for v in self.recipients]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListRecipientsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.recipients:
body["recipients"] = self.recipients
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListRecipientsResponse:
"""Deserializes the ListRecipientsResponse from a dictionary."""
return cls(
next_page_token=d.get("next_page_token", None), recipients=_repeated_dict(d, "recipients", RecipientInfo)
)
@dataclass
class ListSharesResponse:
next_page_token: Optional[str] = None
"""Opaque token to retrieve the next page of results. Absent if there are no more pages.
__page_token__ should be set to this value for the next request (for the next page of results)."""
shares: Optional[List[ShareInfo]] = None
"""An array of data share information objects."""
def as_dict(self) -> dict:
"""Serializes the ListSharesResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.shares:
body["shares"] = [v.as_dict() for v in self.shares]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListSharesResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.next_page_token is not None:
body["next_page_token"] = self.next_page_token
if self.shares:
body["shares"] = self.shares
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListSharesResponse:
"""Deserializes the ListSharesResponse from a dictionary."""
return cls(next_page_token=d.get("next_page_token", None), shares=_repeated_dict(d, "shares", ShareInfo))
@dataclass
class NotebookFile:
comment: Optional[str] = None
"""The comment of the notebook file."""
id: Optional[str] = None
"""The id of the notebook file."""
name: Optional[str] = None
"""Name of the notebook file."""
share: Optional[str] = None
"""The name of the share that the notebook file belongs to."""
share_id: Optional[str] = None
"""The id of the share that the notebook file belongs to."""
tags: Optional[List[catalog.TagKeyValue]] = None
"""The tags of the notebook file."""
def as_dict(self) -> dict:
"""Serializes the NotebookFile into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = [v.as_dict() for v in self.tags]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the NotebookFile into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = self.tags
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> NotebookFile:
"""Deserializes the NotebookFile from a dictionary."""
return cls(
comment=d.get("comment", None),
id=d.get("id", None),
name=d.get("name", None),
share=d.get("share", None),
share_id=d.get("share_id", None),
tags=_repeated_dict(d, "tags", catalog.TagKeyValue),
)
@dataclass
class OidcFederationPolicy:
"""Specifies the policy to use for validating OIDC claims in your federated tokens from Delta
Sharing Clients. Refer to https://docs.databricks.com/en/delta-sharing/create-recipient-oidc-fed
for more details."""
issuer: str
"""The required token issuer, as specified in the 'iss' claim of federated tokens."""
subject_claim: str
"""The claim that contains the subject of the token. Depending on the identity provider and the use
case (U2M or M2M), this can vary: - For Entra ID (AAD): * U2M flow (group access): Use `groups`.
* U2M flow (user access): Use `oid`. * M2M flow (OAuth App access): Use `azp`. - For other IdPs,
refer to the specific IdP documentation.
Supported `subject_claim` values are: - `oid`: Object ID of the user. - `azp`: Client ID of the
OAuth app. - `groups`: Object ID of the group. - `sub`: Subject identifier for other use cases."""
subject: str
"""The required token subject, as specified in the subject claim of federated tokens. The subject
claim identifies the identity of the user or machine accessing the resource. Examples for Entra
ID (AAD): - U2M flow (group access): If the subject claim is `groups`, this must be the Object
ID of the group in Entra ID. - U2M flow (user access): If the subject claim is `oid`, this must
be the Object ID of the user in Entra ID. - M2M flow (OAuth App access): If the subject claim is
`azp`, this must be the client ID of the OAuth app registered in Entra ID."""
audiences: Optional[List[str]] = None
"""The allowed token audiences, as specified in the 'aud' claim of federated tokens. The audience
identifier is intended to represent the recipient of the token. Can be any non-empty string
value. As long as the audience in the token matches at least one audience in the policy,"""
def as_dict(self) -> dict:
"""Serializes the OidcFederationPolicy into a dictionary suitable for use as a JSON request body."""
body = {}
if self.audiences:
body["audiences"] = [v for v in self.audiences]
if self.issuer is not None:
body["issuer"] = self.issuer
if self.subject is not None:
body["subject"] = self.subject
if self.subject_claim is not None:
body["subject_claim"] = self.subject_claim
return body
def as_shallow_dict(self) -> dict:
"""Serializes the OidcFederationPolicy into a shallow dictionary of its immediate attributes."""
body = {}
if self.audiences:
body["audiences"] = self.audiences
if self.issuer is not None:
body["issuer"] = self.issuer
if self.subject is not None:
body["subject"] = self.subject
if self.subject_claim is not None:
body["subject_claim"] = self.subject_claim
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> OidcFederationPolicy:
"""Deserializes the OidcFederationPolicy from a dictionary."""
return cls(
audiences=d.get("audiences", None),
issuer=d.get("issuer", None),
subject=d.get("subject", None),
subject_claim=d.get("subject_claim", None),
)
@dataclass
class Partition:
values: Optional[List[PartitionValue]] = None
"""An array of partition values."""
def as_dict(self) -> dict:
"""Serializes the Partition into a dictionary suitable for use as a JSON request body."""
body = {}
if self.values:
body["values"] = [v.as_dict() for v in self.values]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Partition into a shallow dictionary of its immediate attributes."""
body = {}
if self.values:
body["values"] = self.values
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Partition:
"""Deserializes the Partition from a dictionary."""
return cls(values=_repeated_dict(d, "values", PartitionValue))
@dataclass
class PartitionValue:
name: Optional[str] = None
"""The name of the partition column."""
op: Optional[PartitionValueOp] = None
"""The operator to apply for the value."""
recipient_property_key: Optional[str] = None
"""The key of a Delta Sharing recipient's property. For example "databricks-account-id". When this
field is set, field `value` can not be set."""
value: Optional[str] = None
"""The value of the partition column. When this value is not set, it means `null` value. When this
field is set, field `recipient_property_key` can not be set."""
def as_dict(self) -> dict:
"""Serializes the PartitionValue into a dictionary suitable for use as a JSON request body."""
body = {}
if self.name is not None:
body["name"] = self.name
if self.op is not None:
body["op"] = self.op.value
if self.recipient_property_key is not None:
body["recipient_property_key"] = self.recipient_property_key
if self.value is not None:
body["value"] = self.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PartitionValue into a shallow dictionary of its immediate attributes."""
body = {}
if self.name is not None:
body["name"] = self.name
if self.op is not None:
body["op"] = self.op
if self.recipient_property_key is not None:
body["recipient_property_key"] = self.recipient_property_key
if self.value is not None:
body["value"] = self.value
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PartitionValue:
"""Deserializes the PartitionValue from a dictionary."""
return cls(
name=d.get("name", None),
op=_enum(d, "op", PartitionValueOp),
recipient_property_key=d.get("recipient_property_key", None),
value=d.get("value", None),
)
class PartitionValueOp(Enum):
EQUAL = "EQUAL"
LIKE = "LIKE"
@dataclass
class PermissionsChange:
add: Optional[List[str]] = None
"""The set of privileges to add."""
principal: Optional[str] = None
"""The principal whose privileges we are changing. Only one of principal or principal_id should be
specified, never both at the same time."""
remove: Optional[List[str]] = None
"""The set of privileges to remove."""
def as_dict(self) -> dict:
"""Serializes the PermissionsChange into a dictionary suitable for use as a JSON request body."""
body = {}
if self.add:
body["add"] = [v for v in self.add]
if self.principal is not None:
body["principal"] = self.principal
if self.remove:
body["remove"] = [v for v in self.remove]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PermissionsChange into a shallow dictionary of its immediate attributes."""
body = {}
if self.add:
body["add"] = self.add
if self.principal is not None:
body["principal"] = self.principal
if self.remove:
body["remove"] = self.remove
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PermissionsChange:
"""Deserializes the PermissionsChange from a dictionary."""
return cls(add=d.get("add", None), principal=d.get("principal", None), remove=d.get("remove", None))
class Privilege(Enum):
ACCESS = "ACCESS"
ALL_PRIVILEGES = "ALL_PRIVILEGES"
APPLY_TAG = "APPLY_TAG"
CREATE = "CREATE"
CREATE_CATALOG = "CREATE_CATALOG"
CREATE_CONNECTION = "CREATE_CONNECTION"
CREATE_EXTERNAL_LOCATION = "CREATE_EXTERNAL_LOCATION"
CREATE_EXTERNAL_TABLE = "CREATE_EXTERNAL_TABLE"
CREATE_EXTERNAL_VOLUME = "CREATE_EXTERNAL_VOLUME"
CREATE_FOREIGN_CATALOG = "CREATE_FOREIGN_CATALOG"
CREATE_FOREIGN_SECURABLE = "CREATE_FOREIGN_SECURABLE"
CREATE_FUNCTION = "CREATE_FUNCTION"
CREATE_MANAGED_STORAGE = "CREATE_MANAGED_STORAGE"
CREATE_MATERIALIZED_VIEW = "CREATE_MATERIALIZED_VIEW"
CREATE_MODEL = "CREATE_MODEL"
CREATE_PROVIDER = "CREATE_PROVIDER"
CREATE_RECIPIENT = "CREATE_RECIPIENT"
CREATE_SCHEMA = "CREATE_SCHEMA"
CREATE_SERVICE_CREDENTIAL = "CREATE_SERVICE_CREDENTIAL"
CREATE_SHARE = "CREATE_SHARE"
CREATE_STORAGE_CREDENTIAL = "CREATE_STORAGE_CREDENTIAL"
CREATE_TABLE = "CREATE_TABLE"
CREATE_VIEW = "CREATE_VIEW"
CREATE_VOLUME = "CREATE_VOLUME"
EXECUTE = "EXECUTE"
MANAGE = "MANAGE"
MANAGE_ALLOWLIST = "MANAGE_ALLOWLIST"
MODIFY = "MODIFY"
READ_FILES = "READ_FILES"
READ_PRIVATE_FILES = "READ_PRIVATE_FILES"
READ_VOLUME = "READ_VOLUME"
REFRESH = "REFRESH"
SELECT = "SELECT"
SET_SHARE_PERMISSION = "SET_SHARE_PERMISSION"
USAGE = "USAGE"
USE_CATALOG = "USE_CATALOG"
USE_CONNECTION = "USE_CONNECTION"
USE_MARKETPLACE_ASSETS = "USE_MARKETPLACE_ASSETS"
USE_PROVIDER = "USE_PROVIDER"
USE_RECIPIENT = "USE_RECIPIENT"
USE_SCHEMA = "USE_SCHEMA"
USE_SHARE = "USE_SHARE"
WRITE_FILES = "WRITE_FILES"
WRITE_PRIVATE_FILES = "WRITE_PRIVATE_FILES"
WRITE_VOLUME = "WRITE_VOLUME"
@dataclass
class PrivilegeAssignment:
principal: Optional[str] = None
"""The principal (user email address or group name). For deleted principals, `principal` is empty
while `principal_id` is populated."""
privileges: Optional[List[Privilege]] = None
"""The privileges assigned to the principal."""
def as_dict(self) -> dict:
"""Serializes the PrivilegeAssignment into a dictionary suitable for use as a JSON request body."""
body = {}
if self.principal is not None:
body["principal"] = self.principal
if self.privileges:
body["privileges"] = [v.value for v in self.privileges]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PrivilegeAssignment into a shallow dictionary of its immediate attributes."""
body = {}
if self.principal is not None:
body["principal"] = self.principal
if self.privileges:
body["privileges"] = self.privileges
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PrivilegeAssignment:
"""Deserializes the PrivilegeAssignment from a dictionary."""
return cls(principal=d.get("principal", None), privileges=_repeated_enum(d, "privileges", Privilege))
@dataclass
class ProviderInfo:
authentication_type: Optional[AuthenticationType] = None
cloud: Optional[str] = None
"""Cloud vendor of the provider's UC metastore. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
comment: Optional[str] = None
"""Description about the provider."""
created_at: Optional[int] = None
"""Time at which this Provider was created, in epoch milliseconds."""
created_by: Optional[str] = None
"""Username of Provider creator."""
data_provider_global_metastore_id: Optional[str] = None
"""The global UC metastore id of the data provider. This field is only present when the
__authentication_type__ is **DATABRICKS**. The identifier is of format
__cloud__:__region__:__metastore-uuid__."""
metastore_id: Optional[str] = None
"""UUID of the provider's UC metastore. This field is only present when the __authentication_type__
is **DATABRICKS**."""
name: Optional[str] = None
"""The name of the Provider."""
owner: Optional[str] = None
"""Username of Provider owner."""
recipient_profile: Optional[RecipientProfile] = None
"""The recipient profile. This field is only present when the authentication_type is `TOKEN` or
`OAUTH_CLIENT_CREDENTIALS`."""
recipient_profile_str: Optional[str] = None
"""This field is required when the __authentication_type__ is **TOKEN**,
**OAUTH_CLIENT_CREDENTIALS** or not provided."""
region: Optional[str] = None
"""Cloud region of the provider's UC metastore. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
updated_at: Optional[int] = None
"""Time at which this Provider was created, in epoch milliseconds."""
updated_by: Optional[str] = None
"""Username of user who last modified Provider."""
def as_dict(self) -> dict:
"""Serializes the ProviderInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.authentication_type is not None:
body["authentication_type"] = self.authentication_type.value
if self.cloud is not None:
body["cloud"] = self.cloud
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.data_provider_global_metastore_id is not None:
body["data_provider_global_metastore_id"] = self.data_provider_global_metastore_id
if self.metastore_id is not None:
body["metastore_id"] = self.metastore_id
if self.name is not None:
body["name"] = self.name
if self.owner is not None:
body["owner"] = self.owner
if self.recipient_profile:
body["recipient_profile"] = self.recipient_profile.as_dict()
if self.recipient_profile_str is not None:
body["recipient_profile_str"] = self.recipient_profile_str
if self.region is not None:
body["region"] = self.region
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ProviderInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.authentication_type is not None:
body["authentication_type"] = self.authentication_type
if self.cloud is not None:
body["cloud"] = self.cloud
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.data_provider_global_metastore_id is not None:
body["data_provider_global_metastore_id"] = self.data_provider_global_metastore_id
if self.metastore_id is not None:
body["metastore_id"] = self.metastore_id
if self.name is not None:
body["name"] = self.name
if self.owner is not None:
body["owner"] = self.owner
if self.recipient_profile:
body["recipient_profile"] = self.recipient_profile
if self.recipient_profile_str is not None:
body["recipient_profile_str"] = self.recipient_profile_str
if self.region is not None:
body["region"] = self.region
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ProviderInfo:
"""Deserializes the ProviderInfo from a dictionary."""
return cls(
authentication_type=_enum(d, "authentication_type", AuthenticationType),
cloud=d.get("cloud", None),
comment=d.get("comment", None),
created_at=d.get("created_at", None),
created_by=d.get("created_by", None),
data_provider_global_metastore_id=d.get("data_provider_global_metastore_id", None),
metastore_id=d.get("metastore_id", None),
name=d.get("name", None),
owner=d.get("owner", None),
recipient_profile=_from_dict(d, "recipient_profile", RecipientProfile),
recipient_profile_str=d.get("recipient_profile_str", None),
region=d.get("region", None),
updated_at=d.get("updated_at", None),
updated_by=d.get("updated_by", None),
)
@dataclass
class ProviderShare:
name: Optional[str] = None
"""The name of the Provider Share."""
def as_dict(self) -> dict:
"""Serializes the ProviderShare into a dictionary suitable for use as a JSON request body."""
body = {}
if self.name is not None:
body["name"] = self.name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ProviderShare into a shallow dictionary of its immediate attributes."""
body = {}
if self.name is not None:
body["name"] = self.name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ProviderShare:
"""Deserializes the ProviderShare from a dictionary."""
return cls(name=d.get("name", None))
@dataclass
class RecipientInfo:
activated: Optional[bool] = None
"""A boolean status field showing whether the Recipient's activation URL has been exercised or not."""
activation_url: Optional[str] = None
"""Full activation url to retrieve the access token. It will be empty if the token is already
retrieved."""
authentication_type: Optional[AuthenticationType] = None
cloud: Optional[str] = None
"""Cloud vendor of the recipient's Unity Catalog Metastore. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
comment: Optional[str] = None
"""Description about the recipient."""
created_at: Optional[int] = None
"""Time at which this recipient was created, in epoch milliseconds."""
created_by: Optional[str] = None
"""Username of recipient creator."""
data_recipient_global_metastore_id: Optional[str] = None
"""The global Unity Catalog metastore id provided by the data recipient. This field is only present
when the __authentication_type__ is **DATABRICKS**. The identifier is of format
__cloud__:__region__:__metastore-uuid__."""
expiration_time: Optional[int] = None
"""Expiration timestamp of the token, in epoch milliseconds."""
id: Optional[str] = None
"""[Create,Update:IGN] common - id of the recipient"""
ip_access_list: Optional[IpAccessList] = None
"""IP Access List"""
metastore_id: Optional[str] = None
"""Unique identifier of recipient's Unity Catalog Metastore. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
name: Optional[str] = None
"""Name of Recipient."""
owner: Optional[str] = None
"""Username of the recipient owner."""
properties_kvpairs: Optional[SecurablePropertiesKvPairs] = None
"""Recipient properties as map of string key-value pairs. When provided in update request, the
specified properties will override the existing properties. To add and remove properties, one
would need to perform a read-modify-write."""
region: Optional[str] = None
"""Cloud region of the recipient's Unity Catalog Metastore. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
sharing_code: Optional[str] = None
"""The one-time sharing code provided by the data recipient. This field is only present when the
__authentication_type__ is **DATABRICKS**."""
tokens: Optional[List[RecipientTokenInfo]] = None
"""This field is only present when the __authentication_type__ is **TOKEN**."""
updated_at: Optional[int] = None
"""Time at which the recipient was updated, in epoch milliseconds."""
updated_by: Optional[str] = None
"""Username of recipient updater."""
def as_dict(self) -> dict:
"""Serializes the RecipientInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.activated is not None:
body["activated"] = self.activated
if self.activation_url is not None:
body["activation_url"] = self.activation_url
if self.authentication_type is not None:
body["authentication_type"] = self.authentication_type.value
if self.cloud is not None:
body["cloud"] = self.cloud
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.data_recipient_global_metastore_id is not None:
body["data_recipient_global_metastore_id"] = self.data_recipient_global_metastore_id
if self.expiration_time is not None:
body["expiration_time"] = self.expiration_time
if self.id is not None:
body["id"] = self.id
if self.ip_access_list:
body["ip_access_list"] = self.ip_access_list.as_dict()
if self.metastore_id is not None:
body["metastore_id"] = self.metastore_id
if self.name is not None:
body["name"] = self.name
if self.owner is not None:
body["owner"] = self.owner
if self.properties_kvpairs:
body["properties_kvpairs"] = self.properties_kvpairs.as_dict()
if self.region is not None:
body["region"] = self.region
if self.sharing_code is not None:
body["sharing_code"] = self.sharing_code
if self.tokens:
body["tokens"] = [v.as_dict() for v in self.tokens]
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RecipientInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.activated is not None:
body["activated"] = self.activated
if self.activation_url is not None:
body["activation_url"] = self.activation_url
if self.authentication_type is not None:
body["authentication_type"] = self.authentication_type
if self.cloud is not None:
body["cloud"] = self.cloud
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.data_recipient_global_metastore_id is not None:
body["data_recipient_global_metastore_id"] = self.data_recipient_global_metastore_id
if self.expiration_time is not None:
body["expiration_time"] = self.expiration_time
if self.id is not None:
body["id"] = self.id
if self.ip_access_list:
body["ip_access_list"] = self.ip_access_list
if self.metastore_id is not None:
body["metastore_id"] = self.metastore_id
if self.name is not None:
body["name"] = self.name
if self.owner is not None:
body["owner"] = self.owner
if self.properties_kvpairs:
body["properties_kvpairs"] = self.properties_kvpairs
if self.region is not None:
body["region"] = self.region
if self.sharing_code is not None:
body["sharing_code"] = self.sharing_code
if self.tokens:
body["tokens"] = self.tokens
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RecipientInfo:
"""Deserializes the RecipientInfo from a dictionary."""
return cls(
activated=d.get("activated", None),
activation_url=d.get("activation_url", None),
authentication_type=_enum(d, "authentication_type", AuthenticationType),
cloud=d.get("cloud", None),
comment=d.get("comment", None),
created_at=d.get("created_at", None),
created_by=d.get("created_by", None),
data_recipient_global_metastore_id=d.get("data_recipient_global_metastore_id", None),
expiration_time=d.get("expiration_time", None),
id=d.get("id", None),
ip_access_list=_from_dict(d, "ip_access_list", IpAccessList),
metastore_id=d.get("metastore_id", None),
name=d.get("name", None),
owner=d.get("owner", None),
properties_kvpairs=_from_dict(d, "properties_kvpairs", SecurablePropertiesKvPairs),
region=d.get("region", None),
sharing_code=d.get("sharing_code", None),
tokens=_repeated_dict(d, "tokens", RecipientTokenInfo),
updated_at=d.get("updated_at", None),
updated_by=d.get("updated_by", None),
)
@dataclass
class RecipientProfile:
bearer_token: Optional[str] = None
"""The token used to authorize the recipient."""
endpoint: Optional[str] = None
"""The endpoint for the share to be used by the recipient."""
share_credentials_version: Optional[int] = None
"""The version number of the recipient's credentials on a share."""
def as_dict(self) -> dict:
"""Serializes the RecipientProfile into a dictionary suitable for use as a JSON request body."""
body = {}
if self.bearer_token is not None:
body["bearer_token"] = self.bearer_token
if self.endpoint is not None:
body["endpoint"] = self.endpoint
if self.share_credentials_version is not None:
body["share_credentials_version"] = self.share_credentials_version
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RecipientProfile into a shallow dictionary of its immediate attributes."""
body = {}
if self.bearer_token is not None:
body["bearer_token"] = self.bearer_token
if self.endpoint is not None:
body["endpoint"] = self.endpoint
if self.share_credentials_version is not None:
body["share_credentials_version"] = self.share_credentials_version
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RecipientProfile:
"""Deserializes the RecipientProfile from a dictionary."""
return cls(
bearer_token=d.get("bearer_token", None),
endpoint=d.get("endpoint", None),
share_credentials_version=d.get("share_credentials_version", None),
)
@dataclass
class RecipientTokenInfo:
activation_url: Optional[str] = None
"""Full activation URL to retrieve the access token. It will be empty if the token is already
retrieved."""
created_at: Optional[int] = None
"""Time at which this recipient token was created, in epoch milliseconds."""
created_by: Optional[str] = None
"""Username of recipient token creator."""
expiration_time: Optional[int] = None
"""Expiration timestamp of the token in epoch milliseconds."""
id: Optional[str] = None
"""Unique ID of the recipient token."""
updated_at: Optional[int] = None
"""Time at which this recipient token was updated, in epoch milliseconds."""
updated_by: Optional[str] = None
"""Username of recipient token updater."""
def as_dict(self) -> dict:
"""Serializes the RecipientTokenInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.activation_url is not None:
body["activation_url"] = self.activation_url
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.expiration_time is not None:
body["expiration_time"] = self.expiration_time
if self.id is not None:
body["id"] = self.id
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RecipientTokenInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.activation_url is not None:
body["activation_url"] = self.activation_url
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.expiration_time is not None:
body["expiration_time"] = self.expiration_time
if self.id is not None:
body["id"] = self.id
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RecipientTokenInfo:
"""Deserializes the RecipientTokenInfo from a dictionary."""
return cls(
activation_url=d.get("activation_url", None),
created_at=d.get("created_at", None),
created_by=d.get("created_by", None),
expiration_time=d.get("expiration_time", None),
id=d.get("id", None),
updated_at=d.get("updated_at", None),
updated_by=d.get("updated_by", None),
)
@dataclass
class RegisteredModelAlias:
alias_name: Optional[str] = None
"""Name of the alias."""
version_num: Optional[int] = None
"""Numeric model version that alias will reference."""
def as_dict(self) -> dict:
"""Serializes the RegisteredModelAlias into a dictionary suitable for use as a JSON request body."""
body = {}
if self.alias_name is not None:
body["alias_name"] = self.alias_name
if self.version_num is not None:
body["version_num"] = self.version_num
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RegisteredModelAlias into a shallow dictionary of its immediate attributes."""
body = {}
if self.alias_name is not None:
body["alias_name"] = self.alias_name
if self.version_num is not None:
body["version_num"] = self.version_num
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RegisteredModelAlias:
"""Deserializes the RegisteredModelAlias from a dictionary."""
return cls(alias_name=d.get("alias_name", None), version_num=d.get("version_num", None))
@dataclass
class RetrieveTokenResponse:
bearer_token: Optional[str] = None
"""The token used to authorize the recipient."""
endpoint: Optional[str] = None
"""The endpoint for the share to be used by the recipient."""
expiration_time: Optional[str] = None
"""Expiration timestamp of the token in epoch milliseconds."""
share_credentials_version: Optional[int] = None
"""These field names must follow the delta sharing protocol."""
def as_dict(self) -> dict:
"""Serializes the RetrieveTokenResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.bearer_token is not None:
body["bearerToken"] = self.bearer_token
if self.endpoint is not None:
body["endpoint"] = self.endpoint
if self.expiration_time is not None:
body["expirationTime"] = self.expiration_time
if self.share_credentials_version is not None:
body["shareCredentialsVersion"] = self.share_credentials_version
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RetrieveTokenResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.bearer_token is not None:
body["bearerToken"] = self.bearer_token
if self.endpoint is not None:
body["endpoint"] = self.endpoint
if self.expiration_time is not None:
body["expirationTime"] = self.expiration_time
if self.share_credentials_version is not None:
body["shareCredentialsVersion"] = self.share_credentials_version
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RetrieveTokenResponse:
"""Deserializes the RetrieveTokenResponse from a dictionary."""
return cls(
bearer_token=d.get("bearerToken", None),
endpoint=d.get("endpoint", None),
expiration_time=d.get("expirationTime", None),
share_credentials_version=d.get("shareCredentialsVersion", None),
)
@dataclass
class SecurablePropertiesKvPairs:
"""An object with __properties__ containing map of key-value properties attached to the securable."""
properties: Dict[str, str]
"""A map of key-value properties attached to the securable."""
def as_dict(self) -> dict:
"""Serializes the SecurablePropertiesKvPairs into a dictionary suitable for use as a JSON request body."""
body = {}
if self.properties:
body["properties"] = self.properties
return body
def as_shallow_dict(self) -> dict:
"""Serializes the SecurablePropertiesKvPairs into a shallow dictionary of its immediate attributes."""
body = {}
if self.properties:
body["properties"] = self.properties
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> SecurablePropertiesKvPairs:
"""Deserializes the SecurablePropertiesKvPairs from a dictionary."""
return cls(properties=d.get("properties", None))
@dataclass
class Share:
id: Optional[str] = None
name: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the Share into a dictionary suitable for use as a JSON request body."""
body = {}
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Share into a shallow dictionary of its immediate attributes."""
body = {}
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Share:
"""Deserializes the Share from a dictionary."""
return cls(id=d.get("id", None), name=d.get("name", None))
@dataclass
class ShareInfo:
comment: Optional[str] = None
"""User-provided free-form text description."""
created_at: Optional[int] = None
"""Time at which this share was created, in epoch milliseconds."""
created_by: Optional[str] = None
"""Username of share creator."""
name: Optional[str] = None
"""Name of the share."""
objects: Optional[List[SharedDataObject]] = None
"""A list of shared data objects within the share."""
owner: Optional[str] = None
"""Username of current owner of share."""
storage_location: Optional[str] = None
"""Storage Location URL (full path) for the share."""
storage_root: Optional[str] = None
"""Storage root URL for the share."""
updated_at: Optional[int] = None
"""Time at which this share was updated, in epoch milliseconds."""
updated_by: Optional[str] = None
"""Username of share updater."""
def as_dict(self) -> dict:
"""Serializes the ShareInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.name is not None:
body["name"] = self.name
if self.objects:
body["objects"] = [v.as_dict() for v in self.objects]
if self.owner is not None:
body["owner"] = self.owner
if self.storage_location is not None:
body["storage_location"] = self.storage_location
if self.storage_root is not None:
body["storage_root"] = self.storage_root
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ShareInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.created_at is not None:
body["created_at"] = self.created_at
if self.created_by is not None:
body["created_by"] = self.created_by
if self.name is not None:
body["name"] = self.name
if self.objects:
body["objects"] = self.objects
if self.owner is not None:
body["owner"] = self.owner
if self.storage_location is not None:
body["storage_location"] = self.storage_location
if self.storage_root is not None:
body["storage_root"] = self.storage_root
if self.updated_at is not None:
body["updated_at"] = self.updated_at
if self.updated_by is not None:
body["updated_by"] = self.updated_by
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ShareInfo:
"""Deserializes the ShareInfo from a dictionary."""
return cls(
comment=d.get("comment", None),
created_at=d.get("created_at", None),
created_by=d.get("created_by", None),
name=d.get("name", None),
objects=_repeated_dict(d, "objects", SharedDataObject),
owner=d.get("owner", None),
storage_location=d.get("storage_location", None),
storage_root=d.get("storage_root", None),
updated_at=d.get("updated_at", None),
updated_by=d.get("updated_by", None),
)
@dataclass
class ShareToPrivilegeAssignment:
privilege_assignments: Optional[List[PrivilegeAssignment]] = None
"""The privileges assigned to the principal."""
share_name: Optional[str] = None
"""The share name."""
def as_dict(self) -> dict:
"""Serializes the ShareToPrivilegeAssignment into a dictionary suitable for use as a JSON request body."""
body = {}
if self.privilege_assignments:
body["privilege_assignments"] = [v.as_dict() for v in self.privilege_assignments]
if self.share_name is not None:
body["share_name"] = self.share_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ShareToPrivilegeAssignment into a shallow dictionary of its immediate attributes."""
body = {}
if self.privilege_assignments:
body["privilege_assignments"] = self.privilege_assignments
if self.share_name is not None:
body["share_name"] = self.share_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ShareToPrivilegeAssignment:
"""Deserializes the ShareToPrivilegeAssignment from a dictionary."""
return cls(
privilege_assignments=_repeated_dict(d, "privilege_assignments", PrivilegeAssignment),
share_name=d.get("share_name", None),
)
@dataclass
class SharedDataObject:
name: str
"""A fully qualified name that uniquely identifies a data object. For example, a table's fully
qualified name is in the format of `<catalog>.<schema>.<table>`,"""
added_at: Optional[int] = None
"""The time when this data object is added to the share, in epoch milliseconds."""
added_by: Optional[str] = None
"""Username of the sharer."""
cdf_enabled: Optional[bool] = None
"""Whether to enable cdf or indicate if cdf is enabled on the shared object."""
comment: Optional[str] = None
"""A user-provided comment when adding the data object to the share."""
content: Optional[str] = None
"""The content of the notebook file when the data object type is NOTEBOOK_FILE. This should be
base64 encoded. Required for adding a NOTEBOOK_FILE, optional for updating, ignored for other
types."""
data_object_type: Optional[SharedDataObjectDataObjectType] = None
"""The type of the data object."""
history_data_sharing_status: Optional[SharedDataObjectHistoryDataSharingStatus] = None
"""Whether to enable or disable sharing of data history. If not specified, the default is
**DISABLED**."""
partitions: Optional[List[Partition]] = None
"""Array of partitions for the shared data."""
shared_as: Optional[str] = None
"""A user-provided alias name for table-like data objects within the share.
Use this field for table-like objects (for example: TABLE, VIEW, MATERIALIZED_VIEW,
STREAMING_TABLE, FOREIGN_TABLE). For non-table objects (for example: VOLUME, MODEL,
NOTEBOOK_FILE, FUNCTION), use `string_shared_as` instead.
Important: For non-table objects, this field must be omitted entirely.
Format: Must be a 2-part name `<schema_name>.<table_name>` (e.g., "sales_schema.orders_table") -
Both schema and table names must contain only alphanumeric characters and underscores - No
periods, spaces, forward slashes, or control characters are allowed within each part - Do not
include the catalog name (use 2 parts, not 3)
Behavior: - If not provided, the service automatically generates the alias as `<schema>.<table>`
from the object's original name - If you don't want to specify this field, omit it entirely from
the request (do not pass an empty string) - The `shared_as` name must be unique within the share
Examples: - Valid: "analytics_schema.customer_view" - Invalid:
"catalog.analytics_schema.customer_view" (3 parts not allowed) - Invalid:
"analytics-schema.customer-view" (hyphens not allowed)"""
start_version: Optional[int] = None
"""The start version associated with the object. This allows data providers to control the lowest
object version that is accessible by clients. If specified, clients can query snapshots or
changes for versions >= start_version. If not specified, clients can only query starting from
the version of the object at the time it was added to the share.
NOTE: The start_version should be <= the `current` version of the object."""
status: Optional[SharedDataObjectStatus] = None
"""One of: **ACTIVE**, **PERMISSION_DENIED**."""
string_shared_as: Optional[str] = None
"""A user-provided alias name for non-table data objects within the share.
Use this field for non-table objects (for example: VOLUME, MODEL, NOTEBOOK_FILE, FUNCTION). For
table-like objects (for example: TABLE, VIEW, MATERIALIZED_VIEW, STREAMING_TABLE,
FOREIGN_TABLE), use `shared_as` instead.
Important: For table-like objects, this field must be omitted entirely.
Format: - For VOLUME: Must be a 2-part name `<schema_name>.<volume_name>` (e.g.,
"data_schema.ml_models") - For FUNCTION: Must be a 2-part name `<schema_name>.<function_name>`
(e.g., "udf_schema.calculate_tax") - For MODEL: Must be a 2-part name
`<schema_name>.<model_name>` (e.g., "models.prediction_model") - For NOTEBOOK_FILE: Should be
the notebook file name (e.g., "analysis_notebook.py") - All names must contain only alphanumeric
characters and underscores - No periods, spaces, forward slashes, or control characters are
allowed within each part
Behavior: - If not provided, the service automatically generates the alias from the object's
original name - If you don't want to specify this field, omit it entirely from the request (do
not pass an empty string) - The `string_shared_as` name must be unique for objects of the same
type within the share
Examples: - Valid for VOLUME: "data_schema.training_data" - Valid for FUNCTION:
"analytics.calculate_revenue" - Invalid: "catalog.data_schema.training_data" (3 parts not
allowed for volumes) - Invalid: "data-schema.training-data" (hyphens not allowed)"""
def as_dict(self) -> dict:
"""Serializes the SharedDataObject into a dictionary suitable for use as a JSON request body."""
body = {}
if self.added_at is not None:
body["added_at"] = self.added_at
if self.added_by is not None:
body["added_by"] = self.added_by
if self.cdf_enabled is not None:
body["cdf_enabled"] = self.cdf_enabled
if self.comment is not None:
body["comment"] = self.comment
if self.content is not None:
body["content"] = self.content
if self.data_object_type is not None:
body["data_object_type"] = self.data_object_type.value
if self.history_data_sharing_status is not None:
body["history_data_sharing_status"] = self.history_data_sharing_status.value
if self.name is not None:
body["name"] = self.name
if self.partitions:
body["partitions"] = [v.as_dict() for v in self.partitions]
if self.shared_as is not None:
body["shared_as"] = self.shared_as
if self.start_version is not None:
body["start_version"] = self.start_version
if self.status is not None:
body["status"] = self.status.value
if self.string_shared_as is not None:
body["string_shared_as"] = self.string_shared_as
return body
def as_shallow_dict(self) -> dict:
"""Serializes the SharedDataObject into a shallow dictionary of its immediate attributes."""
body = {}
if self.added_at is not None:
body["added_at"] = self.added_at
if self.added_by is not None:
body["added_by"] = self.added_by
if self.cdf_enabled is not None:
body["cdf_enabled"] = self.cdf_enabled
if self.comment is not None:
body["comment"] = self.comment
if self.content is not None:
body["content"] = self.content
if self.data_object_type is not None:
body["data_object_type"] = self.data_object_type
if self.history_data_sharing_status is not None:
body["history_data_sharing_status"] = self.history_data_sharing_status
if self.name is not None:
body["name"] = self.name
if self.partitions:
body["partitions"] = self.partitions
if self.shared_as is not None:
body["shared_as"] = self.shared_as
if self.start_version is not None:
body["start_version"] = self.start_version
if self.status is not None:
body["status"] = self.status
if self.string_shared_as is not None:
body["string_shared_as"] = self.string_shared_as
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> SharedDataObject:
"""Deserializes the SharedDataObject from a dictionary."""
return cls(
added_at=d.get("added_at", None),
added_by=d.get("added_by", None),
cdf_enabled=d.get("cdf_enabled", None),
comment=d.get("comment", None),
content=d.get("content", None),
data_object_type=_enum(d, "data_object_type", SharedDataObjectDataObjectType),
history_data_sharing_status=_enum(
d, "history_data_sharing_status", SharedDataObjectHistoryDataSharingStatus
),
name=d.get("name", None),
partitions=_repeated_dict(d, "partitions", Partition),
shared_as=d.get("shared_as", None),
start_version=d.get("start_version", None),
status=_enum(d, "status", SharedDataObjectStatus),
string_shared_as=d.get("string_shared_as", None),
)
class SharedDataObjectDataObjectType(Enum):
FEATURE_SPEC = "FEATURE_SPEC"
FOREIGN_TABLE = "FOREIGN_TABLE"
FUNCTION = "FUNCTION"
MATERIALIZED_VIEW = "MATERIALIZED_VIEW"
MODEL = "MODEL"
NOTEBOOK_FILE = "NOTEBOOK_FILE"
SCHEMA = "SCHEMA"
STREAMING_TABLE = "STREAMING_TABLE"
TABLE = "TABLE"
VIEW = "VIEW"
VOLUME = "VOLUME"
class SharedDataObjectHistoryDataSharingStatus(Enum):
DISABLED = "DISABLED"
ENABLED = "ENABLED"
class SharedDataObjectStatus(Enum):
ACTIVE = "ACTIVE"
PERMISSION_DENIED = "PERMISSION_DENIED"
@dataclass
class SharedDataObjectUpdate:
action: Optional[SharedDataObjectUpdateAction] = None
"""One of: **ADD**, **REMOVE**, **UPDATE**."""
data_object: Optional[SharedDataObject] = None
"""The data object that is being added, removed, or updated. The maximum number update data objects
allowed is a 100."""
def as_dict(self) -> dict:
"""Serializes the SharedDataObjectUpdate into a dictionary suitable for use as a JSON request body."""
body = {}
if self.action is not None:
body["action"] = self.action.value
if self.data_object:
body["data_object"] = self.data_object.as_dict()
return body
def as_shallow_dict(self) -> dict:
"""Serializes the SharedDataObjectUpdate into a shallow dictionary of its immediate attributes."""
body = {}
if self.action is not None:
body["action"] = self.action
if self.data_object:
body["data_object"] = self.data_object
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> SharedDataObjectUpdate:
"""Deserializes the SharedDataObjectUpdate from a dictionary."""
return cls(
action=_enum(d, "action", SharedDataObjectUpdateAction),
data_object=_from_dict(d, "data_object", SharedDataObject),
)
class SharedDataObjectUpdateAction(Enum):
ADD = "ADD"
REMOVE = "REMOVE"
UPDATE = "UPDATE"
class SharedSecurableKind(Enum):
"""The SecurableKind of a delta-shared object."""
FUNCTION_FEATURE_SPEC = "FUNCTION_FEATURE_SPEC"
FUNCTION_REGISTERED_MODEL = "FUNCTION_REGISTERED_MODEL"
FUNCTION_STANDARD = "FUNCTION_STANDARD"
@dataclass
class Table:
comment: Optional[str] = None
"""The comment of the table."""
id: Optional[str] = None
"""The id of the table."""
materialization_namespace: Optional[str] = None
"""The catalog and schema of the materialized table"""
materialized_table_name: Optional[str] = None
"""The name of a materialized table."""
name: Optional[str] = None
"""The name of the table."""
schema: Optional[str] = None
"""The name of the schema that the table belongs to."""
share: Optional[str] = None
"""The name of the share that the table belongs to."""
share_id: Optional[str] = None
"""The id of the share that the table belongs to."""
tags: Optional[List[catalog.TagKeyValue]] = None
"""The Tags of the table."""
def as_dict(self) -> dict:
"""Serializes the Table into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.materialization_namespace is not None:
body["materialization_namespace"] = self.materialization_namespace
if self.materialized_table_name is not None:
body["materialized_table_name"] = self.materialized_table_name
if self.name is not None:
body["name"] = self.name
if self.schema is not None:
body["schema"] = self.schema
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = [v.as_dict() for v in self.tags]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Table into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.materialization_namespace is not None:
body["materialization_namespace"] = self.materialization_namespace
if self.materialized_table_name is not None:
body["materialized_table_name"] = self.materialized_table_name
if self.name is not None:
body["name"] = self.name
if self.schema is not None:
body["schema"] = self.schema
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = self.tags
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Table:
"""Deserializes the Table from a dictionary."""
return cls(
comment=d.get("comment", None),
id=d.get("id", None),
materialization_namespace=d.get("materialization_namespace", None),
materialized_table_name=d.get("materialized_table_name", None),
name=d.get("name", None),
schema=d.get("schema", None),
share=d.get("share", None),
share_id=d.get("share_id", None),
tags=_repeated_dict(d, "tags", catalog.TagKeyValue),
)
@dataclass
class UpdateSharePermissionsResponse:
privilege_assignments: Optional[List[PrivilegeAssignment]] = None
"""The privileges assigned to each principal"""
def as_dict(self) -> dict:
"""Serializes the UpdateSharePermissionsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.privilege_assignments:
body["privilege_assignments"] = [v.as_dict() for v in self.privilege_assignments]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the UpdateSharePermissionsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.privilege_assignments:
body["privilege_assignments"] = self.privilege_assignments
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> UpdateSharePermissionsResponse:
"""Deserializes the UpdateSharePermissionsResponse from a dictionary."""
return cls(privilege_assignments=_repeated_dict(d, "privilege_assignments", PrivilegeAssignment))
@dataclass
class Volume:
comment: Optional[str] = None
"""The comment of the volume."""
id: Optional[str] = None
"""This id maps to the shared_volume_id in database Recipient needs shared_volume_id for recon to
check if this volume is already in recipient's DB or not."""
name: Optional[str] = None
"""The name of the volume."""
schema: Optional[str] = None
"""The name of the schema that the volume belongs to."""
share: Optional[str] = None
"""The name of the share that the volume belongs to."""
share_id: Optional[str] = None
"""/ The id of the share that the volume belongs to."""
tags: Optional[List[catalog.TagKeyValue]] = None
"""The tags of the volume."""
def as_dict(self) -> dict:
"""Serializes the Volume into a dictionary suitable for use as a JSON request body."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.schema is not None:
body["schema"] = self.schema
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = [v.as_dict() for v in self.tags]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Volume into a shallow dictionary of its immediate attributes."""
body = {}
if self.comment is not None:
body["comment"] = self.comment
if self.id is not None:
body["id"] = self.id
if self.name is not None:
body["name"] = self.name
if self.schema is not None:
body["schema"] = self.schema
if self.share is not None:
body["share"] = self.share
if self.share_id is not None:
body["share_id"] = self.share_id
if self.tags:
body["tags"] = self.tags
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Volume:
"""Deserializes the Volume from a dictionary."""
return cls(
comment=d.get("comment", None),
id=d.get("id", None),
name=d.get("name", None),
schema=d.get("schema", None),
share=d.get("share", None),
share_id=d.get("share_id", None),
tags=_repeated_dict(d, "tags", catalog.TagKeyValue),
)
class ProvidersAPI:
"""A data provider is an object representing the organization in the real world who shares the data. A
provider contains shares which further contain the shared data."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
name: str,
authentication_type: AuthenticationType,
*,
comment: Optional[str] = None,
recipient_profile_str: Optional[str] = None,
) -> ProviderInfo:
"""Creates a new authentication provider minimally based on a name and authentication type. The caller
must be an admin on the metastore.
:param name: str
The name of the Provider.
:param authentication_type: :class:`AuthenticationType`
:param comment: str (optional)
Description about the provider.
:param recipient_profile_str: str (optional)
This field is required when the __authentication_type__ is **TOKEN**, **OAUTH_CLIENT_CREDENTIALS**
or not provided.
:returns: :class:`ProviderInfo`
"""
body = {}
if authentication_type is not None:
body["authentication_type"] = authentication_type.value
if comment is not None:
body["comment"] = comment
if name is not None:
body["name"] = name
if recipient_profile_str is not None:
body["recipient_profile_str"] = recipient_profile_str
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.1/unity-catalog/providers", body=body, headers=headers)
return ProviderInfo.from_dict(res)
def delete(self, name: str):
"""Deletes an authentication provider, if the caller is a metastore admin or is the owner of the
provider.
:param name: str
Name of the provider.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.1/unity-catalog/providers/{name}", headers=headers)
def get(self, name: str) -> ProviderInfo:
"""Gets a specific authentication provider. The caller must supply the name of the provider, and must
either be a metastore admin or the owner of the provider.
:param name: str
Name of the provider.
:returns: :class:`ProviderInfo`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.1/unity-catalog/providers/{name}", headers=headers)
return ProviderInfo.from_dict(res)
def list(
self,
*,
data_provider_global_metastore_id: Optional[str] = None,
max_results: Optional[int] = None,
page_token: Optional[str] = None,
) -> Iterator[ProviderInfo]:
"""Gets an array of available authentication providers. The caller must either be a metastore admin, have
the **USE_PROVIDER** privilege on the providers, or be the owner of the providers. Providers not owned
by the caller and for which the caller does not have the **USE_PROVIDER** privilege are not included
in the response. There is no guarantee of a specific ordering of the elements in the array.
:param data_provider_global_metastore_id: str (optional)
If not provided, all providers will be returned. If no providers exist with this ID, no results will
be returned.
:param max_results: int (optional)
Maximum number of providers to return. - when set to 0, the page length is set to a server
configured value (recommended); - when set to a value greater than 0, the page length is the minimum
of this value and a server configured value; - when set to a value less than 0, an invalid parameter
error is returned; - If not set, all valid providers are returned (not recommended). - Note: The
number of returned providers might be less than the specified max_results size, even zero. The only
definitive indication that no further providers can be fetched is when the next_page_token is unset
from the response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: Iterator over :class:`ProviderInfo`
"""
query = {}
if data_provider_global_metastore_id is not None:
query["data_provider_global_metastore_id"] = data_provider_global_metastore_id
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
if "max_results" not in query:
query["max_results"] = 0
while True:
json = self._api.do("GET", "/api/2.1/unity-catalog/providers", query=query, headers=headers)
if "providers" in json:
for v in json["providers"]:
yield ProviderInfo.from_dict(v)
if "next_page_token" not in json or not json["next_page_token"]:
return
query["page_token"] = json["next_page_token"]
def list_provider_share_assets(
self,
provider_name: str,
share_name: str,
*,
function_max_results: Optional[int] = None,
notebook_max_results: Optional[int] = None,
table_max_results: Optional[int] = None,
volume_max_results: Optional[int] = None,
) -> ListProviderShareAssetsResponse:
"""Get arrays of assets associated with a specified provider's share. The caller is the recipient of the
share.
:param provider_name: str
The name of the provider who owns the share.
:param share_name: str
The name of the share.
:param function_max_results: int (optional)
Maximum number of functions to return.
:param notebook_max_results: int (optional)
Maximum number of notebooks to return.
:param table_max_results: int (optional)
Maximum number of tables to return.
:param volume_max_results: int (optional)
Maximum number of volumes to return.
:returns: :class:`ListProviderShareAssetsResponse`
"""
query = {}
if function_max_results is not None:
query["function_max_results"] = function_max_results
if notebook_max_results is not None:
query["notebook_max_results"] = notebook_max_results
if table_max_results is not None:
query["table_max_results"] = table_max_results
if volume_max_results is not None:
query["volume_max_results"] = volume_max_results
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", f"/api/2.1/data-sharing/providers/{provider_name}/shares/{share_name}", query=query, headers=headers
)
return ListProviderShareAssetsResponse.from_dict(res)
def list_shares(
self, name: str, *, max_results: Optional[int] = None, page_token: Optional[str] = None
) -> Iterator[ProviderShare]:
"""Gets an array of a specified provider's shares within the metastore where:
* the caller is a metastore admin, or * the caller is the owner.
:param name: str
Name of the provider in which to list shares.
:param max_results: int (optional)
Maximum number of shares to return. - when set to 0, the page length is set to a server configured
value (recommended); - when set to a value greater than 0, the page length is the minimum of this
value and a server configured value; - when set to a value less than 0, an invalid parameter error
is returned; - If not set, all valid shares are returned (not recommended). - Note: The number of
returned shares might be less than the specified max_results size, even zero. The only definitive
indication that no further shares can be fetched is when the next_page_token is unset from the
response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: Iterator over :class:`ProviderShare`
"""
query = {}
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
if "max_results" not in query:
query["max_results"] = 0
while True:
json = self._api.do("GET", f"/api/2.1/unity-catalog/providers/{name}/shares", query=query, headers=headers)
if "shares" in json:
for v in json["shares"]:
yield ProviderShare.from_dict(v)
if "next_page_token" not in json or not json["next_page_token"]:
return
query["page_token"] = json["next_page_token"]
def update(
self,
name: str,
*,
comment: Optional[str] = None,
new_name: Optional[str] = None,
owner: Optional[str] = None,
recipient_profile_str: Optional[str] = None,
) -> ProviderInfo:
"""Updates the information for an authentication provider, if the caller is a metastore admin or is the
owner of the provider. If the update changes the provider name, the caller must be both a metastore
admin and the owner of the provider.
:param name: str
Name of the provider.
:param comment: str (optional)
Description about the provider.
:param new_name: str (optional)
New name for the provider.
:param owner: str (optional)
Username of Provider owner.
:param recipient_profile_str: str (optional)
This field is required when the __authentication_type__ is **TOKEN**, **OAUTH_CLIENT_CREDENTIALS**
or not provided.
:returns: :class:`ProviderInfo`
"""
body = {}
if comment is not None:
body["comment"] = comment
if new_name is not None:
body["new_name"] = new_name
if owner is not None:
body["owner"] = owner
if recipient_profile_str is not None:
body["recipient_profile_str"] = recipient_profile_str
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PATCH", f"/api/2.1/unity-catalog/providers/{name}", body=body, headers=headers)
return ProviderInfo.from_dict(res)
class RecipientActivationAPI:
"""The Recipient Activation API is only applicable in the open sharing model where the recipient object has
the authentication type of `TOKEN`. The data recipient follows the activation link shared by the data
provider to download the credential file that includes the access token. The recipient will then use the
credential file to establish a secure connection with the provider to receive the shared data.
Note that you can download the credential file only once. Recipients should treat the downloaded
credential as a secret and must not share it outside of their organization."""
def __init__(self, api_client):
self._api = api_client
def get_activation_url_info(self, activation_url: str):
"""Gets an activation URL for a share.
:param activation_url: str
The one time activation url. It also accepts activation token.
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do(
"GET", f"/api/2.1/unity-catalog/public/data_sharing_activation_info/{activation_url}", headers=headers
)
def retrieve_token(self, activation_url: str) -> RetrieveTokenResponse:
"""Retrieve access token with an activation url. This is a public API without any authentication.
:param activation_url: str
The one time activation url. It also accepts activation token.
:returns: :class:`RetrieveTokenResponse`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", f"/api/2.1/unity-catalog/public/data_sharing_activation/{activation_url}", headers=headers
)
return RetrieveTokenResponse.from_dict(res)
class RecipientFederationPoliciesAPI:
"""The Recipient Federation Policies APIs are only applicable in the open sharing model where the recipient
object has the authentication type of `OIDC_RECIPIENT`, enabling data sharing from Databricks to
non-Databricks recipients. OIDC Token Federation enables secure, secret-less authentication for accessing
Delta Sharing servers. Users and applications authenticate using short-lived OIDC tokens issued by their
own Identity Provider (IdP), such as Azure Entra ID or Okta, without the need for managing static
credentials or client secrets. A federation policy defines how non-Databricks recipients authenticate
using OIDC tokens. It validates the OIDC claims in federated tokens and is set at the recipient level. The
caller must be the owner of the recipient to create or manage a federation policy. Federation policies
support the following scenarios: - User-to-Machine (U2M) flow: A user accesses Delta Shares using their
own identity, such as connecting through PowerBI Delta Sharing Client. - Machine-to-Machine (M2M) flow: An
application accesses Delta Shares using its own identity, typically for automation tasks like nightly jobs
through Python Delta Sharing Client. OIDC Token Federation enables fine-grained access control, supports
Multi-Factor Authentication (MFA), and enhances security by minimizing the risk of credential leakage
through the use of short-lived, expiring tokens. It is designed for strong identity governance, secure
cross-platform data sharing, and reduced operational overhead for credential management.
For more information, see
https://www.databricks.com/blog/announcing-oidc-token-federation-enhanced-delta-sharing-security and
https://docs.databricks.com/en/delta-sharing/create-recipient-oidc-fed"""
def __init__(self, api_client):
self._api = api_client
def create(self, recipient_name: str, policy: FederationPolicy) -> FederationPolicy:
"""Create a federation policy for an OIDC_FEDERATION recipient for sharing data from Databricks to
non-Databricks recipients. The caller must be the owner of the recipient. When sharing data from
Databricks to non-Databricks clients, you can define a federation policy to authenticate
non-Databricks recipients. The federation policy validates OIDC claims in federated tokens and is
defined at the recipient level. This enables secretless sharing clients to authenticate using OIDC
tokens.
Supported scenarios for federation policies: 1. **User-to-Machine (U2M) flow** (e.g., PowerBI): A user
accesses a resource using their own identity. 2. **Machine-to-Machine (M2M) flow** (e.g., OAuth App):
An OAuth App accesses a resource using its own identity, typically for tasks like running nightly
jobs.
For an overview, refer to: - Blog post: Overview of feature:
https://www.databricks.com/blog/announcing-oidc-token-federation-enhanced-delta-sharing-security
For detailed configuration guides based on your use case: - Creating a Federation Policy as a
provider: https://docs.databricks.com/en/delta-sharing/create-recipient-oidc-fed - Configuration and
usage for Machine-to-Machine (M2M) applications (e.g., Python Delta Sharing Client):
https://docs.databricks.com/aws/en/delta-sharing/sharing-over-oidc-m2m - Configuration and usage for
User-to-Machine (U2M) applications (e.g., PowerBI):
https://docs.databricks.com/aws/en/delta-sharing/sharing-over-oidc-u2m
:param recipient_name: str
Name of the recipient. This is the name of the recipient for which the policy is being created.
:param policy: :class:`FederationPolicy`
Name of the policy. This is the name of the policy to be created.
:returns: :class:`FederationPolicy`
"""
body = policy.as_dict()
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"POST", f"/api/2.0/data-sharing/recipients/{recipient_name}/federation-policies", body=body, headers=headers
)
return FederationPolicy.from_dict(res)
def delete(self, recipient_name: str, name: str):
"""Deletes an existing federation policy for an OIDC_FEDERATION recipient. The caller must be the owner
of the recipient.
:param recipient_name: str
Name of the recipient. This is the name of the recipient for which the policy is being deleted.
:param name: str
Name of the policy. This is the name of the policy to be deleted.
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do(
"DELETE", f"/api/2.0/data-sharing/recipients/{recipient_name}/federation-policies/{name}", headers=headers
)
def get_federation_policy(self, recipient_name: str, name: str) -> FederationPolicy:
"""Reads an existing federation policy for an OIDC_FEDERATION recipient for sharing data from Databricks
to non-Databricks recipients. The caller must have read access to the recipient.
:param recipient_name: str
Name of the recipient. This is the name of the recipient for which the policy is being retrieved.
:param name: str
Name of the policy. This is the name of the policy to be retrieved.
:returns: :class:`FederationPolicy`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", f"/api/2.0/data-sharing/recipients/{recipient_name}/federation-policies/{name}", headers=headers
)
return FederationPolicy.from_dict(res)
def list(
self, recipient_name: str, *, max_results: Optional[int] = None, page_token: Optional[str] = None
) -> Iterator[FederationPolicy]:
"""Lists federation policies for an OIDC_FEDERATION recipient for sharing data from Databricks to
non-Databricks recipients. The caller must have read access to the recipient.
:param recipient_name: str
Name of the recipient. This is the name of the recipient for which the policies are being listed.
:param max_results: int (optional)
:param page_token: str (optional)
:returns: Iterator over :class:`FederationPolicy`
"""
query = {}
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
while True:
json = self._api.do(
"GET",
f"/api/2.0/data-sharing/recipients/{recipient_name}/federation-policies",
query=query,
headers=headers,
)
if "policies" in json:
for v in json["policies"]:
yield FederationPolicy.from_dict(v)
if "next_page_token" not in json or not json["next_page_token"]:
return
query["page_token"] = json["next_page_token"]
class RecipientsAPI:
"""A recipient is an object you create using :method:recipients/create to represent an organization which you
want to allow access shares. The way how sharing works differs depending on whether or not your recipient
has access to a Databricks workspace that is enabled for Unity Catalog:
- For recipients with access to a Databricks workspace that is enabled for Unity Catalog, you can create a
recipient object along with a unique sharing identifier you get from the recipient. The sharing identifier
is the key identifier that enables the secure connection. This sharing mode is called
**Databricks-to-Databricks sharing**.
- For recipients without access to a Databricks workspace that is enabled for Unity Catalog, when you
create a recipient object, Databricks generates an activation link you can send to the recipient. The
recipient follows the activation link to download the credential file, and then uses the credential file
to establish a secure connection to receive the shared data. This sharing mode is called **open sharing**."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
name: str,
authentication_type: AuthenticationType,
*,
comment: Optional[str] = None,
data_recipient_global_metastore_id: Optional[str] = None,
expiration_time: Optional[int] = None,
id: Optional[str] = None,
ip_access_list: Optional[IpAccessList] = None,
owner: Optional[str] = None,
properties_kvpairs: Optional[SecurablePropertiesKvPairs] = None,
sharing_code: Optional[str] = None,
) -> RecipientInfo:
"""Creates a new recipient with the delta sharing authentication type in the metastore. The caller must
be a metastore admin or have the **CREATE_RECIPIENT** privilege on the metastore.
:param name: str
Name of Recipient.
:param authentication_type: :class:`AuthenticationType`
:param comment: str (optional)
Description about the recipient.
:param data_recipient_global_metastore_id: str (optional)
The global Unity Catalog metastore id provided by the data recipient. This field is only present
when the __authentication_type__ is **DATABRICKS**. The identifier is of format
__cloud__:__region__:__metastore-uuid__.
:param expiration_time: int (optional)
Expiration timestamp of the token, in epoch milliseconds.
:param id: str (optional)
[Create,Update:IGN] common - id of the recipient
:param ip_access_list: :class:`IpAccessList` (optional)
IP Access List
:param owner: str (optional)
Username of the recipient owner.
:param properties_kvpairs: :class:`SecurablePropertiesKvPairs` (optional)
Recipient properties as map of string key-value pairs. When provided in update request, the
specified properties will override the existing properties. To add and remove properties, one would
need to perform a read-modify-write.
:param sharing_code: str (optional)
The one-time sharing code provided by the data recipient. This field is only present when the
__authentication_type__ is **DATABRICKS**.
:returns: :class:`RecipientInfo`
"""
body = {}
if authentication_type is not None:
body["authentication_type"] = authentication_type.value
if comment is not None:
body["comment"] = comment
if data_recipient_global_metastore_id is not None:
body["data_recipient_global_metastore_id"] = data_recipient_global_metastore_id
if expiration_time is not None:
body["expiration_time"] = expiration_time
if id is not None:
body["id"] = id
if ip_access_list is not None:
body["ip_access_list"] = ip_access_list.as_dict()
if name is not None:
body["name"] = name
if owner is not None:
body["owner"] = owner
if properties_kvpairs is not None:
body["properties_kvpairs"] = properties_kvpairs.as_dict()
if sharing_code is not None:
body["sharing_code"] = sharing_code
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.1/unity-catalog/recipients", body=body, headers=headers)
return RecipientInfo.from_dict(res)
def delete(self, name: str):
"""Deletes the specified recipient from the metastore. The caller must be the owner of the recipient.
:param name: str
Name of the recipient.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.1/unity-catalog/recipients/{name}", headers=headers)
def get(self, name: str) -> RecipientInfo:
"""Gets a share recipient from the metastore. The caller must be one of: * A user with **USE_RECIPIENT**
privilege on the metastore * The owner of the share recipient * A metastore admin
:param name: str
Name of the recipient.
:returns: :class:`RecipientInfo`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.1/unity-catalog/recipients/{name}", headers=headers)
return RecipientInfo.from_dict(res)
def list(
self,
*,
data_recipient_global_metastore_id: Optional[str] = None,
max_results: Optional[int] = None,
page_token: Optional[str] = None,
) -> Iterator[RecipientInfo]:
"""Gets an array of all share recipients within the current metastore where:
* the caller is a metastore admin, or * the caller is the owner. There is no guarantee of a specific
ordering of the elements in the array.
:param data_recipient_global_metastore_id: str (optional)
If not provided, all recipients will be returned. If no recipients exist with this ID, no results
will be returned.
:param max_results: int (optional)
Maximum number of recipients to return. - when set to 0, the page length is set to a server
configured value (recommended); - when set to a value greater than 0, the page length is the minimum
of this value and a server configured value; - when set to a value less than 0, an invalid parameter
error is returned; - If not set, all valid recipients are returned (not recommended). - Note: The
number of returned recipients might be less than the specified max_results size, even zero. The only
definitive indication that no further recipients can be fetched is when the next_page_token is unset
from the response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: Iterator over :class:`RecipientInfo`
"""
query = {}
if data_recipient_global_metastore_id is not None:
query["data_recipient_global_metastore_id"] = data_recipient_global_metastore_id
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
if "max_results" not in query:
query["max_results"] = 0
while True:
json = self._api.do("GET", "/api/2.1/unity-catalog/recipients", query=query, headers=headers)
if "recipients" in json:
for v in json["recipients"]:
yield RecipientInfo.from_dict(v)
if "next_page_token" not in json or not json["next_page_token"]:
return
query["page_token"] = json["next_page_token"]
def rotate_token(self, name: str, existing_token_expire_in_seconds: int) -> RecipientInfo:
"""Refreshes the specified recipient's delta sharing authentication token with the provided token info.
The caller must be the owner of the recipient.
:param name: str
The name of the Recipient.
:param existing_token_expire_in_seconds: int
The expiration time of the bearer token in ISO 8601 format. This will set the expiration_time of
existing token only to a smaller timestamp, it cannot extend the expiration_time. Use 0 to expire
the existing token immediately, negative number will return an error.
:returns: :class:`RecipientInfo`
"""
body = {}
if existing_token_expire_in_seconds is not None:
body["existing_token_expire_in_seconds"] = existing_token_expire_in_seconds
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", f"/api/2.1/unity-catalog/recipients/{name}/rotate-token", body=body, headers=headers)
return RecipientInfo.from_dict(res)
def share_permissions(
self, name: str, *, max_results: Optional[int] = None, page_token: Optional[str] = None
) -> GetRecipientSharePermissionsResponse:
"""Gets the share permissions for the specified Recipient. The caller must have the **USE_RECIPIENT**
privilege on the metastore or be the owner of the Recipient.
:param name: str
The name of the Recipient.
:param max_results: int (optional)
Maximum number of permissions to return. - when set to 0, the page length is set to a server
configured value (recommended); - when set to a value greater than 0, the page length is the minimum
of this value and a server configured value; - when set to a value less than 0, an invalid parameter
error is returned; - If not set, all valid permissions are returned (not recommended). - Note: The
number of returned permissions might be less than the specified max_results size, even zero. The
only definitive indication that no further permissions can be fetched is when the next_page_token is
unset from the response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: :class:`GetRecipientSharePermissionsResponse`
"""
query = {}
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", f"/api/2.1/unity-catalog/recipients/{name}/share-permissions", query=query, headers=headers
)
return GetRecipientSharePermissionsResponse.from_dict(res)
def update(
self,
name: str,
*,
comment: Optional[str] = None,
expiration_time: Optional[int] = None,
id: Optional[str] = None,
ip_access_list: Optional[IpAccessList] = None,
new_name: Optional[str] = None,
owner: Optional[str] = None,
properties_kvpairs: Optional[SecurablePropertiesKvPairs] = None,
) -> RecipientInfo:
"""Updates an existing recipient in the metastore. The caller must be a metastore admin or the owner of
the recipient. If the recipient name will be updated, the user must be both a metastore admin and the
owner of the recipient.
:param name: str
Name of the recipient.
:param comment: str (optional)
Description about the recipient.
:param expiration_time: int (optional)
Expiration timestamp of the token, in epoch milliseconds.
:param id: str (optional)
[Create,Update:IGN] common - id of the recipient
:param ip_access_list: :class:`IpAccessList` (optional)
IP Access List
:param new_name: str (optional)
New name for the recipient. .
:param owner: str (optional)
Username of the recipient owner.
:param properties_kvpairs: :class:`SecurablePropertiesKvPairs` (optional)
Recipient properties as map of string key-value pairs. When provided in update request, the
specified properties will override the existing properties. To add and remove properties, one would
need to perform a read-modify-write.
:returns: :class:`RecipientInfo`
"""
body = {}
if comment is not None:
body["comment"] = comment
if expiration_time is not None:
body["expiration_time"] = expiration_time
if id is not None:
body["id"] = id
if ip_access_list is not None:
body["ip_access_list"] = ip_access_list.as_dict()
if new_name is not None:
body["new_name"] = new_name
if owner is not None:
body["owner"] = owner
if properties_kvpairs is not None:
body["properties_kvpairs"] = properties_kvpairs.as_dict()
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PATCH", f"/api/2.1/unity-catalog/recipients/{name}", body=body, headers=headers)
return RecipientInfo.from_dict(res)
class SharesAPI:
"""A share is a container instantiated with :method:shares/create. Once created you can iteratively register
a collection of existing data assets defined within the metastore using :method:shares/update. You can
register data assets under their original name, qualified by their original schema, or provide alternate
exposed names."""
def __init__(self, api_client):
self._api = api_client
def create(self, name: str, *, comment: Optional[str] = None, storage_root: Optional[str] = None) -> ShareInfo:
"""Creates a new share for data objects. Data objects can be added after creation with **update**. The
caller must be a metastore admin or have the **CREATE_SHARE** privilege on the metastore.
:param name: str
Name of the share.
:param comment: str (optional)
User-provided free-form text description.
:param storage_root: str (optional)
Storage root URL for the share.
:returns: :class:`ShareInfo`
"""
body = {}
if comment is not None:
body["comment"] = comment
if name is not None:
body["name"] = name
if storage_root is not None:
body["storage_root"] = storage_root
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.1/unity-catalog/shares", body=body, headers=headers)
return ShareInfo.from_dict(res)
def delete(self, name: str):
"""Deletes a data object share from the metastore. The caller must be an owner of the share.
:param name: str
The name of the share.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.1/unity-catalog/shares/{name}", headers=headers)
def get(self, name: str, *, include_shared_data: Optional[bool] = None) -> ShareInfo:
"""Gets a data object share from the metastore. The caller must have the USE_SHARE privilege on the
metastore or be the owner of the share.
:param name: str
The name of the share.
:param include_shared_data: bool (optional)
Query for data to include in the share.
:returns: :class:`ShareInfo`
"""
query = {}
if include_shared_data is not None:
query["include_shared_data"] = include_shared_data
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.1/unity-catalog/shares/{name}", query=query, headers=headers)
return ShareInfo.from_dict(res)
def list_shares(
self, *, max_results: Optional[int] = None, page_token: Optional[str] = None
) -> Iterator[ShareInfo]:
"""Gets an array of data object shares from the metastore. If the caller has the USE_SHARE privilege on
the metastore, all shares are returned. Otherwise, only shares owned by the caller are returned. There
is no guarantee of a specific ordering of the elements in the array.
:param max_results: int (optional)
Maximum number of shares to return. - when set to 0, the page length is set to a server configured
value (recommended); - when set to a value greater than 0, the page length is the minimum of this
value and a server configured value; - when set to a value less than 0, an invalid parameter error
is returned; - If not set, all valid shares are returned (not recommended). - Note: The number of
returned shares might be less than the specified max_results size, even zero. The only definitive
indication that no further shares can be fetched is when the next_page_token is unset from the
response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: Iterator over :class:`ShareInfo`
"""
query = {}
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
if "max_results" not in query:
query["max_results"] = 0
while True:
json = self._api.do("GET", "/api/2.1/unity-catalog/shares", query=query, headers=headers)
if "shares" in json:
for v in json["shares"]:
yield ShareInfo.from_dict(v)
if "next_page_token" not in json or not json["next_page_token"]:
return
query["page_token"] = json["next_page_token"]
def share_permissions(
self, name: str, *, max_results: Optional[int] = None, page_token: Optional[str] = None
) -> GetSharePermissionsResponse:
"""Gets the permissions for a data share from the metastore. The caller must have the USE_SHARE privilege
on the metastore or be the owner of the share.
:param name: str
The name of the Recipient.
:param max_results: int (optional)
Maximum number of permissions to return. - when set to 0, the page length is set to a server
configured value (recommended); - when set to a value greater than 0, the page length is the minimum
of this value and a server configured value; - when set to a value less than 0, an invalid parameter
error is returned; - If not set, all valid permissions are returned (not recommended). - Note: The
number of returned permissions might be less than the specified max_results size, even zero. The
only definitive indication that no further permissions can be fetched is when the next_page_token is
unset from the response.
:param page_token: str (optional)
Opaque pagination token to go to next page based on previous query.
:returns: :class:`GetSharePermissionsResponse`
"""
query = {}
if max_results is not None:
query["max_results"] = max_results
if page_token is not None:
query["page_token"] = page_token
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.1/unity-catalog/shares/{name}/permissions", query=query, headers=headers)
return GetSharePermissionsResponse.from_dict(res)
def update(
self,
name: str,
*,
comment: Optional[str] = None,
new_name: Optional[str] = None,
owner: Optional[str] = None,
storage_root: Optional[str] = None,
updates: Optional[List[SharedDataObjectUpdate]] = None,
) -> ShareInfo:
"""Updates the share with the changes and data objects in the request. The caller must be the owner of
the share or a metastore admin.
When the caller is a metastore admin, only the __owner__ field can be updated.
In the case the share name is changed, **updateShare** requires that the caller is the owner of the
share and has the CREATE_SHARE privilege.
If there are notebook files in the share, the __storage_root__ field cannot be updated.
For each table that is added through this method, the share owner must also have **SELECT** privilege
on the table. This privilege must be maintained indefinitely for recipients to be able to access the
table. Typically, you should use a group as the share owner.
Table removals through **update** do not require additional privileges.
:param name: str
The name of the share.
:param comment: str (optional)
User-provided free-form text description.
:param new_name: str (optional)
New name for the share.
:param owner: str (optional)
Username of current owner of share.
:param storage_root: str (optional)
Storage root URL for the share.
:param updates: List[:class:`SharedDataObjectUpdate`] (optional)
Array of shared data object updates.
:returns: :class:`ShareInfo`
"""
body = {}
if comment is not None:
body["comment"] = comment
if new_name is not None:
body["new_name"] = new_name
if owner is not None:
body["owner"] = owner
if storage_root is not None:
body["storage_root"] = storage_root
if updates is not None:
body["updates"] = [v.as_dict() for v in updates]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PATCH", f"/api/2.1/unity-catalog/shares/{name}", body=body, headers=headers)
return ShareInfo.from_dict(res)
def update_permissions(
self,
name: str,
*,
changes: Optional[List[PermissionsChange]] = None,
omit_permissions_list: Optional[bool] = None,
) -> UpdateSharePermissionsResponse:
"""Updates the permissions for a data share in the metastore. The caller must have both the USE_SHARE and
SET_SHARE_PERMISSION privileges on the metastore, or be the owner of the share.
For new recipient grants, the user must also be the owner of the recipients. recipient revocations do
not require additional privileges.
:param name: str
The name of the share.
:param changes: List[:class:`PermissionsChange`] (optional)
Array of permissions change objects.
:param omit_permissions_list: bool (optional)
Optional. Whether to return the latest permissions list of the share in the response.
:returns: :class:`UpdateSharePermissionsResponse`
"""
body = {}
if changes is not None:
body["changes"] = [v.as_dict() for v in changes]
if omit_permissions_list is not None:
body["omit_permissions_list"] = omit_permissions_list
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PATCH", f"/api/2.1/unity-catalog/shares/{name}/permissions", body=body, headers=headers)
return UpdateSharePermissionsResponse.from_dict(res)