@@ -65,6 +65,8 @@ class SupersetClient:
@property
# [DEF:headers:Function]
# @PURPOSE: Возвращает базовые HTTP-заголовки, используемые сетевым клиентом.
# @PRE: APIClient is initialized and authenticated.
# @POST: Returns a dictionary of HTTP headers.
def headers ( self ) - > dict :
with belief_scope ( " headers " ) :
return self . network . headers
@@ -75,6 +77,8 @@ class SupersetClient:
# [DEF:get_dashboards:Function]
# @PURPOSE: Получает полный список дашбордов, автоматически обрабатывая пагинацию.
# @PARAM: query (Optional[Dict]) - Дополнительные параметры запроса для API.
# @PRE: Client is authenticated.
# @POST: Returns a tuple with total count and list of dashboards.
# @RETURN: Tuple[int, List[Dict]] - Кортеж (общее количество, список дашбордов).
def get_dashboards ( self , query : Optional [ Dict ] = None ) - > Tuple [ int , List [ Dict ] ] :
with belief_scope ( " get_dashboards " ) :
@@ -94,6 +98,8 @@ class SupersetClient:
# [DEF:get_dashboards_summary:Function]
# @PURPOSE: Fetches dashboard metadata optimized for the grid.
# @PRE: Client is authenticated.
# @POST: Returns a list of dashboard metadata summaries.
# @RETURN: List[Dict]
def get_dashboards_summary ( self ) - > List [ Dict ] :
with belief_scope ( " SupersetClient.get_dashboards_summary " ) :
@@ -117,6 +123,8 @@ class SupersetClient:
# [DEF:export_dashboard:Function]
# @PURPOSE: Экспортирует дашборд в виде ZIP-архива.
# @PARAM: dashboard_id (int) - ID дашборда для экспорта.
# @PRE: dashboard_id must exist in Superset.
# @POST: Returns ZIP content and filename.
# @RETURN: Tuple[bytes, str] - Бинарное содержимое ZIP-архива и имя файла.
def export_dashboard ( self , dashboard_id : int ) - > Tuple [ bytes , str ] :
with belief_scope ( " export_dashboard " ) :
@@ -140,6 +148,8 @@ class SupersetClient:
# @PARAM: file_name (Union[str, Path]) - Путь к ZIP-архиву.
# @PARAM: dash_id (Optional[int]) - ID дашборда для удаления при с б о е .
# @PARAM: dash_slug (Optional[str]) - Slug дашборда для поиска ID.
# @PRE: file_name must be a valid ZIP dashboard export.
# @POST: Dashboard is imported or re-imported after deletion.
# @RETURN: Dict - Ответ API в случае успеха.
def import_dashboard ( self , file_name : Union [ str , Path ] , dash_id : Optional [ int ] = None , dash_slug : Optional [ str ] = None ) - > Dict :
with belief_scope ( " import_dashboard " ) :
@@ -165,6 +175,8 @@ class SupersetClient:
# [DEF:delete_dashboard:Function]
# @PURPOSE: Удаляет дашборд по е г о ID или slug.
# @PARAM: dashboard_id (Union[int, str]) - ID или slug дашборда.
# @PRE: dashboard_id must exist.
# @POST: Dashboard is removed from Superset.
def delete_dashboard ( self , dashboard_id : Union [ int , str ] ) - > None :
with belief_scope ( " delete_dashboard " ) :
app_logger . info ( " [delete_dashboard][Enter] Deleting dashboard %s . " , dashboard_id )
@@ -183,6 +195,8 @@ class SupersetClient:
# [DEF:get_datasets:Function]
# @PURPOSE: Получает полный список датасетов, автоматически обрабатывая пагинацию.
# @PARAM: query (Optional[Dict]) - Дополнительные параметры запроса.
# @PRE: Client is authenticated.
# @POST: Returns total count and list of datasets.
# @RETURN: Tuple[int, List[Dict]] - Кортеж (общее количество, список датасетов).
def get_datasets ( self , query : Optional [ Dict ] = None ) - > Tuple [ int , List [ Dict ] ] :
with belief_scope ( " get_datasets " ) :
@@ -201,6 +215,8 @@ class SupersetClient:
# [DEF:get_dataset:Function]
# @PURPOSE: Получает информацию о конкретном датасете по е г о ID.
# @PARAM: dataset_id (int) - ID датасета.
# @PRE: dataset_id must exist.
# @POST: Returns dataset details.
# @RETURN: Dict - Информация о датасете.
def get_dataset ( self , dataset_id : int ) - > Dict :
with belief_scope ( " SupersetClient.get_dataset " , f " id= { dataset_id } " ) :
@@ -215,6 +231,8 @@ class SupersetClient:
# @PURPOSE: Обновляет данные датасета по е г о ID.
# @PARAM: dataset_id (int) - ID датасета.
# @PARAM: data (Dict) - Данные для обновления.
# @PRE: dataset_id must exist.
# @POST: Dataset is updated in Superset.
# @RETURN: Dict - Ответ API.
def update_dataset ( self , dataset_id : int , data : Dict ) - > Dict :
with belief_scope ( " SupersetClient.update_dataset " , f " id= { dataset_id } " ) :
@@ -237,6 +255,8 @@ class SupersetClient:
# [DEF:get_databases:Function]
# @PURPOSE: Получает полный список баз данных.
# @PARAM: query (Optional[Dict]) - Дополнительные параметры запроса.
# @PRE: Client is authenticated.
# @POST: Returns total count and list of databases.
# @RETURN: Tuple[int, List[Dict]] - Кортеж (общее количество, список баз данных).
def get_databases ( self , query : Optional [ Dict ] = None ) - > Tuple [ int , List [ Dict ] ] :
with belief_scope ( " get_databases " ) :
@@ -256,6 +276,8 @@ class SupersetClient:
# [DEF:get_database:Function]
# @PURPOSE: Получает информацию о конкретной базе данных по её ID.
# @PARAM: database_id (int) - ID базы данных.
# @PRE: database_id must exist.
# @POST: Returns database details.
# @RETURN: Dict - Информация о базе данных.
def get_database ( self , database_id : int ) - > Dict :
with belief_scope ( " get_database " ) :
@@ -268,6 +290,8 @@ class SupersetClient:
# [DEF:get_databases_summary:Function]
# @PURPOSE: Fetch a summary of databases including uuid, name, and engine.
# @PRE: Client is authenticated.
# @POST: Returns list of database summaries.
# @RETURN: List[Dict] - Summary of databases.
def get_databases_summary ( self ) - > List [ Dict ] :
with belief_scope ( " SupersetClient.get_databases_summary " ) :
@@ -286,6 +310,8 @@ class SupersetClient:
# [DEF:get_database_by_uuid:Function]
# @PURPOSE: Find a database by its UUID.
# @PARAM: db_uuid (str) - The UUID of the database.
# @PRE: db_uuid must be a valid UUID string.
# @POST: Returns database info or None.
# @RETURN: Optional[Dict] - Database info if found, else None.
def get_database_by_uuid ( self , db_uuid : str ) - > Optional [ Dict ] :
with belief_scope ( " SupersetClient.get_database_by_uuid " , f " uuid= { db_uuid } " ) :
@@ -301,6 +327,9 @@ class SupersetClient:
# [SECTION: HELPERS]
# [DEF:_resolve_target_id_for_delete:Function]
# @PURPOSE: Resolves a dashboard ID from either an ID or a slug.
# @PRE: Either dash_id or dash_slug should be provided.
# @POST: Returns the resolved ID or None.
def _resolve_target_id_for_delete ( self , dash_id : Optional [ int ] , dash_slug : Optional [ str ] ) - > Optional [ int ] :
with belief_scope ( " _resolve_target_id_for_delete " ) :
if dash_id is not None :
@@ -319,6 +348,9 @@ class SupersetClient:
# [/DEF:_resolve_target_id_for_delete:Function]
# [DEF:_do_import:Function]
# @PURPOSE: Performs the actual multipart upload for import.
# @PRE: file_name must be a path to an existing ZIP file.
# @POST: Returns the API response from the upload.
def _do_import ( self , file_name : Union [ str , Path ] ) - > Dict :
with belief_scope ( " _do_import " ) :
app_logger . debug ( f " [_do_import][State] Uploading file: { file_name } " )
@@ -336,6 +368,9 @@ class SupersetClient:
# [/DEF:_do_import:Function]
# [DEF:_validate_export_response:Function]
# @PURPOSE: Validates that the export response is a non-empty ZIP archive.
# @PRE: response must be a valid requests.Response object.
# @POST: Raises SupersetAPIError if validation fails.
def _validate_export_response ( self , response : Response , dashboard_id : int ) - > None :
with belief_scope ( " _validate_export_response " ) :
content_type = response . headers . get ( " Content-Type " , " " )
@@ -346,6 +381,9 @@ class SupersetClient:
# [/DEF:_validate_export_response:Function]
# [DEF:_resolve_export_filename:Function]
# @PURPOSE: Determines the filename for an exported dashboard.
# @PRE: response must contain Content-Disposition header or dashboard_id must be provided.
# @POST: Returns a sanitized filename string.
def _resolve_export_filename ( self , response : Response , dashboard_id : int ) - > str :
with belief_scope ( " _resolve_export_filename " ) :
filename = get_filename_from_headers ( dict ( response . headers ) )
@@ -358,6 +396,9 @@ class SupersetClient:
# [/DEF:_resolve_export_filename:Function]
# [DEF:_validate_query_params:Function]
# @PURPOSE: Ensures query parameters have default page and page_size.
# @PRE: query can be None or a dictionary.
# @POST: Returns a dictionary with at least page and page_size.
def _validate_query_params ( self , query : Optional [ Dict ] ) - > Dict :
with belief_scope ( " _validate_query_params " ) :
base_query = { " page " : 0 , " page_size " : 1000 }
@@ -365,6 +406,9 @@ class SupersetClient:
# [/DEF:_validate_query_params:Function]
# [DEF:_fetch_total_object_count:Function]
# @PURPOSE: Fetches the total number of items for a given endpoint.
# @PRE: endpoint must be a valid Superset API path.
# @POST: Returns the total count as an integer.
def _fetch_total_object_count ( self , endpoint : str ) - > int :
with belief_scope ( " _fetch_total_object_count " ) :
return self . network . fetch_paginated_count (
@@ -375,12 +419,18 @@ class SupersetClient:
# [/DEF:_fetch_total_object_count:Function]
# [DEF:_fetch_all_pages:Function]
# @PURPOSE: Iterates through all pages to collect all data items.
# @PRE: pagination_options must contain base_query, total_count, and results_field.
# @POST: Returns a combined list of all items.
def _fetch_all_pages ( self , endpoint : str , pagination_options : Dict ) - > List [ Dict ] :
with belief_scope ( " _fetch_all_pages " ) :
return self . network . fetch_paginated_data ( endpoint = endpoint , pagination_options = pagination_options )
# [/DEF:_fetch_all_pages:Function]
# [DEF:_validate_import_file:Function]
# @PURPOSE: Validates that the file to be imported is a valid ZIP with metadata.yaml.
# @PRE: zip_path must be a path to a file.
# @POST: Raises error if file is missing, not a ZIP, or missing metadata.
def _validate_import_file ( self , zip_path : Union [ str , Path ] ) - > None :
with belief_scope ( " _validate_import_file " ) :
path = Path ( zip_path )