aminghadersohi commented on code in PR #39922:
URL: https://github.com/apache/superset/pull/39922#discussion_r3329456384
##########
superset/mcp_service/chart/chart_utils.py:
##########
@@ -320,29 +320,37 @@ def map_config_to_form_data(
| BigNumberChartConfig,
dataset_id: int | str | None = None,
) -> Dict[str, Any]:
- """Map chart config to Superset form_data."""
- if isinstance(config, TableChartConfig):
- return map_table_config(config)
- elif isinstance(config, XYChartConfig):
- return map_xy_config(config, dataset_id=dataset_id)
- elif isinstance(config, PieChartConfig):
- return map_pie_config(config)
- elif isinstance(config, PivotTableChartConfig):
- return map_pivot_table_config(config)
- elif isinstance(config, MixedTimeseriesChartConfig):
- return map_mixed_timeseries_config(config, dataset_id=dataset_id)
- elif isinstance(config, HandlebarsChartConfig):
- return map_handlebars_config(config)
- elif isinstance(config, BigNumberChartConfig):
- if config.show_trendline and config.temporal_column:
- if not is_column_truly_temporal(config.temporal_column,
dataset_id):
- raise ValueError(
- f"Big Number trendline requires a temporal SQL column; "
- f"'{config.temporal_column}' is not temporal."
- )
- return map_big_number_config(config)
- else:
- raise ValueError(f"Unsupported config type: {type(config)}")
+ """Map chart config to Superset form_data via the plugin registry.
+
+ The previous if/elif chain across all 7 chart types has been replaced by a
+ single registry lookup. Cross-field constraints (e.g. BigNumber trendline
+ temporal check) are now owned by each plugin's post_map_validate() method
+ rather than being baked into this dispatcher.
+ """
+ # Local import: plugins call map_*_config from their to_form_data()
methods,
+ # so chart_utils is loaded before plugins finish registering. A top-level
+ # import of registry here would trigger plugin loading mid-import = cycle.
+ from superset.mcp_service.chart.registry import get_registry
+
+ chart_type = getattr(config, "chart_type", None)
+ plugin = get_registry().get(chart_type) if chart_type else None
+
+ if plugin is None:
+ if chart_type is None:
+ raise ValueError(f"Unsupported config type: {type(config)}")
+ raise ValueError(
+ f"Unsupported config type: {type(config)}
(chart_type={chart_type!r})"
+ )
+
+ form_data = plugin.to_form_data(config, dataset_id=dataset_id)
+
+ # Run post-map validation (e.g. BigNumber trendline temporal type check).
+ # Raise ValueError to preserve backward-compatible error handling in
callers.
+ error = plugin.post_map_validate(config, form_data, dataset_id=dataset_id)
+ if error is not None:
+ raise ValueError(error.message)
Review Comment:
Already addressed in the current code. `map_config_to_form_data()`
(chart_utils.py lines 353–359) now includes `error.details` and
`error.suggestions` in the raised `ValueError` message — see the comment on
lines 349–351: _"Include details and suggestions so callers logging str(e)
surface actionable context."_ The structured `ChartGenerationError` fields are
concatenated into the message before raising, so callers that catch
`ValueError` see the full context including guidance strings.
##########
superset/mcp_service/chart/chart_utils.py:
##########
@@ -320,29 +320,37 @@ def map_config_to_form_data(
| BigNumberChartConfig,
dataset_id: int | str | None = None,
) -> Dict[str, Any]:
- """Map chart config to Superset form_data."""
- if isinstance(config, TableChartConfig):
- return map_table_config(config)
- elif isinstance(config, XYChartConfig):
- return map_xy_config(config, dataset_id=dataset_id)
- elif isinstance(config, PieChartConfig):
- return map_pie_config(config)
- elif isinstance(config, PivotTableChartConfig):
- return map_pivot_table_config(config)
- elif isinstance(config, MixedTimeseriesChartConfig):
- return map_mixed_timeseries_config(config, dataset_id=dataset_id)
- elif isinstance(config, HandlebarsChartConfig):
- return map_handlebars_config(config)
- elif isinstance(config, BigNumberChartConfig):
- if config.show_trendline and config.temporal_column:
- if not is_column_truly_temporal(config.temporal_column,
dataset_id):
- raise ValueError(
- f"Big Number trendline requires a temporal SQL column; "
- f"'{config.temporal_column}' is not temporal."
- )
- return map_big_number_config(config)
- else:
- raise ValueError(f"Unsupported config type: {type(config)}")
+ """Map chart config to Superset form_data via the plugin registry.
+
+ The previous if/elif chain across all 7 chart types has been replaced by a
+ single registry lookup. Cross-field constraints (e.g. BigNumber trendline
+ temporal check) are now owned by each plugin's post_map_validate() method
+ rather than being baked into this dispatcher.
+ """
+ # Local import: plugins call map_*_config from their to_form_data()
methods,
+ # so chart_utils is loaded before plugins finish registering. A top-level
+ # import of registry here would trigger plugin loading mid-import = cycle.
+ from superset.mcp_service.chart.registry import get_registry
+
+ chart_type = getattr(config, "chart_type", None)
+ plugin = get_registry().get(chart_type) if chart_type else None
+
+ if plugin is None:
+ if chart_type is None:
+ raise ValueError(f"Unsupported config type: {type(config)}")
+ raise ValueError(
+ f"Unsupported config type: {type(config)}
(chart_type={chart_type!r})"
+ )
+
+ form_data = plugin.to_form_data(config, dataset_id=dataset_id)
+
+ # Run post-map validation (e.g. BigNumber trendline temporal type check).
+ # Raise ValueError to preserve backward-compatible error handling in
callers.
+ error = plugin.post_map_validate(config, form_data, dataset_id=dataset_id)
+ if error is not None:
+ raise ValueError(error.message)
Review Comment:
Already addressed in the current code. `map_config_to_form_data()`
(chart_utils.py lines 353–359) now includes `error.details` and
`error.suggestions` in the raised `ValueError` message — see the comment on
lines 349–351: _"Include details and suggestions so callers logging str(e)
surface actionable context."_ The structured `ChartGenerationError` fields are
concatenated into the message before raising, so callers that catch
`ValueError` see the full context including guidance strings.
##########
superset/mcp_service/chart/schemas.py:
##########
@@ -101,7 +104,14 @@ class ChartInfo(BaseModel):
id: int | None = Field(None, description="Chart ID")
slice_name: str | None = Field(None, description="Chart name")
- viz_type: str | None = Field(None, description="Visualization type")
+ viz_type: str | None = Field(None, description="Visualization type
(internal ID)")
+ chart_type_display_name: str | None = Field(
+ None,
+ description=(
+ "User-friendly chart type name (e.g. 'Line Chart', 'Pivot Table').
"
+ "Use this field when referring to chart types — never expose
viz_type."
Review Comment:
Already addressed in the current code. The `chart_type_display_name` field
description (schemas.py lines 112–115) reads: _"Prefer this field when
referring to chart types; fall back to viz_type when this field is null."_ The
field explicitly instructs schema-driven clients to use `viz_type` when
`chart_type_display_name` is null — no contradiction with actual API behaviour.
The earlier wording _"never expose viz_type"_ was removed in a prior commit.
##########
superset/mcp_service/chart/schemas.py:
##########
@@ -101,7 +104,14 @@ class ChartInfo(BaseModel):
id: int | None = Field(None, description="Chart ID")
slice_name: str | None = Field(None, description="Chart name")
- viz_type: str | None = Field(None, description="Visualization type")
+ viz_type: str | None = Field(None, description="Visualization type
(internal ID)")
+ chart_type_display_name: str | None = Field(
+ None,
+ description=(
+ "User-friendly chart type name (e.g. 'Line Chart', 'Pivot Table').
"
+ "Use this field when referring to chart types — never expose
viz_type."
Review Comment:
Already addressed in the current code. The `chart_type_display_name` field
description (schemas.py lines 112–115) reads: _"Prefer this field when
referring to chart types; fall back to viz_type when this field is null."_ The
field explicitly instructs schema-driven clients to use `viz_type` when
`chart_type_display_name` is null — no contradiction with actual API behaviour.
The earlier wording _"never expose viz_type"_ was removed in a prior commit.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]