From ac60411433f6fcf35e251790e3f68cbeb9e5a96e Mon Sep 17 00:00:00 2001 From: Jan Tychtl Date: Wed, 21 Oct 2026 14:16:25 +0200 Subject: [PATCH] fix(gooddata-sdk): keep isHiddenFromKda on declarative metrics CatalogDeclarativeMetric did not declare is_hidden_from_kda. The generated DeclarativeMetric gained the field when the API client was regenerated, but the SDK attrs class was not updated, and cattrs drops keys a class does not declare. So loading a metric layout from disk or the server lost the flag silently, and every SDK put sent the metric without it: a git deploy could never set it, and a load-then-put wiped a flag set in the UI. Declare the field on the metric class only; the other analytics classes share CatalogAnalyticsBase but their generated models have no such field. An unset field stays None and is not sent, so existing layouts and cassettes are unchanged. A round-trip test covers true, false and an absent key through disk and to_api(). jira: GDAI-2630 risk: low --- .../analytics_model/analytics_model.py | 2 ++ .../test_declarative_analytics_metrics.py | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 packages/gooddata-sdk/tests/catalog/unit_tests/test_declarative_analytics_metrics.py diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py index f5406ba13..fb8d8a43b 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py @@ -331,6 +331,8 @@ def client_class() -> type[DeclarativeFilterContext]: @define(kw_only=True) class CatalogDeclarativeMetric(CatalogAnalyticsBase): + is_hidden_from_kda: bool | None = None + @staticmethod def client_class() -> type[DeclarativeMetric]: return DeclarativeMetric diff --git a/packages/gooddata-sdk/tests/catalog/unit_tests/test_declarative_analytics_metrics.py b/packages/gooddata-sdk/tests/catalog/unit_tests/test_declarative_analytics_metrics.py new file mode 100644 index 000000000..32141963b --- /dev/null +++ b/packages/gooddata-sdk/tests/catalog/unit_tests/test_declarative_analytics_metrics.py @@ -0,0 +1,34 @@ +# (C) 2026 GoodData Corporation +"""Unit test: a metric's ``isHiddenFromKda`` survives the declarative round trip.""" + +from __future__ import annotations + +from pathlib import Path + +import pytest +from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model import ( + CatalogDeclarativeAnalyticsLayer, +) + +_METRIC = {"id": "bmk_w_fraud_charged_back", "title": "BMK", "content": {"format": "#,##0", "maql": "SELECT 1"}} + + +@pytest.mark.parametrize( + ("extra", "expected"), + [ + ({"isHiddenFromKda": True}, True), + ({"isHiddenFromKda": False}, False), + ({}, None), + ], + ids=["hidden", "explicit-visible", "absent"], +) +def test_declarative_metric_is_hidden_from_kda_survives_round_trip( + tmp_path: Path, extra: dict, expected: bool | None +) -> None: + layer = CatalogDeclarativeAnalyticsLayer.from_dict({"metrics": [{**_METRIC, **extra}]}) + + layer.store_to_disk(tmp_path) + reloaded = CatalogDeclarativeAnalyticsLayer.load_from_disk(tmp_path) + + assert reloaded.metrics[0].is_hidden_from_kda is expected + assert reloaded.to_api().to_dict(camel_case=True)["metrics"][0] == {**_METRIC, **extra}