aminghadersohi commented on code in PR #45485:
URL: https://github.com/apache/superset/pull/45485#discussion_r4337488710


##########
superset/mcp_service/utils/schema_utils.py:
##########
@@ -34,6 +36,22 @@
 T = TypeVar("T")
 
 
+@contextmanager
+def field_validation_error(field_name: str) -> Iterator[None]:
+    """Attach a declared field location to checks in a model-level validator.
+
+    Keep the original ValueError for Pydantic consumers; the MCP diagnostic
+    formatter exposes only the schema-backed location and a static reason.
+    """
+    try:
+        yield
+    except ValueError as ex:
+        raise ValidationError.from_exception_data(
+            "Field validation",
+            [{"type": "value_error", "loc": (field_name,), "ctx": {"error": 
ex}}],
+        ) from ex

Review Comment:
   Follow-up fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3: the shared 
sanitizers emit stable error types, so sibling text fields get an actionable, 
input-free reason instead of “Invalid value”. Bullet comma labels and 
empty-after-sanitization certification text have their own reasons. Compact 
chart-config diagnostics resolve declared nested fields server-side; unknown 
tags/fields and dictionary keys remain masked.
   
   Regression test: 
`tests/unit_tests/mcp_service/test_sanitization_warning_inputs.py::test_sibling_sanitization_wire_error_names_field_with_actionable_reason`
 — all 28 cases fail at e8c421c3c2f319f6ec2d86102fa6fb925bddb972 and pass at 
6632cff2c8b12ff4660d1a28fa864e29646f77e3. I copied the new tests into a 
detached worktree at that prior head and ran pytest with `-m 'not manual and 
not llm_compliance'`.
   
   Additional regressions: 
`test_sibling_alias_sanitization_wire_error_names_canonical_field` (5 failures 
before), `test_nested_chart_sanitization_wire_error_names_field` (12 failures 
before, covering 
generate_chart/update_chart/generate_explore_link/update_chart_preview), and 
`test_sanitizer_guard_wire_error_is_actionable` (6 failures before; 2 
pre-existing native length guards already pass). Combined before result: 51 
failed, 2 passed; the seven sanitizer/schema/wire modules pass after: 1057 
passed. The full MCP run with the same marker exclusions and `-n 4` reports 
11225 passed, 12 skipped. Changed-branch-file pre-commit passes, including 
mypy, ruff and pylint. No real-provider or live-deployment check was run.
   
   Siblings checked:
   - superset/mcp_service/dashboard/schemas.py 
(GenerateDashboardRequest.dashboard_title) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/dashboard/schemas.py 
(UpdateDashboardRequest.dashboard_title) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/dashboard/schemas.py 
(DuplicateDashboardRequest.dashboard_title) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/dashboard/schemas.py 
(ManageDashboardCertificationRequest.certified_by) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/dashboard/schemas.py 
(ManageDashboardCertificationRequest.certification_details) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (GenerateChartRequest.chart_name) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (UpdateChartRequest.chart_name) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (BaseChartConfig.temporal_column) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (ColumnRef.name; including 
column_name/column aliases) — fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (ColumnRef.label) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (ColumnRef.sql_expression; 
SQL-specific rejections) — fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (FilterConfig.column; including col 
alias) — fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (FilterConfig.value; scalar/list, 
including val alias) — fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (GanttSortByConfig.column; including 
col alias) — fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (SunburstChartConfig.time_range) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py 
(InteractivePivotChartConfig.comparison_period) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (BulletChartConfig.time_range) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (BulletChartConfig.range_labels) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py (BulletChartConfig.marker_labels) — 
fixed in 6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/chart/schemas.py 
(BulletChartConfig.marker_line_labels) — fixed in 
6632cff2c8b12ff4660d1a28fa864e29646f77e3
   - superset/mcp_service/dashboard/schemas.py (_sanitize_header_text) — not 
affected: plain React header text only strips invisible characters and checks 
length; it does not use the shared URL/content sanitizer.
   - superset/mcp_service/utils/error_builder.py (_sanitize_user_input) — not 
affected: output escaping, not a Pydantic input-rejection path.
   
   SQL expressions retain their separate policy: prose containing `data:` is 
not itself rejected there; SQL-specific content rejections receive the safe 
reason. No sanitizer acceptance/rejection policy changed in this follow-up.
   



-- 
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]

Reply via email to