You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2026/03/20 19:43:18 UTC
(superset) 17/32: fix(chart): prevent chart list from failing when a datasource lacks explore_url (#38721)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch 6.1
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 25915f016b64f679b64364eff8d5aa25f6a943af
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Wed Mar 18 10:23:57 2026 -0300
fix(chart): prevent chart list from failing when a datasource lacks explore_url (#38721)
---
superset/models/slice.py | 7 +++++--
tests/unit_tests/models/slice_test.py | 38 +++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/superset/models/slice.py b/superset/models/slice.py
index 8b864f4ddc2..04c698ce95d 100644
--- a/superset/models/slice.py
+++ b/superset/models/slice.py
@@ -164,10 +164,13 @@ class Slice( # pylint: disable=too-many-public-methods
@renders("datasource_url")
def datasource_url(self) -> str | None:
+ # Use getattr to guard against datasource types that don't have explore_url
+ # (e.g. Query objects), which would otherwise raise AttributeError and cause
+ # the entire chart list response to fail.
if self.table:
- return self.table.explore_url
+ return getattr(self.table, "explore_url", None)
datasource = self.datasource
- return datasource.explore_url if datasource else None
+ return getattr(datasource, "explore_url", None) if datasource else None
def datasource_name_text(self) -> str | None:
if self.table:
diff --git a/tests/unit_tests/models/slice_test.py b/tests/unit_tests/models/slice_test.py
index dc6bbb86552..e55d00dede0 100644
--- a/tests/unit_tests/models/slice_test.py
+++ b/tests/unit_tests/models/slice_test.py
@@ -85,3 +85,41 @@ class TestSlice:
"""Test id_or_uuid_filter returns correct BinaryExpression."""
result = id_or_uuid_filter(input_value)
assert result is not None
+
+ def test_datasource_url_returns_none_when_datasource_lacks_explore_url(self):
+ """datasource_url() must not raise when the datasource has no explore_url.
+
+ Charts whose datasource resolves to a Query (or any other type without
+ explore_url) used to raise AttributeError, which caused the entire chart
+ list API response to fail instead of just skipping that one chart.
+ """
+ slc = Slice()
+ slc.id = 1
+
+ # Simulate a datasource object that does NOT have explore_url (e.g. Query)
+ mock_datasource = MagicMock(spec=[]) # spec=[] means no attributes at all
+ slc.table = mock_datasource
+
+ result = slc.datasource_url()
+ assert result is None
+
+ def test_datasource_url_returns_explore_url_when_present(self):
+ """datasource_url() returns the datasource explore_url when it exists."""
+ slc = Slice()
+ slc.id = 1
+
+ mock_table = MagicMock()
+ mock_table.explore_url = "/explore/?datasource_type=table&datasource_id=1"
+ slc.table = mock_table
+
+ result = slc.datasource_url()
+ assert result == "/explore/?datasource_type=table&datasource_id=1"
+
+ def test_datasource_url_returns_none_when_no_datasource(self):
+ """datasource_url() returns None when there is no datasource."""
+ slc = Slice()
+ slc.id = 1
+ slc.table = None
+
+ result = slc.datasource_url()
+ assert result is None