# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. from __future__ import annotations import logging import random import time from dataclasses import dataclass from datetime import timedelta from enum import Enum from typing import Any, Callable, Dict, Iterator, List, Optional from databricks.sdk.client_types import HostType from databricks.sdk.service import sql from databricks.sdk.service._internal import (Wait, _enum, _from_dict, _repeated_dict) from ..errors import OperationFailed _LOG = logging.getLogger("databricks.sdk") # all definitions in this file are in alphabetical order @dataclass class AuthorizationDetails: grant_rules: Optional[List[AuthorizationDetailsGrantRule]] = None """Represents downscoped permission rules with specific access rights. This field is specific to `workspace_rule_set` constraint.""" resource_legacy_acl_path: Optional[str] = None """The acl path of the tree store resource resource.""" resource_name: Optional[str] = None """The resource name to which the authorization rule applies. This field is specific to `workspace_rule_set` constraint. Format: `workspaces/{workspace_id}/dashboards/{dashboard_id}`""" type: Optional[str] = None """The type of authorization downscoping policy. Ex: `workspace_rule_set` defines access rules for a specific workspace resource""" def as_dict(self) -> dict: """Serializes the AuthorizationDetails into a dictionary suitable for use as a JSON request body.""" body = {} if self.grant_rules: body["grant_rules"] = [v.as_dict() for v in self.grant_rules] if self.resource_legacy_acl_path is not None: body["resource_legacy_acl_path"] = self.resource_legacy_acl_path if self.resource_name is not None: body["resource_name"] = self.resource_name if self.type is not None: body["type"] = self.type return body def as_shallow_dict(self) -> dict: """Serializes the AuthorizationDetails into a shallow dictionary of its immediate attributes.""" body = {} if self.grant_rules: body["grant_rules"] = self.grant_rules if self.resource_legacy_acl_path is not None: body["resource_legacy_acl_path"] = self.resource_legacy_acl_path if self.resource_name is not None: body["resource_name"] = self.resource_name if self.type is not None: body["type"] = self.type return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AuthorizationDetails: """Deserializes the AuthorizationDetails from a dictionary.""" return cls( grant_rules=_repeated_dict(d, "grant_rules", AuthorizationDetailsGrantRule), resource_legacy_acl_path=d.get("resource_legacy_acl_path", None), resource_name=d.get("resource_name", None), type=d.get("type", None), ) @dataclass class AuthorizationDetailsGrantRule: permission_set: Optional[str] = None """Permission sets for dashboard are defined in iam-common/rbac-common/permission-sets/definitions/TreeStoreBasePermissionSets Ex: `permissionSets/dashboard.runner`""" def as_dict(self) -> dict: """Serializes the AuthorizationDetailsGrantRule into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission_set is not None: body["permission_set"] = self.permission_set return body def as_shallow_dict(self) -> dict: """Serializes the AuthorizationDetailsGrantRule into a shallow dictionary of its immediate attributes.""" body = {} if self.permission_set is not None: body["permission_set"] = self.permission_set return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AuthorizationDetailsGrantRule: """Deserializes the AuthorizationDetailsGrantRule from a dictionary.""" return cls(permission_set=d.get("permission_set", None)) @dataclass class CronSchedule: quartz_cron_expression: str """A cron expression using quartz syntax. EX: `0 0 8 * * ?` represents everyday at 8am. See [Cron Trigger] for details. [Cron Trigger]: http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html""" timezone_id: str """A Java timezone id. The schedule will be resolved with respect to this timezone. See [Java TimeZone] for details. [Java TimeZone]: https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html""" def as_dict(self) -> dict: """Serializes the CronSchedule into a dictionary suitable for use as a JSON request body.""" body = {} if self.quartz_cron_expression is not None: body["quartz_cron_expression"] = self.quartz_cron_expression if self.timezone_id is not None: body["timezone_id"] = self.timezone_id return body def as_shallow_dict(self) -> dict: """Serializes the CronSchedule into a shallow dictionary of its immediate attributes.""" body = {} if self.quartz_cron_expression is not None: body["quartz_cron_expression"] = self.quartz_cron_expression if self.timezone_id is not None: body["timezone_id"] = self.timezone_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> CronSchedule: """Deserializes the CronSchedule from a dictionary.""" return cls(quartz_cron_expression=d.get("quartz_cron_expression", None), timezone_id=d.get("timezone_id", None)) @dataclass class Dashboard: create_time: Optional[str] = None """The timestamp of when the dashboard was created.""" dashboard_id: Optional[str] = None """UUID identifying the dashboard.""" display_name: Optional[str] = None """The display name of the dashboard.""" etag: Optional[str] = None """The etag for the dashboard. Can be optionally provided on updates to ensure that the dashboard has not been modified since the last read. This field is excluded in List Dashboards responses.""" lifecycle_state: Optional[LifecycleState] = None """The state of the dashboard resource. Used for tracking trashed status.""" parent_path: Optional[str] = None """The workspace path of the folder containing the dashboard. Includes leading slash and no trailing slash. This field is excluded in List Dashboards responses.""" path: Optional[str] = None """The workspace path of the dashboard asset, including the file name. Exported dashboards always have the file extension `.lvdash.json`. This field is excluded in List Dashboards responses.""" serialized_dashboard: Optional[str] = None """The contents of the dashboard in serialized string form. This field is excluded in List Dashboards responses. Use the [get dashboard API] to retrieve an example response, which includes the `serialized_dashboard` field. This field provides the structure of the JSON string that represents the dashboard's layout and components. [get dashboard API]: https://docs.databricks.com/api/workspace/lakeview/get""" update_time: Optional[str] = None """The timestamp of when the dashboard was last updated by the user. This field is excluded in List Dashboards responses.""" warehouse_id: Optional[str] = None """The warehouse ID used to run the dashboard.""" def as_dict(self) -> dict: """Serializes the Dashboard into a dictionary suitable for use as a JSON request body.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.display_name is not None: body["display_name"] = self.display_name if self.etag is not None: body["etag"] = self.etag if self.lifecycle_state is not None: body["lifecycle_state"] = self.lifecycle_state.value if self.parent_path is not None: body["parent_path"] = self.parent_path if self.path is not None: body["path"] = self.path if self.serialized_dashboard is not None: body["serialized_dashboard"] = self.serialized_dashboard if self.update_time is not None: body["update_time"] = self.update_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body def as_shallow_dict(self) -> dict: """Serializes the Dashboard into a shallow dictionary of its immediate attributes.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.display_name is not None: body["display_name"] = self.display_name if self.etag is not None: body["etag"] = self.etag if self.lifecycle_state is not None: body["lifecycle_state"] = self.lifecycle_state if self.parent_path is not None: body["parent_path"] = self.parent_path if self.path is not None: body["path"] = self.path if self.serialized_dashboard is not None: body["serialized_dashboard"] = self.serialized_dashboard if self.update_time is not None: body["update_time"] = self.update_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Dashboard: """Deserializes the Dashboard from a dictionary.""" return cls( create_time=d.get("create_time", None), dashboard_id=d.get("dashboard_id", None), display_name=d.get("display_name", None), etag=d.get("etag", None), lifecycle_state=_enum(d, "lifecycle_state", LifecycleState), parent_path=d.get("parent_path", None), path=d.get("path", None), serialized_dashboard=d.get("serialized_dashboard", None), update_time=d.get("update_time", None), warehouse_id=d.get("warehouse_id", None), ) class DashboardView(Enum): DASHBOARD_VIEW_BASIC = "DASHBOARD_VIEW_BASIC" @dataclass class GenieAttachment: """Genie AI Response""" attachment_id: Optional[str] = None """Attachment ID""" query: Optional[GenieQueryAttachment] = None """Query Attachment if Genie responds with a SQL query""" suggested_questions: Optional[GenieSuggestedQuestionsAttachment] = None """Follow-up questions suggested by Genie""" text: Optional[TextAttachment] = None """Text Attachment if Genie responds with text This also contains the final summary when available.""" def as_dict(self) -> dict: """Serializes the GenieAttachment into a dictionary suitable for use as a JSON request body.""" body = {} if self.attachment_id is not None: body["attachment_id"] = self.attachment_id if self.query: body["query"] = self.query.as_dict() if self.suggested_questions: body["suggested_questions"] = self.suggested_questions.as_dict() if self.text: body["text"] = self.text.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the GenieAttachment into a shallow dictionary of its immediate attributes.""" body = {} if self.attachment_id is not None: body["attachment_id"] = self.attachment_id if self.query: body["query"] = self.query if self.suggested_questions: body["suggested_questions"] = self.suggested_questions if self.text: body["text"] = self.text return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieAttachment: """Deserializes the GenieAttachment from a dictionary.""" return cls( attachment_id=d.get("attachment_id", None), query=_from_dict(d, "query", GenieQueryAttachment), suggested_questions=_from_dict(d, "suggested_questions", GenieSuggestedQuestionsAttachment), text=_from_dict(d, "text", TextAttachment), ) @dataclass class GenieConversation: space_id: str """Genie space ID""" title: str """Conversation title""" conversation_id: str """Conversation ID""" created_timestamp: Optional[int] = None """Timestamp when the message was created""" id: Optional[str] = None """Conversation ID. Legacy identifier, use conversation_id instead""" last_updated_timestamp: Optional[int] = None """Timestamp when the message was last updated""" user_id: Optional[int] = None """ID of the user who created the conversation""" def as_dict(self) -> dict: """Serializes the GenieConversation into a dictionary suitable for use as a JSON request body.""" body = {} if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.space_id is not None: body["space_id"] = self.space_id if self.title is not None: body["title"] = self.title if self.user_id is not None: body["user_id"] = self.user_id return body def as_shallow_dict(self) -> dict: """Serializes the GenieConversation into a shallow dictionary of its immediate attributes.""" body = {} if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.space_id is not None: body["space_id"] = self.space_id if self.title is not None: body["title"] = self.title if self.user_id is not None: body["user_id"] = self.user_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieConversation: """Deserializes the GenieConversation from a dictionary.""" return cls( conversation_id=d.get("conversation_id", None), created_timestamp=d.get("created_timestamp", None), id=d.get("id", None), last_updated_timestamp=d.get("last_updated_timestamp", None), space_id=d.get("space_id", None), title=d.get("title", None), user_id=d.get("user_id", None), ) @dataclass class GenieConversationSummary: conversation_id: str created_timestamp: Optional[int] = None title: Optional[str] = None def as_dict(self) -> dict: """Serializes the GenieConversationSummary into a dictionary suitable for use as a JSON request body.""" body = {} if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.title is not None: body["title"] = self.title return body def as_shallow_dict(self) -> dict: """Serializes the GenieConversationSummary into a shallow dictionary of its immediate attributes.""" body = {} if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.title is not None: body["title"] = self.title return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieConversationSummary: """Deserializes the GenieConversationSummary from a dictionary.""" return cls( conversation_id=d.get("conversation_id", None), created_timestamp=d.get("created_timestamp", None), title=d.get("title", None), ) @dataclass class GenieFeedback: """Feedback containing rating and optional comment""" rating: Optional[GenieFeedbackRating] = None """The feedback rating""" def as_dict(self) -> dict: """Serializes the GenieFeedback into a dictionary suitable for use as a JSON request body.""" body = {} if self.rating is not None: body["rating"] = self.rating.value return body def as_shallow_dict(self) -> dict: """Serializes the GenieFeedback into a shallow dictionary of its immediate attributes.""" body = {} if self.rating is not None: body["rating"] = self.rating return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieFeedback: """Deserializes the GenieFeedback from a dictionary.""" return cls(rating=_enum(d, "rating", GenieFeedbackRating)) class GenieFeedbackRating(Enum): """Feedback rating for Genie messages""" NEGATIVE = "NEGATIVE" NONE = "NONE" POSITIVE = "POSITIVE" @dataclass class GenieGenerateDownloadFullQueryResultResponse: download_id: Optional[str] = None """Download ID. Use this ID to track the download request in subsequent polling calls""" download_id_signature: Optional[str] = None """JWT signature for the download_id to ensure secure access to query results""" def as_dict(self) -> dict: """Serializes the GenieGenerateDownloadFullQueryResultResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.download_id is not None: body["download_id"] = self.download_id if self.download_id_signature is not None: body["download_id_signature"] = self.download_id_signature return body def as_shallow_dict(self) -> dict: """Serializes the GenieGenerateDownloadFullQueryResultResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.download_id is not None: body["download_id"] = self.download_id if self.download_id_signature is not None: body["download_id_signature"] = self.download_id_signature return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieGenerateDownloadFullQueryResultResponse: """Deserializes the GenieGenerateDownloadFullQueryResultResponse from a dictionary.""" return cls(download_id=d.get("download_id", None), download_id_signature=d.get("download_id_signature", None)) @dataclass class GenieGetDownloadFullQueryResultResponse: statement_response: Optional[sql.StatementResponse] = None """SQL Statement Execution response. See [Get status, manifest, and result first chunk](:method:statementexecution/getstatement) for more details.""" def as_dict(self) -> dict: """Serializes the GenieGetDownloadFullQueryResultResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.statement_response: body["statement_response"] = self.statement_response.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the GenieGetDownloadFullQueryResultResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.statement_response: body["statement_response"] = self.statement_response return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieGetDownloadFullQueryResultResponse: """Deserializes the GenieGetDownloadFullQueryResultResponse from a dictionary.""" return cls(statement_response=_from_dict(d, "statement_response", sql.StatementResponse)) @dataclass class GenieGetMessageQueryResultResponse: statement_response: Optional[sql.StatementResponse] = None """SQL Statement Execution response. See [Get status, manifest, and result first chunk](:method:statementexecution/getstatement) for more details.""" def as_dict(self) -> dict: """Serializes the GenieGetMessageQueryResultResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.statement_response: body["statement_response"] = self.statement_response.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the GenieGetMessageQueryResultResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.statement_response: body["statement_response"] = self.statement_response return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieGetMessageQueryResultResponse: """Deserializes the GenieGetMessageQueryResultResponse from a dictionary.""" return cls(statement_response=_from_dict(d, "statement_response", sql.StatementResponse)) @dataclass class GenieListConversationMessagesResponse: messages: Optional[List[GenieMessage]] = None """List of messages in the conversation.""" next_page_token: Optional[str] = None """The token to use for retrieving the next page of results.""" def as_dict(self) -> dict: """Serializes the GenieListConversationMessagesResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.messages: body["messages"] = [v.as_dict() for v in self.messages] if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body def as_shallow_dict(self) -> dict: """Serializes the GenieListConversationMessagesResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.messages: body["messages"] = self.messages if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieListConversationMessagesResponse: """Deserializes the GenieListConversationMessagesResponse from a dictionary.""" return cls(messages=_repeated_dict(d, "messages", GenieMessage), next_page_token=d.get("next_page_token", None)) @dataclass class GenieListConversationsResponse: conversations: Optional[List[GenieConversationSummary]] = None """List of conversations in the Genie space""" next_page_token: Optional[str] = None """Token to get the next page of results""" def as_dict(self) -> dict: """Serializes the GenieListConversationsResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.conversations: body["conversations"] = [v.as_dict() for v in self.conversations] if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body def as_shallow_dict(self) -> dict: """Serializes the GenieListConversationsResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.conversations: body["conversations"] = self.conversations if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieListConversationsResponse: """Deserializes the GenieListConversationsResponse from a dictionary.""" return cls( conversations=_repeated_dict(d, "conversations", GenieConversationSummary), next_page_token=d.get("next_page_token", None), ) @dataclass class GenieListSpacesResponse: next_page_token: Optional[str] = None """Token to get the next page of results""" spaces: Optional[List[GenieSpace]] = None """List of Genie spaces""" def as_dict(self) -> dict: """Serializes the GenieListSpacesResponse 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.spaces: body["spaces"] = [v.as_dict() for v in self.spaces] return body def as_shallow_dict(self) -> dict: """Serializes the GenieListSpacesResponse 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.spaces: body["spaces"] = self.spaces return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieListSpacesResponse: """Deserializes the GenieListSpacesResponse from a dictionary.""" return cls(next_page_token=d.get("next_page_token", None), spaces=_repeated_dict(d, "spaces", GenieSpace)) @dataclass class GenieMessage: space_id: str """Genie space ID""" conversation_id: str """Conversation ID""" content: str """User message content""" message_id: str """Message ID""" attachments: Optional[List[GenieAttachment]] = None """AI-generated response to the message""" created_timestamp: Optional[int] = None """Timestamp when the message was created""" error: Optional[MessageError] = None """Error message if Genie failed to respond to the message""" feedback: Optional[GenieFeedback] = None """User feedback for the message if provided""" id: Optional[str] = None """Message ID. Legacy identifier, use message_id instead""" last_updated_timestamp: Optional[int] = None """Timestamp when the message was last updated""" query_result: Optional[Result] = None """The result of SQL query if the message includes a query attachment. Deprecated. Use `query_result_metadata` in `GenieQueryAttachment` instead.""" status: Optional[MessageStatus] = None user_id: Optional[int] = None """ID of the user who created the message""" def as_dict(self) -> dict: """Serializes the GenieMessage into a dictionary suitable for use as a JSON request body.""" body = {} if self.attachments: body["attachments"] = [v.as_dict() for v in self.attachments] if self.content is not None: body["content"] = self.content if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.error: body["error"] = self.error.as_dict() if self.feedback: body["feedback"] = self.feedback.as_dict() if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.message_id is not None: body["message_id"] = self.message_id if self.query_result: body["query_result"] = self.query_result.as_dict() if self.space_id is not None: body["space_id"] = self.space_id if self.status is not None: body["status"] = self.status.value if self.user_id is not None: body["user_id"] = self.user_id return body def as_shallow_dict(self) -> dict: """Serializes the GenieMessage into a shallow dictionary of its immediate attributes.""" body = {} if self.attachments: body["attachments"] = self.attachments if self.content is not None: body["content"] = self.content if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.created_timestamp is not None: body["created_timestamp"] = self.created_timestamp if self.error: body["error"] = self.error if self.feedback: body["feedback"] = self.feedback if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.message_id is not None: body["message_id"] = self.message_id if self.query_result: body["query_result"] = self.query_result if self.space_id is not None: body["space_id"] = self.space_id if self.status is not None: body["status"] = self.status if self.user_id is not None: body["user_id"] = self.user_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieMessage: """Deserializes the GenieMessage from a dictionary.""" return cls( attachments=_repeated_dict(d, "attachments", GenieAttachment), content=d.get("content", None), conversation_id=d.get("conversation_id", None), created_timestamp=d.get("created_timestamp", None), error=_from_dict(d, "error", MessageError), feedback=_from_dict(d, "feedback", GenieFeedback), id=d.get("id", None), last_updated_timestamp=d.get("last_updated_timestamp", None), message_id=d.get("message_id", None), query_result=_from_dict(d, "query_result", Result), space_id=d.get("space_id", None), status=_enum(d, "status", MessageStatus), user_id=d.get("user_id", None), ) @dataclass class GenieQueryAttachment: description: Optional[str] = None """Description of the query""" id: Optional[str] = None last_updated_timestamp: Optional[int] = None """Time when the user updated the query last""" parameters: Optional[List[QueryAttachmentParameter]] = None query: Optional[str] = None """AI generated SQL query""" query_result_metadata: Optional[GenieResultMetadata] = None """Metadata associated with the query result.""" statement_id: Optional[str] = None """Statement Execution API statement id. Use [Get status, manifest, and result first chunk](:method:statementexecution/getstatement) to get the full result data.""" title: Optional[str] = None """Name of the query""" def as_dict(self) -> dict: """Serializes the GenieQueryAttachment into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.parameters: body["parameters"] = [v.as_dict() for v in self.parameters] if self.query is not None: body["query"] = self.query if self.query_result_metadata: body["query_result_metadata"] = self.query_result_metadata.as_dict() if self.statement_id is not None: body["statement_id"] = self.statement_id if self.title is not None: body["title"] = self.title return body def as_shallow_dict(self) -> dict: """Serializes the GenieQueryAttachment into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.id is not None: body["id"] = self.id if self.last_updated_timestamp is not None: body["last_updated_timestamp"] = self.last_updated_timestamp if self.parameters: body["parameters"] = self.parameters if self.query is not None: body["query"] = self.query if self.query_result_metadata: body["query_result_metadata"] = self.query_result_metadata if self.statement_id is not None: body["statement_id"] = self.statement_id if self.title is not None: body["title"] = self.title return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieQueryAttachment: """Deserializes the GenieQueryAttachment from a dictionary.""" return cls( description=d.get("description", None), id=d.get("id", None), last_updated_timestamp=d.get("last_updated_timestamp", None), parameters=_repeated_dict(d, "parameters", QueryAttachmentParameter), query=d.get("query", None), query_result_metadata=_from_dict(d, "query_result_metadata", GenieResultMetadata), statement_id=d.get("statement_id", None), title=d.get("title", None), ) @dataclass class GenieResultMetadata: is_truncated: Optional[bool] = None """Indicates whether the result set is truncated.""" row_count: Optional[int] = None """The number of rows in the result set.""" def as_dict(self) -> dict: """Serializes the GenieResultMetadata into a dictionary suitable for use as a JSON request body.""" body = {} if self.is_truncated is not None: body["is_truncated"] = self.is_truncated if self.row_count is not None: body["row_count"] = self.row_count return body def as_shallow_dict(self) -> dict: """Serializes the GenieResultMetadata into a shallow dictionary of its immediate attributes.""" body = {} if self.is_truncated is not None: body["is_truncated"] = self.is_truncated if self.row_count is not None: body["row_count"] = self.row_count return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieResultMetadata: """Deserializes the GenieResultMetadata from a dictionary.""" return cls(is_truncated=d.get("is_truncated", None), row_count=d.get("row_count", None)) @dataclass class GenieSpace: space_id: str """Genie space ID""" title: str """Title of the Genie Space""" description: Optional[str] = None """Description of the Genie Space""" serialized_space: Optional[str] = None """The contents of the Genie Space in serialized string form. This field is excluded in List Genie spaces responses. Use the [Get Genie Space](:method:genie/getspace) API to retrieve an example response, which includes the `serialized_space` field. This field provides the structure of the JSON string that represents the space's layout and components.""" warehouse_id: Optional[str] = None """Warehouse associated with the Genie Space""" def as_dict(self) -> dict: """Serializes the GenieSpace into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.serialized_space is not None: body["serialized_space"] = self.serialized_space if self.space_id is not None: body["space_id"] = self.space_id if self.title is not None: body["title"] = self.title if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body def as_shallow_dict(self) -> dict: """Serializes the GenieSpace into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.serialized_space is not None: body["serialized_space"] = self.serialized_space if self.space_id is not None: body["space_id"] = self.space_id if self.title is not None: body["title"] = self.title if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieSpace: """Deserializes the GenieSpace from a dictionary.""" return cls( description=d.get("description", None), serialized_space=d.get("serialized_space", None), space_id=d.get("space_id", None), title=d.get("title", None), warehouse_id=d.get("warehouse_id", None), ) @dataclass class GenieStartConversationResponse: message_id: str """Message ID""" conversation_id: str """Conversation ID""" conversation: Optional[GenieConversation] = None message: Optional[GenieMessage] = None def as_dict(self) -> dict: """Serializes the GenieStartConversationResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.conversation: body["conversation"] = self.conversation.as_dict() if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.message: body["message"] = self.message.as_dict() if self.message_id is not None: body["message_id"] = self.message_id return body def as_shallow_dict(self) -> dict: """Serializes the GenieStartConversationResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.conversation: body["conversation"] = self.conversation if self.conversation_id is not None: body["conversation_id"] = self.conversation_id if self.message: body["message"] = self.message if self.message_id is not None: body["message_id"] = self.message_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieStartConversationResponse: """Deserializes the GenieStartConversationResponse from a dictionary.""" return cls( conversation=_from_dict(d, "conversation", GenieConversation), conversation_id=d.get("conversation_id", None), message=_from_dict(d, "message", GenieMessage), message_id=d.get("message_id", None), ) @dataclass class GenieSuggestedQuestionsAttachment: """Follow-up questions suggested by Genie""" questions: Optional[List[str]] = None """The suggested follow-up questions""" def as_dict(self) -> dict: """Serializes the GenieSuggestedQuestionsAttachment into a dictionary suitable for use as a JSON request body.""" body = {} if self.questions: body["questions"] = [v for v in self.questions] return body def as_shallow_dict(self) -> dict: """Serializes the GenieSuggestedQuestionsAttachment into a shallow dictionary of its immediate attributes.""" body = {} if self.questions: body["questions"] = self.questions return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GenieSuggestedQuestionsAttachment: """Deserializes the GenieSuggestedQuestionsAttachment from a dictionary.""" return cls(questions=d.get("questions", None)) @dataclass class GetPublishedDashboardTokenInfoResponse: authorization_details: Optional[List[AuthorizationDetails]] = None """Authorization constraints for accessing the published dashboard. Currently includes `workspace_rule_set` and could be enriched with `unity_catalog_privileges` before oAuth token generation.""" custom_claim: Optional[str] = None """Custom claim generated from external_value and external_viewer_id. Format: `urn:aibi:external_data:::`""" scope: Optional[str] = None """Scope defining access permissions.""" def as_dict(self) -> dict: """Serializes the GetPublishedDashboardTokenInfoResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.authorization_details: body["authorization_details"] = [v.as_dict() for v in self.authorization_details] if self.custom_claim is not None: body["custom_claim"] = self.custom_claim if self.scope is not None: body["scope"] = self.scope return body def as_shallow_dict(self) -> dict: """Serializes the GetPublishedDashboardTokenInfoResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.authorization_details: body["authorization_details"] = self.authorization_details if self.custom_claim is not None: body["custom_claim"] = self.custom_claim if self.scope is not None: body["scope"] = self.scope return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GetPublishedDashboardTokenInfoResponse: """Deserializes the GetPublishedDashboardTokenInfoResponse from a dictionary.""" return cls( authorization_details=_repeated_dict(d, "authorization_details", AuthorizationDetails), custom_claim=d.get("custom_claim", None), scope=d.get("scope", None), ) class LifecycleState(Enum): ACTIVE = "ACTIVE" TRASHED = "TRASHED" @dataclass class ListDashboardsResponse: dashboards: Optional[List[Dashboard]] = None next_page_token: Optional[str] = None """A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent dashboards.""" def as_dict(self) -> dict: """Serializes the ListDashboardsResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.dashboards: body["dashboards"] = [v.as_dict() for v in self.dashboards] if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body def as_shallow_dict(self) -> dict: """Serializes the ListDashboardsResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.dashboards: body["dashboards"] = self.dashboards if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListDashboardsResponse: """Deserializes the ListDashboardsResponse from a dictionary.""" return cls( dashboards=_repeated_dict(d, "dashboards", Dashboard), next_page_token=d.get("next_page_token", None) ) @dataclass class ListSchedulesResponse: next_page_token: Optional[str] = None """A token that can be used as a `page_token` in subsequent requests to retrieve the next page of results. If this field is omitted, there are no subsequent schedules.""" schedules: Optional[List[Schedule]] = None def as_dict(self) -> dict: """Serializes the ListSchedulesResponse 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.schedules: body["schedules"] = [v.as_dict() for v in self.schedules] return body def as_shallow_dict(self) -> dict: """Serializes the ListSchedulesResponse 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.schedules: body["schedules"] = self.schedules return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListSchedulesResponse: """Deserializes the ListSchedulesResponse from a dictionary.""" return cls(next_page_token=d.get("next_page_token", None), schedules=_repeated_dict(d, "schedules", Schedule)) @dataclass class ListSubscriptionsResponse: next_page_token: Optional[str] = None """A token that can be used as a `page_token` in subsequent requests to retrieve the next page of results. If this field is omitted, there are no subsequent subscriptions.""" subscriptions: Optional[List[Subscription]] = None def as_dict(self) -> dict: """Serializes the ListSubscriptionsResponse 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.subscriptions: body["subscriptions"] = [v.as_dict() for v in self.subscriptions] return body def as_shallow_dict(self) -> dict: """Serializes the ListSubscriptionsResponse 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.subscriptions: body["subscriptions"] = self.subscriptions return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListSubscriptionsResponse: """Deserializes the ListSubscriptionsResponse from a dictionary.""" return cls( next_page_token=d.get("next_page_token", None), subscriptions=_repeated_dict(d, "subscriptions", Subscription), ) @dataclass class MessageError: error: Optional[str] = None type: Optional[MessageErrorType] = None def as_dict(self) -> dict: """Serializes the MessageError into a dictionary suitable for use as a JSON request body.""" body = {} if self.error is not None: body["error"] = self.error if self.type is not None: body["type"] = self.type.value return body def as_shallow_dict(self) -> dict: """Serializes the MessageError into a shallow dictionary of its immediate attributes.""" body = {} if self.error is not None: body["error"] = self.error if self.type is not None: body["type"] = self.type return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> MessageError: """Deserializes the MessageError from a dictionary.""" return cls(error=d.get("error", None), type=_enum(d, "type", MessageErrorType)) class MessageErrorType(Enum): BLOCK_MULTIPLE_EXECUTIONS_EXCEPTION = "BLOCK_MULTIPLE_EXECUTIONS_EXCEPTION" CHAT_COMPLETION_CLIENT_EXCEPTION = "CHAT_COMPLETION_CLIENT_EXCEPTION" CHAT_COMPLETION_CLIENT_TIMEOUT_EXCEPTION = "CHAT_COMPLETION_CLIENT_TIMEOUT_EXCEPTION" CHAT_COMPLETION_NETWORK_EXCEPTION = "CHAT_COMPLETION_NETWORK_EXCEPTION" CONTENT_FILTER_EXCEPTION = "CONTENT_FILTER_EXCEPTION" CONTEXT_EXCEEDED_EXCEPTION = "CONTEXT_EXCEEDED_EXCEPTION" COULD_NOT_GET_DASHBOARD_SCHEMA_EXCEPTION = "COULD_NOT_GET_DASHBOARD_SCHEMA_EXCEPTION" COULD_NOT_GET_MODEL_DEPLOYMENTS_EXCEPTION = "COULD_NOT_GET_MODEL_DEPLOYMENTS_EXCEPTION" COULD_NOT_GET_UC_SCHEMA_EXCEPTION = "COULD_NOT_GET_UC_SCHEMA_EXCEPTION" DEPLOYMENT_NOT_FOUND_EXCEPTION = "DEPLOYMENT_NOT_FOUND_EXCEPTION" DESCRIBE_QUERY_INVALID_SQL_ERROR = "DESCRIBE_QUERY_INVALID_SQL_ERROR" DESCRIBE_QUERY_TIMEOUT = "DESCRIBE_QUERY_TIMEOUT" DESCRIBE_QUERY_UNEXPECTED_FAILURE = "DESCRIBE_QUERY_UNEXPECTED_FAILURE" EXCEEDED_MAX_TOKEN_LENGTH_EXCEPTION = "EXCEEDED_MAX_TOKEN_LENGTH_EXCEPTION" FUNCTIONS_NOT_AVAILABLE_EXCEPTION = "FUNCTIONS_NOT_AVAILABLE_EXCEPTION" FUNCTION_ARGUMENTS_INVALID_EXCEPTION = "FUNCTION_ARGUMENTS_INVALID_EXCEPTION" FUNCTION_ARGUMENTS_INVALID_JSON_EXCEPTION = "FUNCTION_ARGUMENTS_INVALID_JSON_EXCEPTION" FUNCTION_ARGUMENTS_INVALID_TYPE_EXCEPTION = "FUNCTION_ARGUMENTS_INVALID_TYPE_EXCEPTION" FUNCTION_CALL_MISSING_PARAMETER_EXCEPTION = "FUNCTION_CALL_MISSING_PARAMETER_EXCEPTION" GENERATED_SQL_QUERY_TOO_LONG_EXCEPTION = "GENERATED_SQL_QUERY_TOO_LONG_EXCEPTION" GENERIC_CHAT_COMPLETION_EXCEPTION = "GENERIC_CHAT_COMPLETION_EXCEPTION" GENERIC_CHAT_COMPLETION_SERVICE_EXCEPTION = "GENERIC_CHAT_COMPLETION_SERVICE_EXCEPTION" GENERIC_SQL_EXEC_API_CALL_EXCEPTION = "GENERIC_SQL_EXEC_API_CALL_EXCEPTION" ILLEGAL_PARAMETER_DEFINITION_EXCEPTION = "ILLEGAL_PARAMETER_DEFINITION_EXCEPTION" INTERNAL_CATALOG_ASSET_CREATION_FAILED_EXCEPTION = "INTERNAL_CATALOG_ASSET_CREATION_FAILED_EXCEPTION" INTERNAL_CATALOG_ASSET_CREATION_ONGOING_EXCEPTION = "INTERNAL_CATALOG_ASSET_CREATION_ONGOING_EXCEPTION" INTERNAL_CATALOG_ASSET_CREATION_UNSUPPORTED_EXCEPTION = "INTERNAL_CATALOG_ASSET_CREATION_UNSUPPORTED_EXCEPTION" INTERNAL_CATALOG_MISSING_UC_PATH_EXCEPTION = "INTERNAL_CATALOG_MISSING_UC_PATH_EXCEPTION" INTERNAL_CATALOG_PATH_OVERLAP_EXCEPTION = "INTERNAL_CATALOG_PATH_OVERLAP_EXCEPTION" INVALID_CERTIFIED_ANSWER_FUNCTION_EXCEPTION = "INVALID_CERTIFIED_ANSWER_FUNCTION_EXCEPTION" INVALID_CERTIFIED_ANSWER_IDENTIFIER_EXCEPTION = "INVALID_CERTIFIED_ANSWER_IDENTIFIER_EXCEPTION" INVALID_CHAT_COMPLETION_JSON_EXCEPTION = "INVALID_CHAT_COMPLETION_JSON_EXCEPTION" INVALID_COMPLETION_REQUEST_EXCEPTION = "INVALID_COMPLETION_REQUEST_EXCEPTION" INVALID_FUNCTION_CALL_EXCEPTION = "INVALID_FUNCTION_CALL_EXCEPTION" INVALID_SQL_MULTIPLE_DATASET_REFERENCES_EXCEPTION = "INVALID_SQL_MULTIPLE_DATASET_REFERENCES_EXCEPTION" INVALID_SQL_MULTIPLE_STATEMENTS_EXCEPTION = "INVALID_SQL_MULTIPLE_STATEMENTS_EXCEPTION" INVALID_SQL_UNKNOWN_TABLE_EXCEPTION = "INVALID_SQL_UNKNOWN_TABLE_EXCEPTION" INVALID_TABLE_IDENTIFIER_EXCEPTION = "INVALID_TABLE_IDENTIFIER_EXCEPTION" LOCAL_CONTEXT_EXCEEDED_EXCEPTION = "LOCAL_CONTEXT_EXCEEDED_EXCEPTION" MESSAGE_ATTACHMENT_TOO_LONG_ERROR = "MESSAGE_ATTACHMENT_TOO_LONG_ERROR" MESSAGE_CANCELLED_WHILE_EXECUTING_EXCEPTION = "MESSAGE_CANCELLED_WHILE_EXECUTING_EXCEPTION" MESSAGE_DELETED_WHILE_EXECUTING_EXCEPTION = "MESSAGE_DELETED_WHILE_EXECUTING_EXCEPTION" MESSAGE_UPDATED_WHILE_EXECUTING_EXCEPTION = "MESSAGE_UPDATED_WHILE_EXECUTING_EXCEPTION" MISSING_SQL_QUERY_EXCEPTION = "MISSING_SQL_QUERY_EXCEPTION" NO_DEPLOYMENTS_AVAILABLE_TO_WORKSPACE = "NO_DEPLOYMENTS_AVAILABLE_TO_WORKSPACE" NO_QUERY_TO_VISUALIZE_EXCEPTION = "NO_QUERY_TO_VISUALIZE_EXCEPTION" NO_TABLES_TO_QUERY_EXCEPTION = "NO_TABLES_TO_QUERY_EXCEPTION" RATE_LIMIT_EXCEEDED_GENERIC_EXCEPTION = "RATE_LIMIT_EXCEEDED_GENERIC_EXCEPTION" RATE_LIMIT_EXCEEDED_SPECIFIED_WAIT_EXCEPTION = "RATE_LIMIT_EXCEEDED_SPECIFIED_WAIT_EXCEPTION" REPLY_PROCESS_TIMEOUT_EXCEPTION = "REPLY_PROCESS_TIMEOUT_EXCEPTION" RETRYABLE_PROCESSING_EXCEPTION = "RETRYABLE_PROCESSING_EXCEPTION" SQL_EXECUTION_EXCEPTION = "SQL_EXECUTION_EXCEPTION" STOP_PROCESS_DUE_TO_AUTO_REGENERATE = "STOP_PROCESS_DUE_TO_AUTO_REGENERATE" TABLES_MISSING_EXCEPTION = "TABLES_MISSING_EXCEPTION" TOO_MANY_CERTIFIED_ANSWERS_EXCEPTION = "TOO_MANY_CERTIFIED_ANSWERS_EXCEPTION" TOO_MANY_TABLES_EXCEPTION = "TOO_MANY_TABLES_EXCEPTION" UNEXPECTED_REPLY_PROCESS_EXCEPTION = "UNEXPECTED_REPLY_PROCESS_EXCEPTION" UNKNOWN_AI_MODEL = "UNKNOWN_AI_MODEL" UNSUPPORTED_CONVERSATION_TYPE_EXCEPTION = "UNSUPPORTED_CONVERSATION_TYPE_EXCEPTION" WAREHOUSE_ACCESS_MISSING_EXCEPTION = "WAREHOUSE_ACCESS_MISSING_EXCEPTION" WAREHOUSE_NOT_FOUND_EXCEPTION = "WAREHOUSE_NOT_FOUND_EXCEPTION" class MessageStatus(Enum): """MessageStatus. The possible values are: * `FETCHING_METADATA`: Fetching metadata from the data sources. * `FILTERING_CONTEXT`: Running smart context step to determine relevant context. * `ASKING_AI`: Waiting for the LLM to respond to the user's question. * `PENDING_WAREHOUSE`: Waiting for warehouse before the SQL query can start executing. * `EXECUTING_QUERY`: Executing a generated SQL query. Get the SQL query result by calling [getMessageAttachmentQueryResult](:method:genie/getMessageAttachmentQueryResult) API. * `FAILED`: The response generation or query execution failed. See `error` field. * `COMPLETED`: Message processing is completed. Results are in the `attachments` field. Get the SQL query result by calling [getMessageAttachmentQueryResult](:method:genie/getMessageAttachmentQueryResult) API. * `SUBMITTED`: Message has been submitted. * `QUERY_RESULT_EXPIRED`: SQL result is not available anymore. The user needs to rerun the query. Rerun the SQL query result by calling [executeMessageAttachmentQuery](:method:genie/executeMessageAttachmentQuery) API. * `CANCELLED`: Message has been cancelled.""" ASKING_AI = "ASKING_AI" CANCELLED = "CANCELLED" COMPLETED = "COMPLETED" EXECUTING_QUERY = "EXECUTING_QUERY" FAILED = "FAILED" FETCHING_METADATA = "FETCHING_METADATA" FILTERING_CONTEXT = "FILTERING_CONTEXT" PENDING_WAREHOUSE = "PENDING_WAREHOUSE" QUERY_RESULT_EXPIRED = "QUERY_RESULT_EXPIRED" SUBMITTED = "SUBMITTED" @dataclass class PublishedDashboard: display_name: Optional[str] = None """The display name of the published dashboard.""" embed_credentials: Optional[bool] = None """Indicates whether credentials are embedded in the published dashboard.""" revision_create_time: Optional[str] = None """The timestamp of when the published dashboard was last revised.""" warehouse_id: Optional[str] = None """The warehouse ID used to run the published dashboard.""" def as_dict(self) -> dict: """Serializes the PublishedDashboard into a dictionary suitable for use as a JSON request body.""" body = {} if self.display_name is not None: body["display_name"] = self.display_name if self.embed_credentials is not None: body["embed_credentials"] = self.embed_credentials if self.revision_create_time is not None: body["revision_create_time"] = self.revision_create_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body def as_shallow_dict(self) -> dict: """Serializes the PublishedDashboard into a shallow dictionary of its immediate attributes.""" body = {} if self.display_name is not None: body["display_name"] = self.display_name if self.embed_credentials is not None: body["embed_credentials"] = self.embed_credentials if self.revision_create_time is not None: body["revision_create_time"] = self.revision_create_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> PublishedDashboard: """Deserializes the PublishedDashboard from a dictionary.""" return cls( display_name=d.get("display_name", None), embed_credentials=d.get("embed_credentials", None), revision_create_time=d.get("revision_create_time", None), warehouse_id=d.get("warehouse_id", None), ) @dataclass class QueryAttachmentParameter: keyword: Optional[str] = None sql_type: Optional[str] = None value: Optional[str] = None def as_dict(self) -> dict: """Serializes the QueryAttachmentParameter into a dictionary suitable for use as a JSON request body.""" body = {} if self.keyword is not None: body["keyword"] = self.keyword if self.sql_type is not None: body["sql_type"] = self.sql_type if self.value is not None: body["value"] = self.value return body def as_shallow_dict(self) -> dict: """Serializes the QueryAttachmentParameter into a shallow dictionary of its immediate attributes.""" body = {} if self.keyword is not None: body["keyword"] = self.keyword if self.sql_type is not None: body["sql_type"] = self.sql_type if self.value is not None: body["value"] = self.value return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> QueryAttachmentParameter: """Deserializes the QueryAttachmentParameter from a dictionary.""" return cls(keyword=d.get("keyword", None), sql_type=d.get("sql_type", None), value=d.get("value", None)) @dataclass class Result: is_truncated: Optional[bool] = None """If result is truncated""" row_count: Optional[int] = None """Row count of the result""" statement_id: Optional[str] = None """Statement Execution API statement id. Use [Get status, manifest, and result first chunk](:method:statementexecution/getstatement) to get the full result data.""" statement_id_signature: Optional[str] = None """JWT corresponding to the statement contained in this result""" def as_dict(self) -> dict: """Serializes the Result into a dictionary suitable for use as a JSON request body.""" body = {} if self.is_truncated is not None: body["is_truncated"] = self.is_truncated if self.row_count is not None: body["row_count"] = self.row_count if self.statement_id is not None: body["statement_id"] = self.statement_id if self.statement_id_signature is not None: body["statement_id_signature"] = self.statement_id_signature return body def as_shallow_dict(self) -> dict: """Serializes the Result into a shallow dictionary of its immediate attributes.""" body = {} if self.is_truncated is not None: body["is_truncated"] = self.is_truncated if self.row_count is not None: body["row_count"] = self.row_count if self.statement_id is not None: body["statement_id"] = self.statement_id if self.statement_id_signature is not None: body["statement_id_signature"] = self.statement_id_signature return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Result: """Deserializes the Result from a dictionary.""" return cls( is_truncated=d.get("is_truncated", None), row_count=d.get("row_count", None), statement_id=d.get("statement_id", None), statement_id_signature=d.get("statement_id_signature", None), ) @dataclass class Schedule: cron_schedule: CronSchedule """The cron expression describing the frequency of the periodic refresh for this schedule.""" create_time: Optional[str] = None """A timestamp indicating when the schedule was created.""" dashboard_id: Optional[str] = None """UUID identifying the dashboard to which the schedule belongs.""" display_name: Optional[str] = None """The display name for schedule.""" etag: Optional[str] = None """The etag for the schedule. Must be left empty on create, must be provided on updates to ensure that the schedule has not been modified since the last read, and can be optionally provided on delete.""" pause_status: Optional[SchedulePauseStatus] = None """The status indicates whether this schedule is paused or not.""" schedule_id: Optional[str] = None """UUID identifying the schedule.""" update_time: Optional[str] = None """A timestamp indicating when the schedule was last updated.""" warehouse_id: Optional[str] = None """The warehouse id to run the dashboard with for the schedule.""" def as_dict(self) -> dict: """Serializes the Schedule into a dictionary suitable for use as a JSON request body.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.cron_schedule: body["cron_schedule"] = self.cron_schedule.as_dict() if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.display_name is not None: body["display_name"] = self.display_name if self.etag is not None: body["etag"] = self.etag if self.pause_status is not None: body["pause_status"] = self.pause_status.value if self.schedule_id is not None: body["schedule_id"] = self.schedule_id if self.update_time is not None: body["update_time"] = self.update_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body def as_shallow_dict(self) -> dict: """Serializes the Schedule into a shallow dictionary of its immediate attributes.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.cron_schedule: body["cron_schedule"] = self.cron_schedule if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.display_name is not None: body["display_name"] = self.display_name if self.etag is not None: body["etag"] = self.etag if self.pause_status is not None: body["pause_status"] = self.pause_status if self.schedule_id is not None: body["schedule_id"] = self.schedule_id if self.update_time is not None: body["update_time"] = self.update_time if self.warehouse_id is not None: body["warehouse_id"] = self.warehouse_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Schedule: """Deserializes the Schedule from a dictionary.""" return cls( create_time=d.get("create_time", None), cron_schedule=_from_dict(d, "cron_schedule", CronSchedule), dashboard_id=d.get("dashboard_id", None), display_name=d.get("display_name", None), etag=d.get("etag", None), pause_status=_enum(d, "pause_status", SchedulePauseStatus), schedule_id=d.get("schedule_id", None), update_time=d.get("update_time", None), warehouse_id=d.get("warehouse_id", None), ) class SchedulePauseStatus(Enum): PAUSED = "PAUSED" UNPAUSED = "UNPAUSED" @dataclass class Subscriber: destination_subscriber: Optional[SubscriptionSubscriberDestination] = None """The destination to receive the subscription email. This parameter is mutually exclusive with `user_subscriber`.""" user_subscriber: Optional[SubscriptionSubscriberUser] = None """The user to receive the subscription email. This parameter is mutually exclusive with `destination_subscriber`.""" def as_dict(self) -> dict: """Serializes the Subscriber into a dictionary suitable for use as a JSON request body.""" body = {} if self.destination_subscriber: body["destination_subscriber"] = self.destination_subscriber.as_dict() if self.user_subscriber: body["user_subscriber"] = self.user_subscriber.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the Subscriber into a shallow dictionary of its immediate attributes.""" body = {} if self.destination_subscriber: body["destination_subscriber"] = self.destination_subscriber if self.user_subscriber: body["user_subscriber"] = self.user_subscriber return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Subscriber: """Deserializes the Subscriber from a dictionary.""" return cls( destination_subscriber=_from_dict(d, "destination_subscriber", SubscriptionSubscriberDestination), user_subscriber=_from_dict(d, "user_subscriber", SubscriptionSubscriberUser), ) @dataclass class Subscription: subscriber: Subscriber """Subscriber details for users and destinations to be added as subscribers to the schedule.""" create_time: Optional[str] = None """A timestamp indicating when the subscription was created.""" created_by_user_id: Optional[int] = None """UserId of the user who adds subscribers (users or notification destinations) to the dashboard's schedule.""" dashboard_id: Optional[str] = None """UUID identifying the dashboard to which the subscription belongs.""" etag: Optional[str] = None """The etag for the subscription. Must be left empty on create, can be optionally provided on delete to ensure that the subscription has not been deleted since the last read.""" schedule_id: Optional[str] = None """UUID identifying the schedule to which the subscription belongs.""" skip_notify: Optional[bool] = None """Controls whether notifications are sent to the subscriber for scheduled dashboard refreshes. If not defined, defaults to false in the backend to match the current behavior (refresh and notify)""" subscription_id: Optional[str] = None """UUID identifying the subscription.""" update_time: Optional[str] = None """A timestamp indicating when the subscription was last updated.""" def as_dict(self) -> dict: """Serializes the Subscription into a dictionary suitable for use as a JSON request body.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.created_by_user_id is not None: body["created_by_user_id"] = self.created_by_user_id if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.etag is not None: body["etag"] = self.etag if self.schedule_id is not None: body["schedule_id"] = self.schedule_id if self.skip_notify is not None: body["skip_notify"] = self.skip_notify if self.subscriber: body["subscriber"] = self.subscriber.as_dict() if self.subscription_id is not None: body["subscription_id"] = self.subscription_id if self.update_time is not None: body["update_time"] = self.update_time return body def as_shallow_dict(self) -> dict: """Serializes the Subscription into a shallow dictionary of its immediate attributes.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.created_by_user_id is not None: body["created_by_user_id"] = self.created_by_user_id if self.dashboard_id is not None: body["dashboard_id"] = self.dashboard_id if self.etag is not None: body["etag"] = self.etag if self.schedule_id is not None: body["schedule_id"] = self.schedule_id if self.skip_notify is not None: body["skip_notify"] = self.skip_notify if self.subscriber: body["subscriber"] = self.subscriber if self.subscription_id is not None: body["subscription_id"] = self.subscription_id if self.update_time is not None: body["update_time"] = self.update_time return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Subscription: """Deserializes the Subscription from a dictionary.""" return cls( create_time=d.get("create_time", None), created_by_user_id=d.get("created_by_user_id", None), dashboard_id=d.get("dashboard_id", None), etag=d.get("etag", None), schedule_id=d.get("schedule_id", None), skip_notify=d.get("skip_notify", None), subscriber=_from_dict(d, "subscriber", Subscriber), subscription_id=d.get("subscription_id", None), update_time=d.get("update_time", None), ) @dataclass class SubscriptionSubscriberDestination: destination_id: str """The canonical identifier of the destination to receive email notification.""" def as_dict(self) -> dict: """Serializes the SubscriptionSubscriberDestination into a dictionary suitable for use as a JSON request body.""" body = {} if self.destination_id is not None: body["destination_id"] = self.destination_id return body def as_shallow_dict(self) -> dict: """Serializes the SubscriptionSubscriberDestination into a shallow dictionary of its immediate attributes.""" body = {} if self.destination_id is not None: body["destination_id"] = self.destination_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> SubscriptionSubscriberDestination: """Deserializes the SubscriptionSubscriberDestination from a dictionary.""" return cls(destination_id=d.get("destination_id", None)) @dataclass class SubscriptionSubscriberUser: user_id: int """UserId of the subscriber.""" def as_dict(self) -> dict: """Serializes the SubscriptionSubscriberUser into a dictionary suitable for use as a JSON request body.""" body = {} if self.user_id is not None: body["user_id"] = self.user_id return body def as_shallow_dict(self) -> dict: """Serializes the SubscriptionSubscriberUser into a shallow dictionary of its immediate attributes.""" body = {} if self.user_id is not None: body["user_id"] = self.user_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> SubscriptionSubscriberUser: """Deserializes the SubscriptionSubscriberUser from a dictionary.""" return cls(user_id=d.get("user_id", None)) @dataclass class TextAttachment: content: Optional[str] = None """AI generated message""" id: Optional[str] = None purpose: Optional[TextAttachmentPurpose] = None """Purpose/intent of this text attachment""" def as_dict(self) -> dict: """Serializes the TextAttachment into a dictionary suitable for use as a JSON request body.""" body = {} if self.content is not None: body["content"] = self.content if self.id is not None: body["id"] = self.id if self.purpose is not None: body["purpose"] = self.purpose.value return body def as_shallow_dict(self) -> dict: """Serializes the TextAttachment into a shallow dictionary of its immediate attributes.""" body = {} if self.content is not None: body["content"] = self.content if self.id is not None: body["id"] = self.id if self.purpose is not None: body["purpose"] = self.purpose return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> TextAttachment: """Deserializes the TextAttachment from a dictionary.""" return cls( content=d.get("content", None), id=d.get("id", None), purpose=_enum(d, "purpose", TextAttachmentPurpose) ) class TextAttachmentPurpose(Enum): """Purpose/intent of a text attachment""" FOLLOW_UP_QUESTION = "FOLLOW_UP_QUESTION" @dataclass class TrashDashboardResponse: def as_dict(self) -> dict: """Serializes the TrashDashboardResponse into a dictionary suitable for use as a JSON request body.""" body = {} return body def as_shallow_dict(self) -> dict: """Serializes the TrashDashboardResponse into a shallow dictionary of its immediate attributes.""" body = {} return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> TrashDashboardResponse: """Deserializes the TrashDashboardResponse from a dictionary.""" return cls() @dataclass class UnpublishDashboardResponse: def as_dict(self) -> dict: """Serializes the UnpublishDashboardResponse into a dictionary suitable for use as a JSON request body.""" body = {} return body def as_shallow_dict(self) -> dict: """Serializes the UnpublishDashboardResponse into a shallow dictionary of its immediate attributes.""" body = {} return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> UnpublishDashboardResponse: """Deserializes the UnpublishDashboardResponse from a dictionary.""" return cls() class GenieAPI: """Genie provides a no-code experience for business users, powered by AI/BI. Analysts set up spaces that business users can use to ask questions using natural language. Genie uses data registered to Unity Catalog and requires at least CAN USE permission on a Pro or Serverless SQL warehouse. Also, Databricks Assistant must be enabled.""" def __init__(self, api_client): self._api = api_client def wait_get_message_genie_completed( self, conversation_id: str, message_id: str, space_id: str, timeout=timedelta(minutes=20), callback: Optional[Callable[[GenieMessage], None]] = None, ) -> GenieMessage: deadline = time.time() + timeout.total_seconds() target_states = (MessageStatus.COMPLETED,) failure_states = (MessageStatus.FAILED,) status_message = "polling..." attempt = 1 while time.time() < deadline: poll = self.get_message(conversation_id=conversation_id, message_id=message_id, space_id=space_id) status = poll.status status_message = f"current status: {status}" if status in target_states: return poll if callback: callback(poll) if status in failure_states: msg = f"failed to reach COMPLETED, got {status}: {status_message}" raise OperationFailed(msg) prefix = f"conversation_id={conversation_id}, message_id={message_id}, space_id={space_id}" sleep = attempt if sleep > 10: # sleep 10s max per attempt sleep = 10 _LOG.debug(f"{prefix}: ({status}) {status_message} (sleeping ~{sleep}s)") time.sleep(sleep + random.random()) attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") def create_message(self, space_id: str, conversation_id: str, content: str) -> Wait[GenieMessage]: """Create new message in a [conversation](:method:genie/startconversation). The AI response uses all previously created messages in the conversation to respond. :param space_id: str The ID associated with the Genie space where the conversation is started. :param conversation_id: str The ID associated with the conversation. :param content: str User message content. :returns: Long-running operation waiter for :class:`GenieMessage`. See :method:wait_get_message_genie_completed for more details. """ body = {} if content is not None: body["content"] = content 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 op_response = self._api.do( "POST", f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages", body=body, headers=headers, ) return Wait( self.wait_get_message_genie_completed, response=GenieMessage.from_dict(op_response), conversation_id=conversation_id, message_id=op_response["message_id"], space_id=space_id, ) def create_message_and_wait( self, space_id: str, conversation_id: str, content: str, timeout=timedelta(minutes=20) ) -> GenieMessage: return self.create_message(content=content, conversation_id=conversation_id, space_id=space_id).result( timeout=timeout ) def create_space( self, warehouse_id: str, serialized_space: str, *, description: Optional[str] = None, parent_path: Optional[str] = None, title: Optional[str] = None, ) -> GenieSpace: """Creates a Genie space from a serialized payload. :param warehouse_id: str Warehouse to associate with the new space :param serialized_space: str The contents of the Genie Space in serialized string form. Use the [Get Genie Space](:method:genie/getspace) API to retrieve an example response, which includes the `serialized_space` field. This field provides the structure of the JSON string that represents the space's layout and components. :param description: str (optional) Optional description :param parent_path: str (optional) Parent folder path where the space will be registered :param title: str (optional) Optional title override :returns: :class:`GenieSpace` """ body = {} if description is not None: body["description"] = description if parent_path is not None: body["parent_path"] = parent_path if serialized_space is not None: body["serialized_space"] = serialized_space if title is not None: body["title"] = title if warehouse_id is not None: body["warehouse_id"] = warehouse_id 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.0/genie/spaces", body=body, headers=headers) return GenieSpace.from_dict(res) def delete_conversation(self, space_id: str, conversation_id: str): """Delete a conversation. :param space_id: str The ID associated with the Genie space where the conversation is located. :param conversation_id: str The ID of the conversation to delete. """ 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/genie/spaces/{space_id}/conversations/{conversation_id}", headers=headers) def delete_conversation_message(self, space_id: str, conversation_id: str, message_id: str): """Delete a conversation message. :param space_id: str The ID associated with the Genie space where the message is located. :param conversation_id: str The ID associated with the conversation. :param message_id: str The ID associated with the message to delete. """ 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}", headers=headers, ) def execute_message_attachment_query( self, space_id: str, conversation_id: str, message_id: str, attachment_id: str ) -> GenieGetMessageQueryResultResponse: """Execute the SQL for a message query attachment. Use this API when the query attachment has expired and needs to be re-executed. :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :param attachment_id: str Attachment ID :returns: :class:`GenieGetMessageQueryResultResponse` """ 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( "POST", f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/execute-query", headers=headers, ) return GenieGetMessageQueryResultResponse.from_dict(res) def execute_message_query( self, space_id: str, conversation_id: str, message_id: str ) -> GenieGetMessageQueryResultResponse: """DEPRECATED: Use [Execute Message Attachment Query](:method:genie/executemessageattachmentquery) instead. :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :returns: :class:`GenieGetMessageQueryResultResponse` """ 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( "POST", f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/execute-query", headers=headers, ) return GenieGetMessageQueryResultResponse.from_dict(res) def generate_download_full_query_result( self, space_id: str, conversation_id: str, message_id: str, attachment_id: str ) -> GenieGenerateDownloadFullQueryResultResponse: """Initiates a new SQL execution and returns a `download_id` and `download_id_signature` that you can use to track the progress of the download. The query result is stored in an external link and can be retrieved using the [Get Download Full Query Result](:method:genie/getdownloadfullqueryresult) API. Both `download_id` and `download_id_signature` must be provided when calling the Get endpoint. ---- ### **Warning: Databricks strongly recommends that you protect the URLs that are returned by the `EXTERNAL_LINKS` disposition.** When you use the `EXTERNAL_LINKS` disposition, a short-lived, URL is generated, which can be used to download the results directly from . As a short-lived is embedded in this URL, you should protect the URL. Because URLs are already generated with embedded temporary s, you must not set an `Authorization` header in the download requests. See [Execute Statement](:method:statementexecution/executestatement) for more details. ---- :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :param attachment_id: str Attachment ID :returns: :class:`GenieGenerateDownloadFullQueryResultResponse` """ 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( "POST", f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/downloads", headers=headers, ) return GenieGenerateDownloadFullQueryResultResponse.from_dict(res) def get_download_full_query_result( self, space_id: str, conversation_id: str, message_id: str, attachment_id: str, download_id: str, download_id_signature: str, ) -> GenieGetDownloadFullQueryResultResponse: """After [Generating a Full Query Result Download](:method:genie/generatedownloadfullqueryresult) and successfully receiving a `download_id` and `download_id_signature`, use this API to poll the download progress. Both `download_id` and `download_id_signature` are required to call this endpoint. When the download is complete, the API returns the result in the `EXTERNAL_LINKS` disposition, containing one or more external links to the query result files. ---- ### **Warning: Databricks strongly recommends that you protect the URLs that are returned by the `EXTERNAL_LINKS` disposition.** When you use the `EXTERNAL_LINKS` disposition, a short-lived, URL is generated, which can be used to download the results directly from . As a short-lived is embedded in this URL, you should protect the URL. Because URLs are already generated with embedded temporary s, you must not set an `Authorization` header in the download requests. See [Execute Statement](:method:statementexecution/executestatement) for more details. ---- :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :param attachment_id: str Attachment ID :param download_id: str Download ID. This ID is provided by the [Generate Download endpoint](:method:genie/generateDownloadFullQueryResult) :param download_id_signature: str JWT signature for the download_id to ensure secure access to query results :returns: :class:`GenieGetDownloadFullQueryResultResponse` """ query = {} if download_id_signature is not None: query["download_id_signature"] = download_id_signature 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/downloads/{download_id}", query=query, headers=headers, ) return GenieGetDownloadFullQueryResultResponse.from_dict(res) def get_message(self, space_id: str, conversation_id: str, message_id: str) -> GenieMessage: """Get message from conversation. :param space_id: str The ID associated with the Genie space where the target conversation is located. :param conversation_id: str The ID associated with the target conversation. :param message_id: str The ID associated with the target message from the identified conversation. :returns: :class:`GenieMessage` """ 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}", headers=headers, ) return GenieMessage.from_dict(res) def get_message_attachment_query_result( self, space_id: str, conversation_id: str, message_id: str, attachment_id: str ) -> GenieGetMessageQueryResultResponse: """Get the result of SQL query if the message has a query attachment. This is only available if a message has a query attachment and the message status is `EXECUTING_QUERY` OR `COMPLETED`. :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :param attachment_id: str Attachment ID :returns: :class:`GenieGetMessageQueryResultResponse` """ 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/query-result", headers=headers, ) return GenieGetMessageQueryResultResponse.from_dict(res) def get_message_query_result( self, space_id: str, conversation_id: str, message_id: str ) -> GenieGetMessageQueryResultResponse: """DEPRECATED: Use [Get Message Attachment Query Result](:method:genie/getmessageattachmentqueryresult) instead. :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :returns: :class:`GenieGetMessageQueryResultResponse` """ 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/query-result", headers=headers, ) return GenieGetMessageQueryResultResponse.from_dict(res) def get_message_query_result_by_attachment( self, space_id: str, conversation_id: str, message_id: str, attachment_id: str ) -> GenieGetMessageQueryResultResponse: """DEPRECATED: Use [Get Message Attachment Query Result](:method:genie/getmessageattachmentqueryresult) instead. :param space_id: str Genie space ID :param conversation_id: str Conversation ID :param message_id: str Message ID :param attachment_id: str Attachment ID :returns: :class:`GenieGetMessageQueryResultResponse` """ 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/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/query-result/{attachment_id}", headers=headers, ) return GenieGetMessageQueryResultResponse.from_dict(res) def get_space(self, space_id: str, *, include_serialized_space: Optional[bool] = None) -> GenieSpace: """Get details of a Genie Space. :param space_id: str The ID associated with the Genie space :param include_serialized_space: bool (optional) Whether to include the serialized space export in the response. Requires at least CAN EDIT permission on the space. :returns: :class:`GenieSpace` """ query = {} if include_serialized_space is not None: query["include_serialized_space"] = include_serialized_space 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/genie/spaces/{space_id}", query=query, headers=headers) return GenieSpace.from_dict(res) def list_conversation_messages( self, space_id: str, conversation_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> GenieListConversationMessagesResponse: """List messages in a conversation :param space_id: str The ID associated with the Genie space where the conversation is located :param conversation_id: str The ID of the conversation to list messages from :param page_size: int (optional) Maximum number of messages to return per page :param page_token: str (optional) Token to get the next page of results :returns: :class:`GenieListConversationMessagesResponse` """ query = {} if page_size is not None: query["page_size"] = page_size 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.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages", query=query, headers=headers, ) return GenieListConversationMessagesResponse.from_dict(res) def list_conversations( self, space_id: str, *, include_all: Optional[bool] = None, page_size: Optional[int] = None, page_token: Optional[str] = None, ) -> GenieListConversationsResponse: """Get a list of conversations in a Genie Space. :param space_id: str The ID of the Genie space to retrieve conversations from. :param include_all: bool (optional) Include all conversations in the space across all users. Requires at least CAN MANAGE permission on the space. :param page_size: int (optional) Maximum number of conversations to return per page :param page_token: str (optional) Token to get the next page of results :returns: :class:`GenieListConversationsResponse` """ query = {} if include_all is not None: query["include_all"] = include_all if page_size is not None: query["page_size"] = page_size 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.0/genie/spaces/{space_id}/conversations", query=query, headers=headers) return GenieListConversationsResponse.from_dict(res) def list_spaces( self, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> GenieListSpacesResponse: """Get list of Genie Spaces. :param page_size: int (optional) Maximum number of spaces to return per page :param page_token: str (optional) Pagination token for getting the next page of results :returns: :class:`GenieListSpacesResponse` """ query = {} if page_size is not None: query["page_size"] = page_size 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", "/api/2.0/genie/spaces", query=query, headers=headers) return GenieListSpacesResponse.from_dict(res) def send_message_feedback(self, space_id: str, conversation_id: str, message_id: str, rating: GenieFeedbackRating): """Send feedback for a message. :param space_id: str The ID associated with the Genie space where the message is located. :param conversation_id: str The ID associated with the conversation. :param message_id: str The ID associated with the message to provide feedback for. :param rating: :class:`GenieFeedbackRating` The rating (POSITIVE, NEGATIVE, or NONE). """ body = {} if rating is not None: body["rating"] = rating.value 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 self._api.do( "POST", f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/feedback", body=body, headers=headers, ) def start_conversation(self, space_id: str, content: str) -> Wait[GenieMessage]: """Start a new conversation. :param space_id: str The ID associated with the Genie space where you want to start a conversation. :param content: str The text of the message that starts the conversation. :returns: Long-running operation waiter for :class:`GenieMessage`. See :method:wait_get_message_genie_completed for more details. """ body = {} if content is not None: body["content"] = content 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 op_response = self._api.do( "POST", f"/api/2.0/genie/spaces/{space_id}/start-conversation", body=body, headers=headers ) return Wait( self.wait_get_message_genie_completed, response=GenieStartConversationResponse.from_dict(op_response), conversation_id=op_response["conversation_id"], message_id=op_response["message_id"], space_id=space_id, ) def start_conversation_and_wait(self, space_id: str, content: str, timeout=timedelta(minutes=20)) -> GenieMessage: return self.start_conversation(content=content, space_id=space_id).result(timeout=timeout) def trash_space(self, space_id: str): """Move a Genie Space to the trash. :param space_id: str The ID associated with the Genie space to be sent to the trash. """ 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/genie/spaces/{space_id}", headers=headers) def update_space( self, space_id: str, *, description: Optional[str] = None, serialized_space: Optional[str] = None, title: Optional[str] = None, warehouse_id: Optional[str] = None, ) -> GenieSpace: """Updates a Genie space with a serialized payload. :param space_id: str Genie space ID :param description: str (optional) Optional description :param serialized_space: str (optional) The contents of the Genie Space in serialized string form (full replacement). Use the [Get Genie Space](:method:genie/getspace) API to retrieve an example response, which includes the `serialized_space` field. This field provides the structure of the JSON string that represents the space's layout and components. :param title: str (optional) Optional title override :param warehouse_id: str (optional) Optional warehouse override :returns: :class:`GenieSpace` """ body = {} if description is not None: body["description"] = description if serialized_space is not None: body["serialized_space"] = serialized_space if title is not None: body["title"] = title if warehouse_id is not None: body["warehouse_id"] = warehouse_id 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.0/genie/spaces/{space_id}", body=body, headers=headers) return GenieSpace.from_dict(res) class LakeviewAPI: """These APIs provide specific management operations for Lakeview dashboards. Generic resource management can be done with Workspace API (import, export, get-status, list, delete).""" def __init__(self, api_client): self._api = api_client def create( self, dashboard: Dashboard, *, dataset_catalog: Optional[str] = None, dataset_schema: Optional[str] = None ) -> Dashboard: """Create a draft dashboard. :param dashboard: :class:`Dashboard` :param dataset_catalog: str (optional) Sets the default catalog for all datasets in this dashboard. Does not impact table references that use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s existing configuration. :param dataset_schema: str (optional) Sets the default schema for all datasets in this dashboard. Does not impact table references that use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing configuration. :returns: :class:`Dashboard` """ body = dashboard.as_dict() query = {} if dataset_catalog is not None: query["dataset_catalog"] = dataset_catalog if dataset_schema is not None: query["dataset_schema"] = dataset_schema 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.0/lakeview/dashboards", query=query, body=body, headers=headers) return Dashboard.from_dict(res) def create_schedule(self, dashboard_id: str, schedule: Schedule) -> Schedule: """Create dashboard schedule. :param dashboard_id: str UUID identifying the dashboard to which the schedule belongs. :param schedule: :class:`Schedule` The schedule to create. A dashboard is limited to 10 schedules. :returns: :class:`Schedule` """ body = schedule.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/lakeview/dashboards/{dashboard_id}/schedules", body=body, headers=headers) return Schedule.from_dict(res) def create_subscription(self, dashboard_id: str, schedule_id: str, subscription: Subscription) -> Subscription: """Create schedule subscription. :param dashboard_id: str UUID identifying the dashboard to which the subscription belongs. :param schedule_id: str UUID identifying the schedule to which the subscription belongs. :param subscription: :class:`Subscription` The subscription to create. A schedule is limited to 100 subscriptions. :returns: :class:`Subscription` """ body = subscription.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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}/subscriptions", body=body, headers=headers, ) return Subscription.from_dict(res) def delete_schedule(self, dashboard_id: str, schedule_id: str, *, etag: Optional[str] = None): """Delete dashboard schedule. :param dashboard_id: str UUID identifying the dashboard to which the schedule belongs. :param schedule_id: str UUID identifying the schedule. :param etag: str (optional) The etag for the schedule. Optionally, it can be provided to verify that the schedule has not been modified from its last retrieval. """ query = {} if etag is not None: query["etag"] = etag 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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}", query=query, headers=headers, ) def delete_subscription( self, dashboard_id: str, schedule_id: str, subscription_id: str, *, etag: Optional[str] = None ): """Delete schedule subscription. :param dashboard_id: str UUID identifying the dashboard which the subscription belongs. :param schedule_id: str UUID identifying the schedule which the subscription belongs. :param subscription_id: str UUID identifying the subscription. :param etag: str (optional) The etag for the subscription. Can be optionally provided to ensure that the subscription has not been modified since the last read. """ query = {} if etag is not None: query["etag"] = etag 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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}/subscriptions/{subscription_id}", query=query, headers=headers, ) def get(self, dashboard_id: str) -> Dashboard: """Get a draft dashboard. :param dashboard_id: str UUID identifying the dashboard. :returns: :class:`Dashboard` """ 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/lakeview/dashboards/{dashboard_id}", headers=headers) return Dashboard.from_dict(res) def get_published(self, dashboard_id: str) -> PublishedDashboard: """Get the current published dashboard. :param dashboard_id: str UUID identifying the published dashboard. :returns: :class:`PublishedDashboard` """ 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/lakeview/dashboards/{dashboard_id}/published", headers=headers) return PublishedDashboard.from_dict(res) def get_schedule(self, dashboard_id: str, schedule_id: str) -> Schedule: """Get dashboard schedule. :param dashboard_id: str UUID identifying the dashboard to which the schedule belongs. :param schedule_id: str UUID identifying the schedule. :returns: :class:`Schedule` """ 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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}", headers=headers ) return Schedule.from_dict(res) def get_subscription(self, dashboard_id: str, schedule_id: str, subscription_id: str) -> Subscription: """Get schedule subscription. :param dashboard_id: str UUID identifying the dashboard which the subscription belongs. :param schedule_id: str UUID identifying the schedule which the subscription belongs. :param subscription_id: str UUID identifying the subscription. :returns: :class:`Subscription` """ 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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}/subscriptions/{subscription_id}", headers=headers, ) return Subscription.from_dict(res) def list( self, *, page_size: Optional[int] = None, page_token: Optional[str] = None, show_trashed: Optional[bool] = None, view: Optional[DashboardView] = None, ) -> Iterator[Dashboard]: """List dashboards. :param page_size: int (optional) The number of dashboards to return per page. :param page_token: str (optional) A page token, received from a previous `ListDashboards` call. This token can be used to retrieve the subsequent page. :param show_trashed: bool (optional) The flag to include dashboards located in the trash. If unspecified, only active dashboards will be returned. :param view: :class:`DashboardView` (optional) `DASHBOARD_VIEW_BASIC`only includes summary metadata from the dashboard. :returns: Iterator over :class:`Dashboard` """ query = {} if page_size is not None: query["page_size"] = page_size if page_token is not None: query["page_token"] = page_token if show_trashed is not None: query["show_trashed"] = show_trashed if view is not None: query["view"] = view.value 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", "/api/2.0/lakeview/dashboards", query=query, headers=headers) if "dashboards" in json: for v in json["dashboards"]: yield Dashboard.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_schedules( self, dashboard_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> Iterator[Schedule]: """List dashboard schedules. :param dashboard_id: str UUID identifying the dashboard to which the schedules belongs. :param page_size: int (optional) The number of schedules to return per page. :param page_token: str (optional) A page token, received from a previous `ListSchedules` call. Use this to retrieve the subsequent page. :returns: Iterator over :class:`Schedule` """ query = {} if page_size is not None: query["page_size"] = page_size 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/lakeview/dashboards/{dashboard_id}/schedules", query=query, headers=headers ) if "schedules" in json: for v in json["schedules"]: yield Schedule.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_subscriptions( self, dashboard_id: str, schedule_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> Iterator[Subscription]: """List schedule subscriptions. :param dashboard_id: str UUID identifying the dashboard which the subscriptions belongs. :param schedule_id: str UUID identifying the schedule which the subscriptions belongs. :param page_size: int (optional) The number of subscriptions to return per page. :param page_token: str (optional) A page token, received from a previous `ListSubscriptions` call. Use this to retrieve the subsequent page. :returns: Iterator over :class:`Subscription` """ query = {} if page_size is not None: query["page_size"] = page_size 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/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}/subscriptions", query=query, headers=headers, ) if "subscriptions" in json: for v in json["subscriptions"]: yield Subscription.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 migrate( self, source_dashboard_id: str, *, display_name: Optional[str] = None, parent_path: Optional[str] = None, update_parameter_syntax: Optional[bool] = None, ) -> Dashboard: """Migrates a classic SQL dashboard to Lakeview. :param source_dashboard_id: str UUID of the dashboard to be migrated. :param display_name: str (optional) Display name for the new Lakeview dashboard. :param parent_path: str (optional) The workspace path of the folder to contain the migrated Lakeview dashboard. :param update_parameter_syntax: bool (optional) Flag to indicate if mustache parameter syntax ({{ param }}) should be auto-updated to named syntax (:param) when converting datasets in the dashboard. :returns: :class:`Dashboard` """ body = {} if display_name is not None: body["display_name"] = display_name if parent_path is not None: body["parent_path"] = parent_path if source_dashboard_id is not None: body["source_dashboard_id"] = source_dashboard_id if update_parameter_syntax is not None: body["update_parameter_syntax"] = update_parameter_syntax 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.0/lakeview/dashboards/migrate", body=body, headers=headers) return Dashboard.from_dict(res) def publish( self, dashboard_id: str, *, embed_credentials: Optional[bool] = None, warehouse_id: Optional[str] = None ) -> PublishedDashboard: """Publish the current draft dashboard. :param dashboard_id: str UUID identifying the dashboard to be published. :param embed_credentials: bool (optional) Flag to indicate if the publisher's credentials should be embedded in the published dashboard. These embedded credentials will be used to execute the published dashboard's queries. :param warehouse_id: str (optional) The ID of the warehouse that can be used to override the warehouse which was set in the draft. :returns: :class:`PublishedDashboard` """ body = {} if embed_credentials is not None: body["embed_credentials"] = embed_credentials if warehouse_id is not None: body["warehouse_id"] = warehouse_id 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/lakeview/dashboards/{dashboard_id}/published", body=body, headers=headers) return PublishedDashboard.from_dict(res) def trash(self, dashboard_id: str): """Trash a dashboard. :param dashboard_id: str UUID identifying the dashboard. """ 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/lakeview/dashboards/{dashboard_id}", headers=headers) def unpublish(self, dashboard_id: str): """Unpublish the dashboard. :param dashboard_id: str UUID identifying the published dashboard. """ 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/lakeview/dashboards/{dashboard_id}/published", headers=headers) def update( self, dashboard_id: str, dashboard: Dashboard, *, dataset_catalog: Optional[str] = None, dataset_schema: Optional[str] = None, ) -> Dashboard: """Update a draft dashboard. :param dashboard_id: str UUID identifying the dashboard. :param dashboard: :class:`Dashboard` :param dataset_catalog: str (optional) Sets the default catalog for all datasets in this dashboard. Does not impact table references that use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s existing configuration. :param dataset_schema: str (optional) Sets the default schema for all datasets in this dashboard. Does not impact table references that use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing configuration. :returns: :class:`Dashboard` """ body = dashboard.as_dict() query = {} if dataset_catalog is not None: query["dataset_catalog"] = dataset_catalog if dataset_schema is not None: query["dataset_schema"] = dataset_schema 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.0/lakeview/dashboards/{dashboard_id}", query=query, body=body, headers=headers ) return Dashboard.from_dict(res) def update_schedule(self, dashboard_id: str, schedule_id: str, schedule: Schedule) -> Schedule: """Update dashboard schedule. :param dashboard_id: str UUID identifying the dashboard to which the schedule belongs. :param schedule_id: str UUID identifying the schedule. :param schedule: :class:`Schedule` The schedule to update. :returns: :class:`Schedule` """ body = schedule.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( "PUT", f"/api/2.0/lakeview/dashboards/{dashboard_id}/schedules/{schedule_id}", body=body, headers=headers ) return Schedule.from_dict(res) class LakeviewEmbeddedAPI: """Token-based Lakeview APIs for embedding dashboards in external applications.""" def __init__(self, api_client): self._api = api_client def get_published_dashboard_token_info( self, dashboard_id: str, *, external_value: Optional[str] = None, external_viewer_id: Optional[str] = None ) -> GetPublishedDashboardTokenInfoResponse: """Get a required authorization details and scopes of a published dashboard to mint an OAuth token. :param dashboard_id: str UUID identifying the published dashboard. :param external_value: str (optional) Provided external value to be included in the custom claim. :param external_viewer_id: str (optional) Provided external viewer id to be included in the custom claim. :returns: :class:`GetPublishedDashboardTokenInfoResponse` """ query = {} if external_value is not None: query["external_value"] = external_value if external_viewer_id is not None: query["external_viewer_id"] = external_viewer_id 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/lakeview/dashboards/{dashboard_id}/published/tokeninfo", query=query, headers=headers ) return GetPublishedDashboardTokenInfoResponse.from_dict(res)