This is an automated email from the ASF dual-hosted git repository. betodealmeida pushed a commit to branch oauth-during-db-creation in repository https://gitbox.apache.org/repos/asf/superset.git
commit 88bc904b3d954df236d8245418089f84fb1d2992 Author: Beto Dealmeida <[email protected]> AuthorDate: Tue May 19 20:32:50 2026 -0400 feat(semantic layers): add metadata on additive metrics --- .../src/superset_core/semantic_layers/types.py | 21 ++++++++ tests/unit_tests/semantic_layers/types_test.py | 58 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/superset-core/src/superset_core/semantic_layers/types.py b/superset-core/src/superset_core/semantic_layers/types.py index 1239c1303be..3bfa9e8c315 100644 --- a/superset-core/src/superset_core/semantic_layers/types.py +++ b/superset-core/src/superset_core/semantic_layers/types.py @@ -92,6 +92,26 @@ class Dimension: grain: Grain | None = None +class AggregationType(str, enum.Enum): + """ + Aggregation function applied by a metric. + + Additivity (across an arbitrary set of grouping dimensions): + * ``SUM``, ``COUNT``: fully additive — sub-group sums roll up via ``sum``. + * ``MIN``, ``MAX``: roll up via ``min`` / ``max`` of sub-group values. + * ``AVG``, ``COUNT_DISTINCT``, ``OTHER``: not safely roll-uppable from + sub-aggregates without auxiliary data. + """ + + SUM = "SUM" + COUNT = "COUNT" + MIN = "MIN" + MAX = "MAX" + AVG = "AVG" + COUNT_DISTINCT = "COUNT_DISTINCT" + OTHER = "OTHER" + + @dataclass(frozen=True) class Metric: id: str @@ -100,6 +120,7 @@ class Metric: definition: str description: str | None = None + aggregation: AggregationType | None = None @dataclass(frozen=True) diff --git a/tests/unit_tests/semantic_layers/types_test.py b/tests/unit_tests/semantic_layers/types_test.py new file mode 100644 index 00000000000..0b1e8813f71 --- /dev/null +++ b/tests/unit_tests/semantic_layers/types_test.py @@ -0,0 +1,58 @@ +# 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. + +from __future__ import annotations + +import pyarrow as pa +from superset_core.semantic_layers.types import AggregationType, Metric + + +def test_metric_aggregation_defaults_to_none() -> None: + metric = Metric( + id="x", + name="x", + type=pa.float64(), + definition="sum(x)", + ) + assert metric.aggregation is None + + +def test_metric_accepts_aggregation_type() -> None: + metric = Metric( + id="x", + name="x", + type=pa.float64(), + definition="sum(x)", + aggregation=AggregationType.SUM, + ) + assert metric.aggregation is AggregationType.SUM + + +def test_aggregation_type_is_string_enum() -> None: + # Behaves as a string for equality and serialization, so it can be sent + # over JSON without an explicit converter. + assert AggregationType.SUM == "SUM" + assert AggregationType.COUNT_DISTINCT.value == "COUNT_DISTINCT" + assert {a.value for a in AggregationType} == { + "SUM", + "COUNT", + "MIN", + "MAX", + "AVG", + "COUNT_DISTINCT", + "OTHER", + }
