mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
Address comments
This commit is contained in:
@@ -21,7 +21,7 @@ from abc import ABC, abstractmethod
|
|||||||
from typing import Any, Generic, TypeVar
|
from typing import Any, Generic, TypeVar
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from superset_core.semantic_layers.semantic_view import SemanticView
|
from superset_core.semantic_layers.view import SemanticView
|
||||||
|
|
||||||
ConfigT = TypeVar("ConfigT", bound=BaseModel)
|
ConfigT = TypeVar("ConfigT", bound=BaseModel)
|
||||||
SemanticViewT = TypeVar("SemanticViewT", bound="SemanticView")
|
SemanticViewT = TypeVar("SemanticViewT", bound="SemanticView")
|
||||||
@@ -25,29 +25,6 @@ from typing import Type as TypeOf
|
|||||||
|
|
||||||
import pyarrow as pa
|
import pyarrow as pa
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"BINARY",
|
|
||||||
"BOOLEAN",
|
|
||||||
"DATE",
|
|
||||||
"DATETIME",
|
|
||||||
"DECIMAL",
|
|
||||||
"Day",
|
|
||||||
"Dimension",
|
|
||||||
"Hour",
|
|
||||||
"INTEGER",
|
|
||||||
"INTERVAL",
|
|
||||||
"Minute",
|
|
||||||
"Month",
|
|
||||||
"NUMBER",
|
|
||||||
"OBJECT",
|
|
||||||
"Quarter",
|
|
||||||
"Second",
|
|
||||||
"STRING",
|
|
||||||
"TIME",
|
|
||||||
"Week",
|
|
||||||
"Year",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Type:
|
class Type:
|
||||||
"""
|
"""
|
||||||
@@ -216,7 +193,7 @@ class Metric:
|
|||||||
name: str
|
name: str
|
||||||
type: TypeOf[Type]
|
type: TypeOf[Type]
|
||||||
|
|
||||||
definition: str | None
|
definition: str | None = None
|
||||||
description: str | None = None
|
description: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class SemanticView(ABC):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_dataframe(
|
def get_table(
|
||||||
self,
|
self,
|
||||||
metrics: list[Metric],
|
metrics: list[Metric],
|
||||||
dimensions: list[Dimension],
|
dimensions: list[Dimension],
|
||||||
@@ -107,3 +107,23 @@ class SemanticView(ABC):
|
|||||||
"""
|
"""
|
||||||
Execute a query and return the number of rows the result would have.
|
Execute a query and return the number of rows the result would have.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_compatible_metrics(
|
||||||
|
self,
|
||||||
|
selected_metrics: set[Metric],
|
||||||
|
selected_dimensions: set[Dimension],
|
||||||
|
) -> set[Metric]:
|
||||||
|
"""
|
||||||
|
Return metrics compatible with the selected dimensions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_compatible_dimensions(
|
||||||
|
self,
|
||||||
|
selected_metrics: set[Metric],
|
||||||
|
selected_dimensions: set[Dimension],
|
||||||
|
) -> set[Dimension]:
|
||||||
|
"""
|
||||||
|
Return dimensions compatible with the selected metrics.
|
||||||
|
"""
|
||||||
@@ -30,7 +30,6 @@ from typing import Any, cast, Sequence, TypeGuard
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pyarrow as pa
|
import pyarrow as pa
|
||||||
from superset_core.semantic_layers.semantic_view import SemanticViewFeature
|
|
||||||
from superset_core.semantic_layers.types import (
|
from superset_core.semantic_layers.types import (
|
||||||
AdhocExpression,
|
AdhocExpression,
|
||||||
Day,
|
Day,
|
||||||
@@ -54,6 +53,7 @@ from superset_core.semantic_layers.types import (
|
|||||||
Week,
|
Week,
|
||||||
Year,
|
Year,
|
||||||
)
|
)
|
||||||
|
from superset_core.semantic_layers.view import SemanticViewFeature
|
||||||
|
|
||||||
from superset.common.db_query_status import QueryStatus
|
from superset.common.db_query_status import QueryStatus
|
||||||
from superset.common.query_object import QueryObject
|
from superset.common.query_object import QueryObject
|
||||||
@@ -348,8 +348,6 @@ def map_query_object(query_object: ValidatedQueryObject) -> list[SemanticQuery]:
|
|||||||
time_offset,
|
time_offset,
|
||||||
all_dimensions,
|
all_dimensions,
|
||||||
)
|
)
|
||||||
print(">>", filters)
|
|
||||||
|
|
||||||
queries.append(
|
queries.append(
|
||||||
SemanticQuery(
|
SemanticQuery(
|
||||||
metrics=metrics,
|
metrics=metrics,
|
||||||
@@ -603,8 +601,8 @@ def _convert_query_object_filter(
|
|||||||
|
|
||||||
operator = operator_mapping.get(operator_str)
|
operator = operator_mapping.get(operator_str)
|
||||||
if not operator:
|
if not operator:
|
||||||
# Unknown operator - create adhoc filter
|
# Unknown operator - raise error to prevent unauthorized access
|
||||||
return None
|
raise ValueError(f"Unsupported filter operator: {operator_str}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Filter(
|
Filter(
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import pandas as pd
|
|||||||
import pyarrow as pa
|
import pyarrow as pa
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from superset_core.semantic_layers.semantic_view import SemanticViewFeature
|
|
||||||
from superset_core.semantic_layers.types import (
|
from superset_core.semantic_layers.types import (
|
||||||
AdhocExpression,
|
AdhocExpression,
|
||||||
Day,
|
Day,
|
||||||
@@ -48,6 +47,7 @@ from superset_core.semantic_layers.types import (
|
|||||||
Week,
|
Week,
|
||||||
Year,
|
Year,
|
||||||
)
|
)
|
||||||
|
from superset_core.semantic_layers.view import SemanticViewFeature
|
||||||
|
|
||||||
from superset.semantic_layers.mapper import (
|
from superset.semantic_layers.mapper import (
|
||||||
_convert_query_object_filter,
|
_convert_query_object_filter,
|
||||||
@@ -59,12 +59,18 @@ from superset.semantic_layers.mapper import (
|
|||||||
_get_order_from_query_object,
|
_get_order_from_query_object,
|
||||||
_get_time_bounds,
|
_get_time_bounds,
|
||||||
_get_time_filter,
|
_get_time_filter,
|
||||||
|
_normalize_column,
|
||||||
|
_validate_filters,
|
||||||
|
_validate_granularity,
|
||||||
|
_validate_group_limit,
|
||||||
|
_validate_metrics,
|
||||||
get_results,
|
get_results,
|
||||||
map_query_object,
|
map_query_object,
|
||||||
validate_query_object,
|
validate_query_object,
|
||||||
ValidatedQueryObject,
|
ValidatedQueryObject,
|
||||||
ValidatedQueryObjectFilterClause,
|
ValidatedQueryObjectFilterClause,
|
||||||
)
|
)
|
||||||
|
from superset.superset_typing import AdhocColumn
|
||||||
from superset.utils.core import FilterOperator
|
from superset.utils.core import FilterOperator
|
||||||
|
|
||||||
# Alias for convenience
|
# Alias for convenience
|
||||||
@@ -1717,9 +1723,6 @@ def test_normalize_column_adhoc_not_in_dimensions() -> None:
|
|||||||
"""
|
"""
|
||||||
Test _normalize_column raises error for AdhocColumn with sqlExpression not in dims.
|
Test _normalize_column raises error for AdhocColumn with sqlExpression not in dims.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _normalize_column
|
|
||||||
from superset.superset_typing import AdhocColumn
|
|
||||||
|
|
||||||
dimension_names = {"category", "region"}
|
dimension_names = {"category", "region"}
|
||||||
adhoc_column: AdhocColumn = {
|
adhoc_column: AdhocColumn = {
|
||||||
"isColumnReference": True,
|
"isColumnReference": True,
|
||||||
@@ -1734,9 +1737,6 @@ def test_normalize_column_adhoc_missing_sql_expression() -> None:
|
|||||||
"""
|
"""
|
||||||
Test _normalize_column raises error for AdhocColumn without sqlExpression.
|
Test _normalize_column raises error for AdhocColumn without sqlExpression.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _normalize_column
|
|
||||||
from superset.superset_typing import AdhocColumn
|
|
||||||
|
|
||||||
dimension_names = {"category", "region"}
|
dimension_names = {"category", "region"}
|
||||||
adhoc_column: AdhocColumn = {
|
adhoc_column: AdhocColumn = {
|
||||||
"isColumnReference": True,
|
"isColumnReference": True,
|
||||||
@@ -1750,9 +1750,6 @@ def test_normalize_column_adhoc_valid(mock_datasource: MagicMock) -> None:
|
|||||||
"""
|
"""
|
||||||
Test _normalize_column with valid AdhocColumn reference.
|
Test _normalize_column with valid AdhocColumn reference.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _normalize_column
|
|
||||||
from superset.superset_typing import AdhocColumn
|
|
||||||
|
|
||||||
dimension_names = {"category", "region"}
|
dimension_names = {"category", "region"}
|
||||||
adhoc_column: AdhocColumn = {
|
adhoc_column: AdhocColumn = {
|
||||||
"isColumnReference": True,
|
"isColumnReference": True,
|
||||||
@@ -2115,8 +2112,6 @@ def test_validate_metrics_adhoc_error(
|
|||||||
"""
|
"""
|
||||||
Test validation error for adhoc metrics.
|
Test validation error for adhoc metrics.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_metrics
|
|
||||||
|
|
||||||
mock_datasource = mocker.Mock()
|
mock_datasource = mocker.Mock()
|
||||||
category_dim = Dimension("category", "category", STRING, "category", "Category")
|
category_dim = Dimension("category", "category", STRING, "category", "Category")
|
||||||
sales_metric = Metric("total_sales", "total_sales", NUMBER, "SUM(amount)", "Sales")
|
sales_metric = Metric("total_sales", "total_sales", NUMBER, "SUM(amount)", "Sales")
|
||||||
@@ -2139,7 +2134,6 @@ def test_validate_filters_adhoc_column_error(
|
|||||||
"""
|
"""
|
||||||
Test validation error for adhoc column in filter.
|
Test validation error for adhoc column in filter.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_filters
|
|
||||||
|
|
||||||
query_object = mocker.Mock()
|
query_object = mocker.Mock()
|
||||||
query_object.filter = [
|
query_object.filter = [
|
||||||
@@ -2160,7 +2154,6 @@ def test_validate_filters_missing_operator_error(
|
|||||||
"""
|
"""
|
||||||
Test validation error for filter without operator.
|
Test validation error for filter without operator.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_filters
|
|
||||||
|
|
||||||
query_object = mocker.Mock()
|
query_object = mocker.Mock()
|
||||||
query_object.filter = [
|
query_object.filter = [
|
||||||
@@ -2481,7 +2474,6 @@ def test_validate_filters_empty(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
Test _validate_filters with empty filter list (the loop doesn't run).
|
Test _validate_filters with empty filter list (the loop doesn't run).
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_filters
|
|
||||||
|
|
||||||
query_object = mocker.Mock()
|
query_object = mocker.Mock()
|
||||||
query_object.filter = [] # Empty filter list
|
query_object.filter = [] # Empty filter list
|
||||||
@@ -2494,7 +2486,6 @@ def test_validate_granularity_valid(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
Test _validate_granularity with valid granularity and time grain.
|
Test _validate_granularity with valid granularity and time grain.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_granularity
|
|
||||||
|
|
||||||
mock_datasource = mocker.Mock()
|
mock_datasource = mocker.Mock()
|
||||||
time_dim = Dimension("order_date", "order_date", STRING, "order_date", "Date", Day)
|
time_dim = Dimension("order_date", "order_date", STRING, "order_date", "Date", Day)
|
||||||
@@ -2514,7 +2505,6 @@ def test_validate_group_limit_valid(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
Test _validate_group_limit with valid group limit settings.
|
Test _validate_group_limit with valid group limit settings.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_group_limit
|
|
||||||
|
|
||||||
mock_datasource = mocker.Mock()
|
mock_datasource = mocker.Mock()
|
||||||
category_dim = Dimension("category", "category", STRING, "category", "Category")
|
category_dim = Dimension("category", "category", STRING, "category", "Category")
|
||||||
@@ -2647,7 +2637,6 @@ def test_validate_filters_with_valid_filters(mocker: MockerFixture) -> None:
|
|||||||
Test _validate_filters with valid filters that pass validation.
|
Test _validate_filters with valid filters that pass validation.
|
||||||
This covers the branch where the loop completes without raising.
|
This covers the branch where the loop completes without raising.
|
||||||
"""
|
"""
|
||||||
from superset.semantic_layers.mapper import _validate_filters
|
|
||||||
|
|
||||||
query_object = mocker.Mock()
|
query_object = mocker.Mock()
|
||||||
query_object.filter = [
|
query_object.filter = [
|
||||||
|
|||||||
Reference in New Issue
Block a user