You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2026/06/15 21:45:49 UTC

(superset) branch master updated: fix(charts): rename deprecated query object fields in schema before QueryObject construction (#41056)

This is an automated email from the ASF dual-hosted git repository.

eschutho pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 09b4bc51a32 fix(charts): rename deprecated query object fields in schema before QueryObject construction (#41056)
09b4bc51a32 is described below

commit 09b4bc51a320c58f433e37bc410fba1d2ab1a3ec
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Mon Jun 15 14:45:41 2026 -0700

    fix(charts): rename deprecated query object fields in schema before QueryObject construction (#41056)
---
 superset/charts/schemas.py              | 15 +++++++++++
 tests/unit_tests/charts/test_schemas.py | 47 +++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/superset/charts/schemas.py b/superset/charts/schemas.py
index 21db7576a32..26e2470fbff 100644
--- a/superset/charts/schemas.py
+++ b/superset/charts/schemas.py
@@ -1454,6 +1454,21 @@ class ChartDataQueryObjectSchema(Schema):
         allow_none=True,
     )
 
+    @post_load
+    def rename_deprecated_fields(
+        self, data: dict[str, Any], **kwargs: Any
+    ) -> dict[str, Any]:
+        _renames = (
+            ("groupby", "columns"),
+            ("granularity_sqla", "granularity"),
+            ("timeseries_limit", "series_limit"),
+            ("timeseries_limit_metric", "series_limit_metric"),
+        )
+        for old, new in _renames:
+            if value := data.pop(old, None):
+                data[new] = value
+        return data
+
 
 class ChartDataQueryContextSchema(Schema):
     query_context_factory: QueryContextFactory | None = None
diff --git a/tests/unit_tests/charts/test_schemas.py b/tests/unit_tests/charts/test_schemas.py
index 041265cd3b1..caa4cadde7e 100644
--- a/tests/unit_tests/charts/test_schemas.py
+++ b/tests/unit_tests/charts/test_schemas.py
@@ -213,6 +213,53 @@ def test_chart_data_query_object_schema_time_grain_sqla_validation(
     assert result["extras"]["time_grain_sqla"] is None
 
 
+def test_chart_data_query_object_schema_deprecated_fields_renamed(
+    app_context: None,
+) -> None:
+    """Deprecated query object fields are renamed to their canonical names."""
+    schema = ChartDataQueryObjectSchema()
+
+    # groupby alone → becomes columns
+    result = schema.load({"groupby": ["country_name"]})
+    assert result.get("columns") == ["country_name"]
+    assert "groupby" not in result
+
+    # groupby overwrites columns when both are provided
+    result = schema.load({"groupby": ["region"], "columns": ["country_name"]})
+    assert result.get("columns") == ["region"]
+    assert "groupby" not in result
+
+    # empty groupby is discarded; existing columns is preserved
+    result = schema.load({"groupby": [], "columns": ["country_name"]})
+    assert result.get("columns") == ["country_name"]
+    assert "groupby" not in result
+
+    # null groupby is discarded; existing columns is preserved (allow_none=True)
+    result = schema.load({"groupby": None, "columns": ["country_name"]})
+    assert result.get("columns") == ["country_name"]
+    assert "groupby" not in result
+
+    # no groupby → columns passes through unchanged
+    result = schema.load({"columns": ["country_name"]})
+    assert result.get("columns") == ["country_name"]
+    assert "groupby" not in result
+
+    # granularity_sqla → granularity
+    result = schema.load({"granularity_sqla": "ds"})
+    assert result.get("granularity") == "ds"
+    assert "granularity_sqla" not in result
+
+    # timeseries_limit → series_limit
+    result = schema.load({"timeseries_limit": 5})
+    assert result.get("series_limit") == 5
+    assert "timeseries_limit" not in result
+
+    # timeseries_limit_metric → series_limit_metric
+    result = schema.load({"timeseries_limit_metric": "count"})
+    assert result.get("series_limit_metric") == "count"
+    assert "timeseries_limit_metric" not in result
+
+
 @pytest.mark.parametrize(
     "app",
     [{"TIME_GRAIN_ADDONS": {"PT10M": "10 minutes"}}],