refactor(mcp): add is_system fields to ThemeInfo and get_schema tests for new model types

- Add is_system, is_system_default, is_system_dark to ThemeInfo and
  serialize_theme_object so schema discovery columns are fully serializable
- Add get_schema tests covering css_template and theme model types:
  default column assertions, search/sort columns, and request validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Amin Ghadersohi
2026-05-20 23:01:36 +00:00
parent 091d2cf4b4
commit 40ed2f56a8
2 changed files with 139 additions and 0 deletions

View File

@@ -73,6 +73,13 @@ class ThemeInfo(BaseModel):
None,
description="Theme JSON configuration data",
)
is_system: bool | None = Field(None, description="Whether this is a system theme")
is_system_default: bool | None = Field(
None, description="Whether this is the default system theme"
)
is_system_dark: bool | None = Field(
None, description="Whether this is the dark system theme"
)
changed_on: str | datetime | None = Field(
None, description="Last modification timestamp"
)
@@ -244,6 +251,9 @@ def serialize_theme_object(obj: Any) -> ThemeInfo | None:
uuid=str(getattr(obj, "uuid", "")) if getattr(obj, "uuid", None) else None,
theme_name=getattr(obj, "theme_name", None),
json_data=getattr(obj, "json_data", None),
is_system=getattr(obj, "is_system", None),
is_system_default=getattr(obj, "is_system_default", None),
is_system_dark=getattr(obj, "is_system_dark", None),
changed_on=getattr(obj, "changed_on", None),
created_on=getattr(obj, "created_on", None),
)

View File

@@ -30,6 +30,9 @@ from superset.mcp_service.common.schema_discovery import (
CHART_DEFAULT_COLUMNS,
CHART_SEARCH_COLUMNS,
CHART_SORTABLE_COLUMNS,
CSS_TEMPLATE_DEFAULT_COLUMNS,
CSS_TEMPLATE_SEARCH_COLUMNS,
CSS_TEMPLATE_SORTABLE_COLUMNS,
DASHBOARD_DEFAULT_COLUMNS,
DASHBOARD_SEARCH_COLUMNS,
DASHBOARD_SORTABLE_COLUMNS,
@@ -38,6 +41,9 @@ from superset.mcp_service.common.schema_discovery import (
DATASET_SORTABLE_COLUMNS,
GetSchemaRequest,
ModelSchemaInfo,
THEME_DEFAULT_COLUMNS,
THEME_SEARCH_COLUMNS,
THEME_SORTABLE_COLUMNS,
)
from superset.utils import json
@@ -527,3 +533,126 @@ class TestSchemaDiscoveryConstants:
assert "slice_name" in CHART_SEARCH_COLUMNS
assert "table_name" in DATASET_SEARCH_COLUMNS
assert "dashboard_title" in DASHBOARD_SEARCH_COLUMNS
def test_css_template_default_columns(self):
"""Test CSS template default columns include id and uuid but not css."""
assert "id" in CSS_TEMPLATE_DEFAULT_COLUMNS
assert "uuid" in CSS_TEMPLATE_DEFAULT_COLUMNS
assert "template_name" in CSS_TEMPLATE_DEFAULT_COLUMNS
assert "css" not in CSS_TEMPLATE_DEFAULT_COLUMNS
def test_css_template_sortable_columns(self):
"""Test CSS template sortable columns are defined correctly."""
assert "id" in CSS_TEMPLATE_SORTABLE_COLUMNS
assert "template_name" in CSS_TEMPLATE_SORTABLE_COLUMNS
assert "changed_on" in CSS_TEMPLATE_SORTABLE_COLUMNS
assert "created_on" in CSS_TEMPLATE_SORTABLE_COLUMNS
def test_theme_default_columns(self):
"""Test theme default columns include uuid."""
assert "id" in THEME_DEFAULT_COLUMNS
assert "uuid" in THEME_DEFAULT_COLUMNS
assert "theme_name" in THEME_DEFAULT_COLUMNS
assert "json_data" not in THEME_DEFAULT_COLUMNS
def test_theme_sortable_columns(self):
"""Test theme sortable columns are defined correctly."""
assert "id" in THEME_SORTABLE_COLUMNS
assert "theme_name" in THEME_SORTABLE_COLUMNS
assert "changed_on" in THEME_SORTABLE_COLUMNS
assert "created_on" in THEME_SORTABLE_COLUMNS
def test_css_template_search_columns_defined(self):
"""Test CSS template search columns are defined."""
assert "template_name" in CSS_TEMPLATE_SEARCH_COLUMNS
def test_theme_search_columns_defined(self):
"""Test theme search columns are defined."""
assert "theme_name" in THEME_SEARCH_COLUMNS
class TestGetSchemaCssTemplateAndTheme:
"""Test get_schema tool for css_template and theme model types."""
@patch("superset.daos.css.CssTemplateDAO.get_filterable_columns_and_operators")
@pytest.mark.asyncio
async def test_get_schema_css_template(self, mock_filters, mcp_server):
"""Test get_schema for css_template model type."""
mock_filters.return_value = {
"template_name": ["eq", "sw", "ilike"],
}
async with Client(mcp_server) as client:
result = await client.call_tool(
"get_schema", {"request": {"model_type": "css_template"}}
)
assert result.content is not None
data = json.loads(result.content[0].text)
assert "schema_info" in data
info = data["schema_info"]
assert info["model_type"] == "css_template"
assert "select_columns" in info
assert "filter_columns" in info
assert "sortable_columns" in info
assert "default_select" in info
assert "search_columns" in info
# uuid and template_name are in defaults; css is not
assert "id" in info["default_select"]
assert "uuid" in info["default_select"]
assert "template_name" in info["default_select"]
assert "css" not in info["default_select"]
# template_name is searchable
assert "template_name" in info["search_columns"]
# sortable columns
assert "template_name" in info["sortable_columns"]
assert "changed_on" in info["sortable_columns"]
@patch("superset.daos.theme.ThemeDAO.get_filterable_columns_and_operators")
@pytest.mark.asyncio
async def test_get_schema_theme(self, mock_filters, mcp_server):
"""Test get_schema for theme model type."""
mock_filters.return_value = {
"theme_name": ["eq", "sw", "ilike"],
}
async with Client(mcp_server) as client:
result = await client.call_tool(
"get_schema", {"request": {"model_type": "theme"}}
)
assert result.content is not None
data = json.loads(result.content[0].text)
assert "schema_info" in data
info = data["schema_info"]
assert info["model_type"] == "theme"
assert "select_columns" in info
assert "filter_columns" in info
# uuid and theme_name are in defaults; json_data is not
assert "id" in info["default_select"]
assert "uuid" in info["default_select"]
assert "theme_name" in info["default_select"]
assert "json_data" not in info["default_select"]
# theme_name is searchable
assert "theme_name" in info["search_columns"]
# sortable columns
assert "theme_name" in info["sortable_columns"]
assert "changed_on" in info["sortable_columns"]
def test_css_template_model_type_accepted(self):
"""css_template is a valid GetSchemaRequest model_type."""
request = GetSchemaRequest(model_type="css_template")
assert request.model_type == "css_template"
def test_theme_model_type_accepted(self):
"""theme is a valid GetSchemaRequest model_type."""
request = GetSchemaRequest(model_type="theme")
assert request.model_type == "theme"