mirror of
https://github.com/apache/superset.git
synced 2026-08-25 01:21:18 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd07663dc1 |
Generated
+22
-19
@@ -86,7 +86,7 @@
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^2.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
"dayjs": "^1.11.22",
|
||||
"dayjs": "^1.11.21",
|
||||
"dom-to-image-more": "^3.10.2",
|
||||
"dom-to-pdf": "^0.3.2",
|
||||
"echarts": "^6.1.0",
|
||||
@@ -220,7 +220,7 @@
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"baseline-browser-mapping": "^2.11.14",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^10.0.5",
|
||||
"concurrently": "^10.0.4",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"css-loader": "^7.1.4",
|
||||
@@ -17190,9 +17190,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "10.0.5",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.5.tgz",
|
||||
"integrity": "sha512-JaP/CoftUrCcAFW/g//RbgEGwlelnEae6cfBLgH6ZdO6s8jPkn6p9SB9u6pdVxYXoiSnFqseOlHfrEfF82TVOg==",
|
||||
"version": "10.0.4",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.4.tgz",
|
||||
"integrity": "sha512-trZql+7l/0+WRAsAnEdctr4+iiOS6ZrViI6H8QWcCF9MFS/LT0dKpe8vluB1to6it+OxSI4VospFTIFMW8DJRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -18541,9 +18541,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.22",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.22.tgz",
|
||||
"integrity": "sha512-1YRnxzt/AabP3GHxnaB9/b+ZScCKu5TeF+co+BWG+lnWVIwEcTFc1FVE0WLNmNO3sA6GGXL40i5qkHfbLzpwrg==",
|
||||
"version": "1.11.21",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz",
|
||||
"integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
@@ -34873,18 +34873,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-error-boundary": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.1.3.tgz",
|
||||
"integrity": "sha512-GnSKpCohFi2nQmJCWwP8O8wub7zexlePvpsejvQr35vS5RTouS1+utTNOmyc540yw5vyOXnSL1rBWsCQDmkyUA==",
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.1.2.tgz",
|
||||
"integrity": "sha512-3DpCr5HVdZ0caUjYE/kIHBEJN0mNP3ZCgf16c48uJ5TbWjorKVp+YG8W3XqlJ7vJAVNw6wNIImyPXmFydwmyng==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.0 || ^19.0.0",
|
||||
"react": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-google-recaptcha": {
|
||||
@@ -42968,7 +42962,7 @@
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-time": "^3.1.0",
|
||||
"d3-time-format": "^4.1.0",
|
||||
"dayjs": "^1.11.22",
|
||||
"dayjs": "^1.11.21",
|
||||
"dompurify": "^3.4.13",
|
||||
"fetch-retry": "^6.0.0",
|
||||
"handlebars": "^4.7.9",
|
||||
@@ -42980,7 +42974,7 @@
|
||||
"re-resizable": "^6.11.2",
|
||||
"react-ace": "^14.0.1",
|
||||
"react-draggable": "^4.7.1",
|
||||
"react-error-boundary": "^6.1.3",
|
||||
"react-error-boundary": "^6.1.2",
|
||||
"react-js-cron": "^6.0.2",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-resize-detector": "^7.1.2",
|
||||
@@ -43079,6 +43073,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/dompurify": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz",
|
||||
"integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/react-ace": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-ace/-/react-ace-14.0.1.tgz",
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^2.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
"dayjs": "^1.11.22",
|
||||
"dayjs": "^1.11.21",
|
||||
"dom-to-image-more": "^3.10.2",
|
||||
"dom-to-pdf": "^0.3.2",
|
||||
"echarts": "^6.1.0",
|
||||
@@ -297,7 +297,7 @@
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"baseline-browser-mapping": "^2.11.14",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^10.0.5",
|
||||
"concurrently": "^10.0.4",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"css-loader": "^7.1.4",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-time": "^3.1.0",
|
||||
"d3-time-format": "^4.1.0",
|
||||
"dayjs": "^1.11.22",
|
||||
"dayjs": "^1.11.21",
|
||||
"dompurify": "^3.4.13",
|
||||
"fetch-retry": "^6.0.0",
|
||||
"handlebars": "^4.7.9",
|
||||
@@ -79,7 +79,7 @@
|
||||
"re-resizable": "^6.11.2",
|
||||
"react-ace": "^14.0.1",
|
||||
"react-draggable": "^4.7.1",
|
||||
"react-error-boundary": "^6.1.3",
|
||||
"react-error-boundary": "^6.1.2",
|
||||
"react-js-cron": "^6.0.2",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-resize-detector": "^7.1.2",
|
||||
|
||||
+6
-1
@@ -88,7 +88,12 @@ export const ResultsPaneOnDashboard = ({
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Tabs activeKey={activeTabKey} onChange={setActiveTabKey} items={items} />
|
||||
<Tabs
|
||||
fullHeight
|
||||
activeKey={activeTabKey}
|
||||
onChange={setActiveTabKey}
|
||||
items={items}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -106,10 +106,6 @@ def load_chart_data_into_cache(
|
||||
) -> None:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from superset.commands.chart.data.get_data_command import ChartDataCommand
|
||||
from superset.commands.chart.exceptions import (
|
||||
ChartDataCacheLoadError,
|
||||
ChartDataQueryFailedError,
|
||||
)
|
||||
|
||||
with override_user(_load_user_from_job_metadata(job_metadata), force=False):
|
||||
try:
|
||||
@@ -127,20 +123,6 @@ def load_chart_data_into_cache(
|
||||
except SoftTimeLimitExceeded as ex:
|
||||
_handle_soft_time_limit(job_metadata, ex, "loading chart data")
|
||||
raise
|
||||
except (ChartDataCacheLoadError, ChartDataQueryFailedError) as ex:
|
||||
# These map to 422/400 in the synchronous chart/data endpoint (see
|
||||
# ChartDataRestApi._get_data_response) - expected, client-facing
|
||||
# validation failures (e.g. a chart still referencing columns a
|
||||
# customer has since dropped from the dataset), not application
|
||||
# bugs. The failure is already delivered to the client via
|
||||
# update_job below; re-raising would only surface it a second
|
||||
# time as an unhandled Celery task exception.
|
||||
logger.info("Chart data query failed while loading into cache: %s", ex)
|
||||
async_query_manager.update_job(
|
||||
job_metadata,
|
||||
async_query_manager.STATUS_ERROR,
|
||||
errors=sanitize_error_dicts([{"message": str(ex.message)}]),
|
||||
)
|
||||
except Exception as ex:
|
||||
# Extract SIP-40 style errors when available
|
||||
if isinstance(ex, SupersetErrorException):
|
||||
|
||||
@@ -110,11 +110,8 @@ class TestAsyncQueries(SupersetTestCase):
|
||||
"status": "pending",
|
||||
"errors": [],
|
||||
}
|
||||
# ChartDataQueryFailedError mirrors the synchronous chart/data endpoint's
|
||||
# 400 (see ChartDataRestApi._get_data_response) - an expected validation
|
||||
# failure, not a bug, so the task reports it via update_job and does not
|
||||
# re-raise (see superset/tasks/async_queries.py).
|
||||
load_chart_data_into_cache(job_metadata, query_context)
|
||||
with pytest.raises(ChartDataQueryFailedError):
|
||||
load_chart_data_into_cache(job_metadata, query_context)
|
||||
|
||||
mock_run_command.assert_called_once_with(cache=True)
|
||||
errors = [{"message": "Error: foo"}]
|
||||
|
||||
@@ -21,10 +21,7 @@ import pytest
|
||||
from celery.exceptions import SoftTimeLimitExceeded
|
||||
from flask_babel import lazy_gettext as _
|
||||
|
||||
from superset.commands.chart.exceptions import (
|
||||
ChartDataCacheLoadError,
|
||||
ChartDataQueryFailedError,
|
||||
)
|
||||
from superset.commands.chart.exceptions import ChartDataQueryFailedError
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
from superset.exceptions import (
|
||||
OAuth2RedirectError,
|
||||
@@ -46,7 +43,7 @@ def test_load_chart_data_into_cache_with_error(
|
||||
job_metadata = {"user_id": 1}
|
||||
form_data = {}
|
||||
err_message = "Something went wrong"
|
||||
err = RuntimeError(err_message)
|
||||
err = ChartDataQueryFailedError(_(err_message))
|
||||
|
||||
mock_user = mock.MagicMock()
|
||||
mock_query_context_schema = mock.MagicMock()
|
||||
@@ -57,7 +54,7 @@ def test_load_chart_data_into_cache_with_error(
|
||||
|
||||
mock_query_context_schema.load.side_effect = err
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
with pytest.raises(ChartDataQueryFailedError):
|
||||
load_chart_data_into_cache(job_metadata, form_data)
|
||||
|
||||
expected_errors = [{"message": err_message}]
|
||||
@@ -67,76 +64,6 @@ def test_load_chart_data_into_cache_with_error(
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("superset.tasks.async_queries.security_manager")
|
||||
@mock.patch("superset.tasks.async_queries.async_query_manager")
|
||||
@mock.patch("superset.commands.chart.data.get_data_command.ChartDataCommand")
|
||||
@mock.patch("superset.tasks.async_queries.ChartDataQueryContextSchema")
|
||||
def test_load_chart_data_into_cache_with_query_failed_error_does_not_reraise(
|
||||
mock_query_context_schema_cls: mock.MagicMock,
|
||||
mock_command_cls: mock.MagicMock,
|
||||
mock_async_query_manager: mock.MagicMock,
|
||||
mock_security_manager: mock.MagicMock,
|
||||
) -> None:
|
||||
"""
|
||||
ChartDataQueryFailedError maps to a 400 in the synchronous chart/data
|
||||
endpoint (see ChartDataRestApi._get_data_response) - an expected,
|
||||
client-facing validation failure (e.g. a chart still referencing columns
|
||||
a customer has since dropped from the dataset), not an application bug.
|
||||
The task must still report it to the client via update_job, but must not
|
||||
re-raise it - that would surface it a second time as an unhandled Celery
|
||||
task exception.
|
||||
"""
|
||||
from superset.tasks.async_queries import load_chart_data_into_cache
|
||||
|
||||
job_metadata = {"user_id": 1}
|
||||
form_data: dict[str, Any] = {}
|
||||
err_message = "Columns missing in dataset: ['foo']"
|
||||
|
||||
mock_security_manager.get_user_by_id.return_value = mock.MagicMock()
|
||||
mock_async_query_manager.STATUS_ERROR = "error"
|
||||
mock_query_context_schema_cls.return_value.load.return_value = mock.MagicMock()
|
||||
mock_command_cls.return_value.run.side_effect = ChartDataQueryFailedError(
|
||||
_(err_message)
|
||||
)
|
||||
|
||||
# Should not raise.
|
||||
load_chart_data_into_cache(job_metadata, form_data)
|
||||
|
||||
mock_async_query_manager.update_job.assert_called_once_with(
|
||||
job_metadata, "error", errors=[{"message": err_message}]
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("superset.tasks.async_queries.security_manager")
|
||||
@mock.patch("superset.tasks.async_queries.async_query_manager")
|
||||
@mock.patch("superset.commands.chart.data.get_data_command.ChartDataCommand")
|
||||
@mock.patch("superset.tasks.async_queries.ChartDataQueryContextSchema")
|
||||
def test_load_chart_data_into_cache_with_cache_load_error_does_not_reraise(
|
||||
mock_query_context_schema_cls: mock.MagicMock,
|
||||
mock_command_cls: mock.MagicMock,
|
||||
mock_async_query_manager: mock.MagicMock,
|
||||
mock_security_manager: mock.MagicMock,
|
||||
) -> None:
|
||||
"""Same as above, for the sibling 422-mapped ChartDataCacheLoadError."""
|
||||
from superset.tasks.async_queries import load_chart_data_into_cache
|
||||
|
||||
job_metadata = {"user_id": 1}
|
||||
form_data: dict[str, Any] = {}
|
||||
err_message = "Cache load failed"
|
||||
|
||||
mock_security_manager.get_user_by_id.return_value = mock.MagicMock()
|
||||
mock_async_query_manager.STATUS_ERROR = "error"
|
||||
mock_query_context_schema_cls.return_value.load.return_value = mock.MagicMock()
|
||||
mock_command_cls.return_value.run.side_effect = ChartDataCacheLoadError(err_message)
|
||||
|
||||
# Should not raise.
|
||||
load_chart_data_into_cache(job_metadata, form_data)
|
||||
|
||||
mock_async_query_manager.update_job.assert_called_once_with(
|
||||
job_metadata, "error", errors=[{"message": err_message}]
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("superset.tasks.async_queries.security_manager")
|
||||
@mock.patch("superset.tasks.async_queries.async_query_manager")
|
||||
@mock.patch("superset.tasks.async_queries.ChartDataQueryContextSchema")
|
||||
|
||||
Reference in New Issue
Block a user