mirror of
https://github.com/apache/superset.git
synced 2026-07-19 21:25:38 +00:00
- BLOCKER: add view.raise_for_access() on all external SemanticView paths; use SemanticViewDAO.find_accessible() for list-all to filter at SQL level, mirroring DatasourceDAO.build_semantic_view_query() - MEDIUM: validate requested metrics/dimensions/filters/order_by against the resolved datasource in get_table, matching query_dataset behavior; extract shared validate_names() to mcp_service/utils/query_utils.py - MEDIUM: fix N+1 in list_metrics find_all path by using _apply_base_filter with subqueryload eager options instead of lazy-loaded find_all() - NIT: extract _format_columns to format_data_columns() in response_utils.py; query_dataset now shares the same implementation - NIT: SemanticLayerError now extends MCPBaseError for a consistent error shape across all MCP tools - NIT: fix file permissions (644) on new semantic layer Python files
41 lines
1.4 KiB
Python
41 lines
1.4 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""Shared query validation utilities for MCP tools."""
|
|
|
|
import difflib
|
|
|
|
|
|
def validate_names(
|
|
requested: list[str],
|
|
valid: set[str],
|
|
kind: str,
|
|
) -> list[str]:
|
|
"""Return list of error messages for names not found in *valid*.
|
|
|
|
Includes close-match suggestions when available.
|
|
"""
|
|
errors: list[str] = []
|
|
for name in requested:
|
|
if name not in valid:
|
|
suggestions = difflib.get_close_matches(name, valid, n=3, cutoff=0.6)
|
|
msg = f"Unknown {kind}: '{name}'"
|
|
if suggestions:
|
|
msg += f". Did you mean: {', '.join(suggestions)}?"
|
|
errors.append(msg)
|
|
return errors
|