semantics

This commit is contained in:
2026-03-27 21:27:31 +03:00
parent 7c85552132
commit 2ed66bfebc
182 changed files with 21186 additions and 10254 deletions

View File

@@ -4,7 +4,8 @@
# @SEMANTICS: superset, api, client, rest, http, dashboard, dataset, import, export
# @PURPOSE: Предоставляет высокоуровневый клиент для взаимодействия с Superset REST API, инкапсулируя логику запросов, обработку ошибок и пагинацию.
# @LAYER: Core
# @RELATION: [DEPENDS_ON] ->[APIClient.__init__]
# @RELATION: DEPENDS_ON -> [ConfigModels]
# @RELATION: DEPENDS_ON -> [ConnectionContracts]
#
# @INVARIANT: All network operations must use the internal APIClient instance.
# @PUBLIC_API: SupersetClient
@@ -30,16 +31,17 @@ app_logger = cast(Any, app_logger)
# [DEF:SupersetClient:Class]
# @COMPLEXITY: 3
# @PURPOSE: Класс-обёртка над Superset REST API, предоставляющий методы для работы с дашбордами и датасетами.
# @RELATION: [DEPENDS_ON] ->[APIClient]
# @RELATION: DEPENDS_ON -> [ConfigModels]
# @RELATION: DEPENDS_ON -> [ConnectionContracts]
class SupersetClient:
# [DEF:SupersetClient.__init__:Function]
# [DEF:SupersetClientInit:Function]
# @COMPLEXITY: 3
# @PURPOSE: Инициализирует клиент, проверяет конфигурацию и создает сетевой клиент.
# @PRE: `env` должен быть валидным объектом Environment.
# @POST: Атрибуты `env` и `network` созданы и готовы к работе.
# @DATA_CONTRACT: Input[Environment] -> self.network[APIClient]
# @RELATION: [DEPENDS_ON] ->[Environment]
# @RELATION: [DEPENDS_ON] ->[APIClient.__init__]
# @RELATION: DEPENDS_ON -> [Environment]
# @RELATION: DEPENDS_ON -> [ConnectionContracts]
def __init__(self, env: Environment):
with belief_scope("__init__"):
app_logger.info(
@@ -62,23 +64,23 @@ class SupersetClient:
self.delete_before_reimport: bool = False
app_logger.info("[SupersetClient.__init__][Exit] SupersetClient initialized.")
# [/DEF:SupersetClient.__init__:Function]
# [/DEF:SupersetClientInit:Function]
# [DEF:SupersetClient.authenticate:Function]
# [DEF:SupersetClientAuthenticate:Function]
# @COMPLEXITY: 3
# @PURPOSE: Authenticates the client using the configured credentials.
# @PRE: self.network must be initialized with valid auth configuration.
# @POST: Client is authenticated and tokens are stored.
# @DATA_CONTRACT: None -> Output[Dict[str, str]]
# @RELATION: [CALLS] ->[APIClient.authenticate]
# @RELATION: CALLS -> [ConnectionContracts]
def authenticate(self) -> Dict[str, str]:
with belief_scope("SupersetClient.authenticate"):
return self.network.authenticate()
# [/DEF:SupersetClient.authenticate:Function]
# [/DEF:SupersetClientAuthenticate:Function]
@property
# [DEF:SupersetClient.headers:Function]
# [DEF:SupersetClientHeaders:Function]
# @COMPLEXITY: 1
# @PURPOSE: Возвращает базовые HTTP-заголовки, используемые сетевым клиентом.
# @PRE: APIClient is initialized and authenticated.
@@ -87,17 +89,17 @@ class SupersetClient:
with belief_scope("headers"):
return self.network.headers
# [/DEF:SupersetClient.headers:Function]
# [/DEF:SupersetClientHeaders:Function]
# [SECTION: DASHBOARD OPERATIONS]
# [DEF:SupersetClient.get_dashboards:Function]
# [DEF:SupersetClientGetDashboards:Function]
# @COMPLEXITY: 3
# @PURPOSE: Получает полный список дашбордов, автоматически обрабатывая пагинацию.
# @PRE: Client is authenticated.
# @POST: Returns a tuple with total count and list of dashboards.
# @DATA_CONTRACT: Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[_fetch_all_pages]
# @RELATION: CALLS -> [SupersetClientFetchAllPages]
def get_dashboards(self, query: Optional[Dict] = None) -> Tuple[int, List[Dict]]:
with belief_scope("get_dashboards"):
app_logger.info("[get_dashboards][Enter] Fetching dashboards.")
@@ -127,15 +129,15 @@ class SupersetClient:
app_logger.info("[get_dashboards][Exit] Found %d dashboards.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClient.get_dashboards:Function]
# [/DEF:SupersetClientGetDashboards:Function]
# [DEF:SupersetClient.get_dashboards_page:Function]
# [DEF:SupersetClientGetDashboardsPage:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches a single dashboards page from Superset without iterating all pages.
# @PRE: Client is authenticated.
# @POST: Returns total count and one page of dashboards.
# @DATA_CONTRACT: Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_dashboards_page(
self, query: Optional[Dict] = None
) -> Tuple[int, List[Dict]]:
@@ -167,15 +169,15 @@ class SupersetClient:
total_count = response_json.get("count", len(result))
return total_count, result
# [/DEF:SupersetClient.get_dashboards_page:Function]
# [/DEF:SupersetClientGetDashboardsPage:Function]
# [DEF:SupersetClient.get_dashboards_summary:Function]
# [DEF:SupersetClientGetDashboardsSummary:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches dashboard metadata optimized for the grid.
# @PRE: Client is authenticated.
# @POST: Returns a list of dashboard metadata summaries.
# @DATA_CONTRACT: None -> Output[List[Dict]]
# @RELATION: [CALLS] ->[SupersetClient.get_dashboards]
# @RELATION: CALLS -> [SupersetClientGetDashboards]
def get_dashboards_summary(self, require_slug: bool = False) -> List[Dict]:
with belief_scope("SupersetClient.get_dashboards_summary"):
# Rely on list endpoint default projection to stay compatible
@@ -257,15 +259,15 @@ class SupersetClient:
)
return result
# [/DEF:SupersetClient.get_dashboards_summary:Function]
# [/DEF:SupersetClientGetDashboardsSummary:Function]
# [DEF:SupersetClient.get_dashboards_summary_page:Function]
# [DEF:SupersetClientGetDashboardsSummaryPage:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches one page of dashboard metadata optimized for the grid.
# @PRE: page >= 1 and page_size > 0.
# @POST: Returns mapped summaries and total dashboard count.
# @DATA_CONTRACT: Input[page: int, page_size: int] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[SupersetClient.get_dashboards_page]
# @RELATION: CALLS -> [SupersetClientGetDashboardsPage]
def get_dashboards_summary_page(
self,
page: int,
@@ -333,9 +335,9 @@ class SupersetClient:
return total_count, result
# [/DEF:SupersetClient.get_dashboards_summary_page:Function]
# [/DEF:SupersetClientGetDashboardsSummaryPage:Function]
# [DEF:SupersetClient._extract_owner_labels:Function]
# [DEF:SupersetClientExtractOwnerLabels:Function]
# @COMPLEXITY: 1
# @PURPOSE: Normalize dashboard owners payload to stable display labels.
# @PRE: owners payload can be scalar, object or list.
@@ -362,9 +364,9 @@ class SupersetClient:
normalized.append(label)
return normalized
# [/DEF:SupersetClient._extract_owner_labels:Function]
# [/DEF:SupersetClientExtractOwnerLabels:Function]
# [DEF:SupersetClient._extract_user_display:Function]
# [DEF:SupersetClientExtractUserDisplay:Function]
# @COMPLEXITY: 1
# @PURPOSE: Normalize user payload to a stable display name.
# @PRE: user payload can be string, dict or None.
@@ -396,9 +398,9 @@ class SupersetClient:
return email
return None
# [/DEF:SupersetClient._extract_user_display:Function]
# [/DEF:SupersetClientExtractUserDisplay:Function]
# [DEF:SupersetClient._sanitize_user_text:Function]
# [DEF:SupersetClientSanitizeUserText:Function]
# @COMPLEXITY: 1
# @PURPOSE: Convert scalar value to non-empty user-facing text.
# @PRE: value can be any scalar type.
@@ -411,15 +413,15 @@ class SupersetClient:
return None
return normalized
# [/DEF:SupersetClient._sanitize_user_text:Function]
# [/DEF:SupersetClientSanitizeUserText:Function]
# [DEF:SupersetClient.get_dashboard:Function]
# [DEF:SupersetClientGetDashboard:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches a single dashboard by ID or slug.
# @PRE: Client is authenticated and dashboard_ref exists.
# @POST: Returns dashboard payload from Superset API.
# @DATA_CONTRACT: Input[dashboard_ref: Union[int, str]] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_dashboard(self, dashboard_ref: Union[int, str]) -> Dict:
with belief_scope("SupersetClient.get_dashboard", f"ref={dashboard_ref}"):
response = self.network.request(
@@ -427,15 +429,15 @@ class SupersetClient:
)
return cast(Dict, response)
# [/DEF:SupersetClient.get_dashboard:Function]
# [/DEF:SupersetClientGetDashboard:Function]
# [DEF:SupersetClient.get_dashboard_permalink_state:Function]
# [DEF:SupersetClientGetDashboardPermalinkState:Function]
# @COMPLEXITY: 2
# @PURPOSE: Fetches stored dashboard permalink state by permalink key.
# @PRE: Client is authenticated and permalink key exists.
# @POST: Returns dashboard permalink state payload from Superset API.
# @DATA_CONTRACT: Input[permalink_key: str] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_dashboard_permalink_state(self, permalink_key: str) -> Dict:
with belief_scope(
"SupersetClient.get_dashboard_permalink_state", f"key={permalink_key}"
@@ -445,15 +447,15 @@ class SupersetClient:
)
return cast(Dict, response)
# [/DEF:SupersetClient.get_dashboard_permalink_state:Function]
# [/DEF:SupersetClientGetDashboardPermalinkState:Function]
# [DEF:SupersetClient.get_native_filter_state:Function]
# [DEF:SupersetClientGetNativeFilterState:Function]
# @COMPLEXITY: 2
# @PURPOSE: Fetches stored native filter state by filter state key.
# @PRE: Client is authenticated and filter_state_key exists.
# @POST: Returns native filter state payload from Superset API.
# @DATA_CONTRACT: Input[dashboard_id: Union[int, str], filter_state_key: str] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_native_filter_state(
self, dashboard_id: Union[int, str], filter_state_key: str
) -> Dict:
@@ -467,15 +469,15 @@ class SupersetClient:
)
return cast(Dict, response)
# [/DEF:SupersetClient.get_native_filter_state:Function]
# [/DEF:SupersetClientGetNativeFilterState:Function]
# [DEF:SupersetClient.extract_native_filters_from_permalink:Function]
# [DEF:SupersetClientExtractNativeFiltersFromPermalink:Function]
# @COMPLEXITY: 3
# @PURPOSE: Extract native filters dataMask from a permalink key.
# @PRE: Client is authenticated and permalink_key exists.
# @POST: Returns extracted dataMask with filter states.
# @DATA_CONTRACT: Input[permalink_key: str] -> Output[Dict]
# @RELATION: [CALLS] ->[SupersetClient.get_dashboard_permalink_state]
# @RELATION: CALLS -> [SupersetClientGetDashboardPermalinkState]
def extract_native_filters_from_permalink(self, permalink_key: str) -> Dict:
with belief_scope(
"SupersetClient.extract_native_filters_from_permalink",
@@ -507,15 +509,15 @@ class SupersetClient:
"permalink_key": permalink_key,
}
# [/DEF:SupersetClient.extract_native_filters_from_permalink:Function]
# [/DEF:SupersetClientExtractNativeFiltersFromPermalink:Function]
# [DEF:SupersetClient.extract_native_filters_from_key:Function]
# [DEF:SupersetClientExtractNativeFiltersFromKey:Function]
# @COMPLEXITY: 3
# @PURPOSE: Extract native filters from a native_filters_key URL parameter.
# @PRE: Client is authenticated, dashboard_id and filter_state_key exist.
# @POST: Returns extracted filter state with extraFormData.
# @DATA_CONTRACT: Input[dashboard_id: Union[int, str], filter_state_key: str] -> Output[Dict]
# @RELATION: [CALLS] ->[SupersetClient.get_native_filter_state]
# @RELATION: CALLS -> [SupersetClientGetNativeFilterState]
def extract_native_filters_from_key(
self, dashboard_id: Union[int, str], filter_state_key: str
) -> Dict:
@@ -576,16 +578,16 @@ class SupersetClient:
"filter_state_key": filter_state_key,
}
# [/DEF:SupersetClient.extract_native_filters_from_key:Function]
# [/DEF:SupersetClientExtractNativeFiltersFromKey:Function]
# [DEF:SupersetClient.parse_dashboard_url_for_filters:Function]
# [DEF:SupersetClientParseDashboardUrlForFilters:Function]
# @COMPLEXITY: 3
# @PURPOSE: Parse a Superset dashboard URL and extract native filter state if present.
# @PRE: url must be a valid Superset dashboard URL with optional permalink or native_filters_key.
# @POST: Returns extracted filter state or empty dict if no filters found.
# @DATA_CONTRACT: Input[url: str] -> Output[Dict]
# @RELATION: [CALLS] ->[SupersetClient.extract_native_filters_from_permalink]
# @RELATION: [CALLS] ->[SupersetClient.extract_native_filters_from_key]
# @RELATION: CALLS -> [SupersetClientExtractNativeFiltersFromPermalink]
# @RELATION: CALLS -> [SupersetClientExtractNativeFiltersFromKey]
def parse_dashboard_url_for_filters(self, url: str) -> Dict:
with belief_scope(
"SupersetClient.parse_dashboard_url_for_filters", f"url={url}"
@@ -686,30 +688,30 @@ class SupersetClient:
return result
# [/DEF:SupersetClient.parse_dashboard_url_for_filters:Function]
# [/DEF:SupersetClientParseDashboardUrlForFilters:Function]
# [DEF:SupersetClient.get_chart:Function]
# [DEF:SupersetClientGetChart:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches a single chart by ID.
# @PRE: Client is authenticated and chart_id exists.
# @POST: Returns chart payload from Superset API.
# @DATA_CONTRACT: Input[chart_id: int] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_chart(self, chart_id: int) -> Dict:
with belief_scope("SupersetClient.get_chart", f"id={chart_id}"):
response = self.network.request(method="GET", endpoint=f"/chart/{chart_id}")
return cast(Dict, response)
# [/DEF:SupersetClient.get_chart:Function]
# [/DEF:SupersetClientGetChart:Function]
# [DEF:SupersetClient.get_dashboard_detail:Function]
# [DEF:SupersetClientGetDashboardDetail:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches detailed dashboard information including related charts and datasets.
# @PRE: Client is authenticated and dashboard reference exists.
# @POST: Returns dashboard metadata with charts and datasets lists.
# @DATA_CONTRACT: Input[dashboard_ref: Union[int, str]] -> Output[Dict]
# @RELATION: [CALLS] ->[SupersetClient.get_dashboard]
# @RELATION: [CALLS] ->[SupersetClient.get_chart]
# @RELATION: CALLS -> [SupersetClientGetDashboard]
# @RELATION: CALLS -> [SupersetClientGetChart]
def get_dashboard_detail(self, dashboard_ref: Union[int, str]) -> Dict:
with belief_scope(
"SupersetClient.get_dashboard_detail", f"ref={dashboard_ref}"
@@ -988,15 +990,15 @@ class SupersetClient:
"dataset_count": len(unique_datasets),
}
# [/DEF:SupersetClient.get_dashboard_detail:Function]
# [/DEF:SupersetClientGetDashboardDetail:Function]
# [DEF:SupersetClient.get_charts:Function]
# [DEF:SupersetClientGetCharts:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches all charts with pagination support.
# @PRE: Client is authenticated.
# @POST: Returns total count and charts list.
# @DATA_CONTRACT: Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[_fetch_all_pages]
# @RELATION: CALLS -> [SupersetClientFetchAllPages]
def get_charts(self, query: Optional[Dict] = None) -> Tuple[int, List[Dict]]:
with belief_scope("get_charts"):
validated_query = self._validate_query_params(query or {})
@@ -1012,9 +1014,9 @@ class SupersetClient:
)
return len(paginated_data), paginated_data
# [/DEF:SupersetClient.get_charts:Function]
# [/DEF:SupersetClientGetCharts:Function]
# [DEF:SupersetClient._extract_chart_ids_from_layout:Function]
# [DEF:SupersetClientExtractChartIdsFromLayout:Function]
# @COMPLEXITY: 1
# @PURPOSE: Traverses dashboard layout metadata and extracts chart IDs from common keys.
# @PRE: payload can be dict/list/scalar.
@@ -1048,16 +1050,16 @@ class SupersetClient:
walk(payload)
return found
# [/DEF:SupersetClient._extract_chart_ids_from_layout:Function]
# [/DEF:SupersetClientExtractChartIdsFromLayout:Function]
# [DEF:export_dashboard:Function]
# [DEF:SupersetClientExportDashboard:Function]
# @COMPLEXITY: 3
# @PURPOSE: Экспортирует дашборд в виде ZIP-архива.
# @PRE: dashboard_id must exist in Superset.
# @POST: Returns ZIP content and filename.
# @DATA_CONTRACT: Input[dashboard_id: int] -> Output[Tuple[bytes, str]]
# @SIDE_EFFECT: Performs network I/O to download archive.
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def export_dashboard(self, dashboard_id: int) -> Tuple[bytes, str]:
with belief_scope("export_dashboard"):
app_logger.info(
@@ -1080,17 +1082,17 @@ class SupersetClient:
)
return response.content, filename
# [/DEF:export_dashboard:Function]
# [/DEF:SupersetClientExportDashboard:Function]
# [DEF:import_dashboard:Function]
# [DEF:SupersetClientImportDashboard:Function]
# @COMPLEXITY: 3
# @PURPOSE: Импортирует дашборд из ZIP-файла.
# @PRE: file_name must be a valid ZIP dashboard export.
# @POST: Dashboard is imported or re-imported after deletion.
# @DATA_CONTRACT: Input[file_name: Union[str, Path]] -> Output[Dict]
# @SIDE_EFFECT: Performs network I/O to upload archive.
# @RELATION: [CALLS] ->[SupersetClient._do_import]
# @RELATION: [CALLS] ->[delete_dashboard]
# @RELATION: CALLS -> [SupersetClientDoImport]
# @RELATION: CALLS -> [ConnectionContracts]
def import_dashboard(
self,
file_name: Union[str, Path],
@@ -1127,15 +1129,15 @@ class SupersetClient:
)
return self._do_import(file_path)
# [/DEF:import_dashboard:Function]
# [/DEF:SupersetClientImportDashboard:Function]
# [DEF:delete_dashboard:Function]
# [DEF:SupersetClientDeleteDashboard:Function]
# @COMPLEXITY: 3
# @PURPOSE: Удаляет дашборд по его ID или slug.
# @PRE: dashboard_id must exist.
# @POST: Dashboard is removed from Superset.
# @SIDE_EFFECT: Deletes resource from upstream Superset environment.
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def delete_dashboard(self, dashboard_id: Union[int, str]) -> None:
with belief_scope("delete_dashboard"):
app_logger.info(
@@ -1156,15 +1158,15 @@ class SupersetClient:
response,
)
# [/DEF:delete_dashboard:Function]
# [/DEF:SupersetClientDeleteDashboard:Function]
# [DEF:SupersetClient.get_datasets:Function]
# [DEF:SupersetClientGetDatasets:Function]
# @COMPLEXITY: 3
# @PURPOSE: Получает полный список датасетов, автоматически обрабатывая пагинацию.
# @PRE: Client is authenticated.
# @POST: Returns total count and list of datasets.
# @DATA_CONTRACT: Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[_fetch_all_pages]
# @RELATION: CALLS -> [SupersetClientFetchAllPages]
def get_datasets(self, query: Optional[Dict] = None) -> Tuple[int, List[Dict]]:
with belief_scope("get_datasets"):
app_logger.info("[get_datasets][Enter] Fetching datasets.")
@@ -1181,15 +1183,15 @@ class SupersetClient:
app_logger.info("[get_datasets][Exit] Found %d datasets.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClient.get_datasets:Function]
# [/DEF:SupersetClientGetDatasets:Function]
# [DEF:SupersetClient.get_datasets_summary:Function]
# [DEF:SupersetClientGetDatasetsSummary:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches dataset metadata optimized for the Dataset Hub grid.
# @PRE: Client is authenticated.
# @POST: Returns a list of dataset metadata summaries.
# @RETURN: List[Dict]
# @RELATION: [CALLS] ->[SupersetClient.get_datasets]
# @RELATION: CALLS -> [SupersetClientGetDatasets]
def get_datasets_summary(self) -> List[Dict]:
with belief_scope("SupersetClient.get_datasets_summary"):
query = {"columns": ["id", "table_name", "schema", "database"]}
@@ -1210,17 +1212,17 @@ class SupersetClient:
)
return result
# [/DEF:SupersetClient.get_datasets_summary:Function]
# [/DEF:SupersetClientGetDatasetsSummary:Function]
# [DEF:get_dataset_detail:Function]
# [DEF:SupersetClientGetDatasetDetail:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches detailed dataset information including columns and linked dashboards
# @PRE: Client is authenticated and dataset_id exists.
# @POST: Returns detailed dataset info with columns and linked dashboards.
# @PARAM: dataset_id (int) - The dataset ID to fetch details for.
# @RETURN: Dict - Dataset details with columns and linked_dashboards.
# @RELATION: [CALLS] ->[SupersetClient.get_dataset]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [SupersetClientGetDataset]
# @RELATION: CALLS -> [ConnectionContracts]
def get_dataset_detail(self, dataset_id: int) -> Dict:
with belief_scope("SupersetClient.get_dataset_detail", f"id={dataset_id}"):
@@ -1339,15 +1341,15 @@ class SupersetClient:
)
return result
# [/DEF:get_dataset_detail:Function]
# [/DEF:SupersetClientGetDatasetDetail:Function]
# [DEF:SupersetClient.get_dataset:Function]
# [DEF:SupersetClientGetDataset:Function]
# @COMPLEXITY: 3
# @PURPOSE: Получает информацию о конкретном датасете по его ID.
# @PRE: dataset_id must exist.
# @POST: Returns dataset details.
# @DATA_CONTRACT: Input[dataset_id: int] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_dataset(self, dataset_id: int) -> Dict:
with belief_scope("SupersetClient.get_dataset", f"id={dataset_id}"):
app_logger.info("[get_dataset][Enter] Fetching dataset %s.", dataset_id)
@@ -1358,19 +1360,19 @@ class SupersetClient:
app_logger.info("[get_dataset][Exit] Got dataset %s.", dataset_id)
return response
# [/DEF:SupersetClient.get_dataset:Function]
# [/DEF:SupersetClientGetDataset:Function]
# [DEF:SupersetClient.compile_dataset_preview:Function]
# [DEF:SupersetClientCompileDatasetPreview:Function]
# @COMPLEXITY: 4
# @PURPOSE: Compile dataset preview SQL through the strongest supported Superset preview endpoint family and return normalized SQL output.
# @PRE: dataset_id must be valid and template_params/effective_filters must represent the current preview session inputs.
# @POST: Returns normalized compiled SQL plus raw upstream response, preferring legacy form_data transport with explicit fallback to chart-data.
# @DATA_CONTRACT: Input[dataset_id:int, template_params:Dict, effective_filters:List[Dict]] -> Output[Dict[str, Any]]
# @RELATION: [CALLS] ->[SupersetClient.get_dataset]
# @RELATION: [CALLS] ->[SupersetClient.build_dataset_preview_query_context]
# @RELATION: [CALLS] ->[SupersetClient.build_dataset_preview_legacy_form_data]
# @RELATION: [CALLS] ->[request]
# @RELATION: [CALLS] ->[_extract_compiled_sql_from_preview_response]
# @RELATION: CALLS -> [SupersetClientGetDataset]
# @RELATION: CALLS -> [SupersetClientBuildDatasetPreviewQueryContext]
# @RELATION: CALLS -> [SupersetClientBuildDatasetPreviewLegacyFormData]
# @RELATION: CALLS -> [ConnectionContracts]
# @RELATION: CALLS -> [SupersetClientExtractCompiledSqlFromPreviewResponse]
# @SIDE_EFFECT: Performs upstream dataset lookup and preview network I/O against Superset.
def compile_dataset_preview(
self,
@@ -1535,15 +1537,15 @@ class SupersetClient:
f"(attempts={strategy_attempts!r})"
)
# [/DEF:SupersetClient.compile_dataset_preview:Function]
# [/DEF:SupersetClientCompileDatasetPreview:Function]
# [DEF:SupersetClient.build_dataset_preview_legacy_form_data:Function]
# [DEF:SupersetClientBuildDatasetPreviewLegacyFormData:Function]
# @COMPLEXITY: 4
# @PURPOSE: Build browser-style legacy form_data payload for Superset preview endpoints inferred from observed deployment traffic.
# @PRE: dataset_record should come from Superset dataset detail when possible.
# @POST: Returns one serialized-ready form_data structure preserving native filter clauses in legacy transport fields.
# @DATA_CONTRACT: Input[dataset_id:int,dataset_record:Dict,template_params:Dict,effective_filters:List[Dict]] -> Output[Dict[str, Any]]
# @RELATION: [CALLS] ->[SupersetClient.build_dataset_preview_query_context]
# @RELATION: CALLS -> [SupersetClientBuildDatasetPreviewQueryContext]
# @SIDE_EFFECT: Emits reasoning diagnostics describing the inferred legacy payload shape.
def build_dataset_preview_legacy_form_data(
self,
@@ -1611,15 +1613,15 @@ class SupersetClient:
)
return legacy_form_data
# [/DEF:SupersetClient.build_dataset_preview_legacy_form_data:Function]
# [/DEF:SupersetClientBuildDatasetPreviewLegacyFormData:Function]
# [DEF:SupersetClient.build_dataset_preview_query_context:Function]
# [DEF:SupersetClientBuildDatasetPreviewQueryContext:Function]
# @COMPLEXITY: 4
# @PURPOSE: Build a reduced-scope chart-data query context for deterministic dataset preview compilation.
# @PRE: dataset_record should come from Superset dataset detail when possible.
# @POST: Returns an explicit chart-data payload based on current session inputs and dataset metadata.
# @DATA_CONTRACT: Input[dataset_id:int,dataset_record:Dict,template_params:Dict,effective_filters:List[Dict]] -> Output[Dict[str, Any]]
# @RELATION: [CALLS] ->[_normalize_effective_filters_for_query_context]
# @RELATION: CALLS -> [SupersetClientNormalizeEffectiveFiltersForQueryContext]
# @SIDE_EFFECT: Emits reasoning and reflection logs for deterministic preview payload construction.
def build_dataset_preview_query_context(
self,
@@ -1740,14 +1742,14 @@ class SupersetClient:
)
return payload
# [/DEF:SupersetClient.build_dataset_preview_query_context:Function]
# [/DEF:SupersetClientBuildDatasetPreviewQueryContext:Function]
# [DEF:_normalize_effective_filters_for_query_context:Function]
# [DEF:SupersetClientNormalizeEffectiveFiltersForQueryContext:Function]
# @COMPLEXITY: 3
# @PURPOSE: Convert execution mappings into Superset chart-data filter objects.
# @PRE: effective_filters may contain mapping metadata and arbitrary scalar/list values.
# @POST: Returns only valid filter dictionaries suitable for the chart-data query payload.
# @RELATION: [DEPENDS_ON] ->[FilterStateModels]
# @RELATION: DEPENDS_ON -> [CoreContracts]
def _normalize_effective_filters_for_query_context(
self,
effective_filters: List[Dict[str, Any]],
@@ -1850,14 +1852,14 @@ class SupersetClient:
"diagnostics": diagnostics,
}
# [/DEF:_normalize_effective_filters_for_query_context:Function]
# [/DEF:SupersetClientNormalizeEffectiveFiltersForQueryContext:Function]
# [DEF:_extract_compiled_sql_from_preview_response:Function]
# [DEF:SupersetClientExtractCompiledSqlFromPreviewResponse:Function]
# @COMPLEXITY: 3
# @PURPOSE: Normalize compiled SQL from either chart-data or legacy form_data preview responses.
# @PRE: response must be the decoded preview response body from a supported Superset endpoint.
# @POST: Returns compiled SQL and raw response or raises SupersetAPIError when the endpoint does not expose query text.
# @RELATION: [DEPENDS_ON] ->[SupersetAPIError]
# @RELATION: DEPENDS_ON -> [ConnectionContracts]
def _extract_compiled_sql_from_preview_response(
self, response: Any
) -> Dict[str, Any]:
@@ -1930,16 +1932,16 @@ class SupersetClient:
f"(diagnostics={response_diagnostics!r})"
)
# [/DEF:_extract_compiled_sql_from_preview_response:Function]
# [/DEF:SupersetClientExtractCompiledSqlFromPreviewResponse:Function]
# [DEF:SupersetClient.update_dataset:Function]
# [DEF:SupersetClientUpdateDataset:Function]
# @COMPLEXITY: 3
# @PURPOSE: Обновляет данные датасета по его ID.
# @PRE: dataset_id must exist.
# @POST: Dataset is updated in Superset.
# @DATA_CONTRACT: Input[dataset_id: int, data: Dict] -> Output[Dict]
# @SIDE_EFFECT: Modifies resource in upstream Superset environment.
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def update_dataset(self, dataset_id: int, data: Dict) -> Dict:
with belief_scope("SupersetClient.update_dataset", f"id={dataset_id}"):
app_logger.info("[update_dataset][Enter] Updating dataset %s.", dataset_id)
@@ -1953,15 +1955,15 @@ class SupersetClient:
app_logger.info("[update_dataset][Exit] Updated dataset %s.", dataset_id)
return response
# [/DEF:SupersetClient.update_dataset:Function]
# [/DEF:SupersetClientUpdateDataset:Function]
# [DEF:SupersetClient.get_databases:Function]
# [DEF:SupersetClientGetDatabases:Function]
# @COMPLEXITY: 3
# @PURPOSE: Получает полный список баз данных.
# @PRE: Client is authenticated.
# @POST: Returns total count and list of databases.
# @DATA_CONTRACT: Input[query: Optional[Dict]] -> Output[Tuple[int, List[Dict]]]
# @RELATION: [CALLS] ->[_fetch_all_pages]
# @RELATION: CALLS -> [SupersetClientFetchAllPages]
def get_databases(self, query: Optional[Dict] = None) -> Tuple[int, List[Dict]]:
with belief_scope("get_databases"):
app_logger.info("[get_databases][Enter] Fetching databases.")
@@ -1980,15 +1982,15 @@ class SupersetClient:
app_logger.info("[get_databases][Exit] Found %d databases.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClient.get_databases:Function]
# [/DEF:SupersetClientGetDatabases:Function]
# [DEF:get_database:Function]
# [DEF:SupersetClientGetDatabase:Function]
# @COMPLEXITY: 3
# @PURPOSE: Получает информацию о конкретной базе данных по её ID.
# @PRE: database_id must exist.
# @POST: Returns database details.
# @DATA_CONTRACT: Input[database_id: int] -> Output[Dict]
# @RELATION: [CALLS] ->[request]
# @RELATION: CALLS -> [ConnectionContracts]
def get_database(self, database_id: int) -> Dict:
with belief_scope("get_database"):
app_logger.info("[get_database][Enter] Fetching database %s.", database_id)
@@ -1999,15 +2001,15 @@ class SupersetClient:
app_logger.info("[get_database][Exit] Got database %s.", database_id)
return response
# [/DEF:get_database:Function]
# [/DEF:SupersetClientGetDatabase:Function]
# [DEF:get_databases_summary:Function]
# [DEF:SupersetClientGetDatabasesSummary:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetch a summary of databases including uuid, name, and engine.
# @PRE: Client is authenticated.
# @POST: Returns list of database summaries.
# @DATA_CONTRACT: None -> Output[List[Dict]]
# @RELATION: [CALLS] ->[SupersetClient.get_databases]
# @RELATION: CALLS -> [SupersetClientGetDatabases]
def get_databases_summary(self) -> List[Dict]:
with belief_scope("SupersetClient.get_databases_summary"):
query = {"columns": ["uuid", "database_name", "backend"]}
@@ -2019,29 +2021,29 @@ class SupersetClient:
return databases
# [/DEF:get_databases_summary:Function]
# [/DEF:SupersetClientGetDatabasesSummary:Function]
# [DEF:get_database_by_uuid:Function]
# [DEF:SupersetClientGetDatabaseByUuid:Function]
# @COMPLEXITY: 3
# @PURPOSE: Find a database by its UUID.
# @PRE: db_uuid must be a valid UUID string.
# @POST: Returns database info or None.
# @DATA_CONTRACT: Input[db_uuid: str] -> Output[Optional[Dict]]
# @RELATION: [CALLS] ->[SupersetClient.get_databases]
# @RELATION: CALLS -> [SupersetClientGetDatabases]
def get_database_by_uuid(self, db_uuid: str) -> Optional[Dict]:
with belief_scope("SupersetClient.get_database_by_uuid", f"uuid={db_uuid}"):
query = {"filters": [{"col": "uuid", "op": "eq", "value": db_uuid}]}
_, databases = self.get_databases(query=query)
return databases[0] if databases else None
# [/DEF:get_database_by_uuid:Function]
# [/DEF:SupersetClientGetDatabaseByUuid:Function]
# [DEF:SupersetClient._resolve_target_id_for_delete:Function]
# [DEF:SupersetClientResolveTargetIdForDelete:Function]
# @COMPLEXITY: 1
# @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.
# @RELATION: [CALLS] ->[SupersetClient.get_dashboards]
# @RELATION: CALLS -> [SupersetClientGetDashboards]
def _resolve_target_id_for_delete(
self, dash_id: Optional[int], dash_slug: Optional[str]
) -> Optional[int]:
@@ -2074,14 +2076,14 @@ class SupersetClient:
)
return None
# [/DEF:SupersetClient._resolve_target_id_for_delete:Function]
# [/DEF:SupersetClientResolveTargetIdForDelete:Function]
# [DEF:SupersetClient._do_import:Function]
# [DEF:SupersetClientDoImport:Function]
# @COMPLEXITY: 1
# @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.
# @RELATION: [CALLS] ->[APIClient.upload_file]
# @RELATION: CALLS -> [ConnectionContracts]
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}")
@@ -2103,9 +2105,9 @@ class SupersetClient:
timeout=self.env.timeout * 2,
)
# [/DEF:SupersetClient._do_import:Function]
# [/DEF:SupersetClientDoImport:Function]
# [DEF:_validate_export_response:Function]
# [DEF:SupersetClientValidateExportResponse:Function]
# @COMPLEXITY: 1
# @PURPOSE: Validates that the export response is a non-empty ZIP archive.
# @PRE: response must be a valid requests.Response object.
@@ -2120,9 +2122,9 @@ class SupersetClient:
if not response.content:
raise SupersetAPIError("Получены пустые данные при экспорте")
# [/DEF:_validate_export_response:Function]
# [/DEF:SupersetClientValidateExportResponse:Function]
# [DEF:_resolve_export_filename:Function]
# [DEF:SupersetClientResolveExportFilename:Function]
# @COMPLEXITY: 1
# @PURPOSE: Determines the filename for an exported dashboard.
# @PRE: response must contain Content-Disposition header or dashboard_id must be provided.
@@ -2141,9 +2143,9 @@ class SupersetClient:
)
return filename
# [/DEF:_resolve_export_filename:Function]
# [/DEF:SupersetClientResolveExportFilename:Function]
# [DEF:_validate_query_params:Function]
# [DEF:SupersetClientValidateQueryParams:Function]
# @COMPLEXITY: 1
# @PURPOSE: Ensures query parameters have default page and page_size.
# @PRE: query can be None or a dictionary.
@@ -2155,14 +2157,14 @@ class SupersetClient:
base_query = {"page": 0, "page_size": 100}
return {**base_query, **(query or {})}
# [/DEF:_validate_query_params:Function]
# [/DEF:SupersetClientValidateQueryParams:Function]
# [DEF:_fetch_total_object_count:Function]
# [DEF:SupersetClientFetchTotalObjectCount:Function]
# @COMPLEXITY: 1
# @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.
# @RELATION: [CALLS] ->[fetch_paginated_count]
# @RELATION: CALLS -> [ConnectionContracts]
def _fetch_total_object_count(self, endpoint: str) -> int:
with belief_scope("_fetch_total_object_count"):
return self.network.fetch_paginated_count(
@@ -2171,23 +2173,23 @@ class SupersetClient:
count_field="count",
)
# [/DEF:_fetch_total_object_count:Function]
# [/DEF:SupersetClientFetchTotalObjectCount:Function]
# [DEF:_fetch_all_pages:Function]
# [DEF:SupersetClientFetchAllPages:Function]
# @COMPLEXITY: 1
# @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.
# @RELATION: [CALLS] ->[fetch_paginated_data]
# @RELATION: CALLS -> [ConnectionContracts]
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:SupersetClientFetchAllPages:Function]
# [DEF:_validate_import_file:Function]
# [DEF:SupersetClientValidateImportFile:Function]
# @COMPLEXITY: 1
# @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.
@@ -2205,16 +2207,16 @@ class SupersetClient:
f"Архив {zip_path} не содержит 'metadata.yaml'"
)
# [/DEF:_validate_import_file:Function]
# [/DEF:SupersetClientValidateImportFile:Function]
# [DEF:get_all_resources:Function]
# [DEF:SupersetClientGetAllResources:Function]
# @COMPLEXITY: 3
# @PURPOSE: Fetches all resources of a given type with id, uuid, and name columns.
# @PARAM: resource_type (str) - One of "chart", "dataset", "dashboard".
# @PRE: Client is authenticated. resource_type is valid.
# @POST: Returns a list of resource dicts with at minimum id, uuid, and name fields.
# @RETURN: List[Dict]
# @RELATION: [CALLS] ->[_fetch_all_pages]
# @RELATION: CALLS -> [SupersetClientFetchAllPages]
def get_all_resources(
self, resource_type: str, since_dttm: Optional[datetime] = None
) -> List[Dict]:
@@ -2268,7 +2270,7 @@ class SupersetClient:
)
return data
# [/DEF:get_all_resources:Function]
# [/DEF:SupersetClientGetAllResources:Function]
# [/DEF:SupersetClient:Class]