mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-19 16:11:27 +00:00
Compare commits
8 Commits
update-ind
...
will/conve
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8ace8ae21 | ||
|
|
028ebf84c1 | ||
|
|
83977dbf31 | ||
|
|
d428daa6a1 | ||
|
|
0f322ed8cb | ||
|
|
67f46f4d2b | ||
|
|
fb81b74835 | ||
|
|
c7559cdb4c |
7
.changes/unreleased/Features-20231206-181458.yaml
Normal file
7
.changes/unreleased/Features-20231206-181458.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
kind: Features
|
||||||
|
body: Adds support for parsing conversion metric related properties for the semantic
|
||||||
|
layer.
|
||||||
|
time: 2023-12-06T18:14:58.688221-05:00
|
||||||
|
custom:
|
||||||
|
Author: WilliamDee
|
||||||
|
Issue: "9203"
|
||||||
@@ -5,7 +5,7 @@ from typing import Any, Dict, Iterator, List
|
|||||||
|
|
||||||
|
|
||||||
DERIVED_METRICS = [MetricType.DERIVED, MetricType.RATIO]
|
DERIVED_METRICS = [MetricType.DERIVED, MetricType.RATIO]
|
||||||
BASE_METRICS = [MetricType.SIMPLE, MetricType.CUMULATIVE]
|
BASE_METRICS = [MetricType.SIMPLE, MetricType.CUMULATIVE, MetricType.CONVERSION]
|
||||||
|
|
||||||
|
|
||||||
class MetricReference(object):
|
class MetricReference(object):
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from dbt.contracts.graph.semantic_models import (
|
|||||||
SourceFileMetadata,
|
SourceFileMetadata,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.unparsed import (
|
from dbt.contracts.graph.unparsed import (
|
||||||
|
ConstantPropertyInput,
|
||||||
Docs,
|
Docs,
|
||||||
ExposureType,
|
ExposureType,
|
||||||
ExternalTable,
|
ExternalTable,
|
||||||
@@ -59,7 +60,11 @@ from dbt_semantic_interfaces.references import (
|
|||||||
TimeDimensionReference,
|
TimeDimensionReference,
|
||||||
)
|
)
|
||||||
from dbt_semantic_interfaces.references import MetricReference as DSIMetricReference
|
from dbt_semantic_interfaces.references import MetricReference as DSIMetricReference
|
||||||
from dbt_semantic_interfaces.type_enums import MetricType, TimeGranularity
|
from dbt_semantic_interfaces.type_enums import (
|
||||||
|
ConversionCalculationType,
|
||||||
|
MetricType,
|
||||||
|
TimeGranularity,
|
||||||
|
)
|
||||||
|
|
||||||
from .model_config import (
|
from .model_config import (
|
||||||
NodeConfig,
|
NodeConfig,
|
||||||
@@ -1435,6 +1440,16 @@ class MetricInput(dbtClassMixin):
|
|||||||
return DSIMetricReference(element_name=self.alias or self.name)
|
return DSIMetricReference(element_name=self.alias or self.name)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConversionTypeParams(dbtClassMixin):
|
||||||
|
base_measure: MetricInputMeasure
|
||||||
|
conversion_measure: MetricInputMeasure
|
||||||
|
entity: str
|
||||||
|
calculation: ConversionCalculationType = ConversionCalculationType.CONVERSION_RATE
|
||||||
|
window: Optional[MetricTimeWindow] = None
|
||||||
|
constant_properties: Optional[List[ConstantPropertyInput]] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MetricTypeParams(dbtClassMixin):
|
class MetricTypeParams(dbtClassMixin):
|
||||||
measure: Optional[MetricInputMeasure] = None
|
measure: Optional[MetricInputMeasure] = None
|
||||||
@@ -1445,6 +1460,7 @@ class MetricTypeParams(dbtClassMixin):
|
|||||||
window: Optional[MetricTimeWindow] = None
|
window: Optional[MetricTimeWindow] = None
|
||||||
grain_to_date: Optional[TimeGranularity] = None
|
grain_to_date: Optional[TimeGranularity] = None
|
||||||
metrics: Optional[List[MetricInput]] = None
|
metrics: Optional[List[MetricInput]] = None
|
||||||
|
conversion_type_params: Optional[ConversionTypeParams] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import dbt.helper_types # noqa:F401
|
|||||||
from dbt.exceptions import CompilationError, ParsingError, DbtInternalError
|
from dbt.exceptions import CompilationError, ParsingError, DbtInternalError
|
||||||
|
|
||||||
from dbt.dataclass_schema import dbtClassMixin, StrEnum, ExtensibleDbtClassMixin, ValidationError
|
from dbt.dataclass_schema import dbtClassMixin, StrEnum, ExtensibleDbtClassMixin, ValidationError
|
||||||
|
from dbt_semantic_interfaces.type_enums import ConversionCalculationType
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@@ -597,6 +598,24 @@ class UnparsedMetricInput(dbtClassMixin):
|
|||||||
offset_to_grain: Optional[str] = None # str is really a TimeGranularity Enum
|
offset_to_grain: Optional[str] = None # str is really a TimeGranularity Enum
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConstantPropertyInput(dbtClassMixin):
|
||||||
|
base_property: str
|
||||||
|
conversion_property: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class UnparsedConversionTypeParams(dbtClassMixin):
|
||||||
|
base_measure: Union[UnparsedMetricInputMeasure, str]
|
||||||
|
conversion_measure: Union[UnparsedMetricInputMeasure, str]
|
||||||
|
entity: str
|
||||||
|
calculation: str = (
|
||||||
|
ConversionCalculationType.CONVERSION_RATE.value
|
||||||
|
) # ConversionCalculationType Enum
|
||||||
|
window: Optional[str] = None
|
||||||
|
constant_properties: Optional[List[ConstantPropertyInput]] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class UnparsedMetricTypeParams(dbtClassMixin):
|
class UnparsedMetricTypeParams(dbtClassMixin):
|
||||||
measure: Optional[Union[UnparsedMetricInputMeasure, str]] = None
|
measure: Optional[Union[UnparsedMetricInputMeasure, str]] = None
|
||||||
@@ -606,6 +625,7 @@ class UnparsedMetricTypeParams(dbtClassMixin):
|
|||||||
window: Optional[str] = None
|
window: Optional[str] = None
|
||||||
grain_to_date: Optional[str] = None # str is really a TimeGranularity Enum
|
grain_to_date: Optional[str] = None # str is really a TimeGranularity Enum
|
||||||
metrics: Optional[List[Union[UnparsedMetricInput, str]]] = None
|
metrics: Optional[List[Union[UnparsedMetricInput, str]]] = None
|
||||||
|
conversion_type_params: Optional[UnparsedConversionTypeParams] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -1527,6 +1527,34 @@ def _process_refs(
|
|||||||
node.depends_on.add_node(target_model_id)
|
node.depends_on.add_node(target_model_id)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_metric_depends_on(
|
||||||
|
manifest: Manifest,
|
||||||
|
current_project: str,
|
||||||
|
metric: Metric,
|
||||||
|
) -> None:
|
||||||
|
"""For a given metric, set the `depends_on` property"""
|
||||||
|
|
||||||
|
assert len(metric.type_params.input_measures) > 0
|
||||||
|
for input_measure in metric.type_params.input_measures:
|
||||||
|
target_semantic_model = manifest.resolve_semantic_model_for_measure(
|
||||||
|
target_measure_name=input_measure.name,
|
||||||
|
current_project=current_project,
|
||||||
|
node_package=metric.package_name,
|
||||||
|
)
|
||||||
|
if target_semantic_model is None:
|
||||||
|
raise dbt.exceptions.ParsingError(
|
||||||
|
f"A semantic model having a measure `{input_measure.name}` does not exist but was referenced.",
|
||||||
|
node=metric,
|
||||||
|
)
|
||||||
|
if target_semantic_model.config.enabled is False:
|
||||||
|
raise dbt.exceptions.ParsingError(
|
||||||
|
f"The measure `{input_measure.name}` is referenced on disabled semantic model `{target_semantic_model.name}`.",
|
||||||
|
node=metric,
|
||||||
|
)
|
||||||
|
|
||||||
|
metric.depends_on.add_node(target_semantic_model.unique_id)
|
||||||
|
|
||||||
|
|
||||||
def _process_metric_node(
|
def _process_metric_node(
|
||||||
manifest: Manifest,
|
manifest: Manifest,
|
||||||
current_project: str,
|
current_project: str,
|
||||||
@@ -1546,24 +1574,19 @@ def _process_metric_node(
|
|||||||
metric.type_params.measure is not None
|
metric.type_params.measure is not None
|
||||||
), f"{metric} should have a measure defined, but it does not."
|
), f"{metric} should have a measure defined, but it does not."
|
||||||
metric.type_params.input_measures.append(metric.type_params.measure)
|
metric.type_params.input_measures.append(metric.type_params.measure)
|
||||||
target_semantic_model = manifest.resolve_semantic_model_for_measure(
|
_process_metric_depends_on(
|
||||||
target_measure_name=metric.type_params.measure.name,
|
manifest=manifest, current_project=current_project, metric=metric
|
||||||
current_project=current_project,
|
|
||||||
node_package=metric.package_name,
|
|
||||||
)
|
)
|
||||||
if target_semantic_model is None:
|
elif metric.type is MetricType.CONVERSION:
|
||||||
raise dbt.exceptions.ParsingError(
|
conversion_type_params = metric.type_params.conversion_type_params
|
||||||
f"A semantic model having a measure `{metric.type_params.measure.name}` does not exist but was referenced.",
|
assert (
|
||||||
node=metric,
|
conversion_type_params
|
||||||
|
), f"{metric.name} is a conversion metric and must have conversion_type_params defined."
|
||||||
|
metric.type_params.input_measures.append(conversion_type_params.base_measure)
|
||||||
|
metric.type_params.input_measures.append(conversion_type_params.conversion_measure)
|
||||||
|
_process_metric_depends_on(
|
||||||
|
manifest=manifest, current_project=current_project, metric=metric
|
||||||
)
|
)
|
||||||
if target_semantic_model.config.enabled is False:
|
|
||||||
raise dbt.exceptions.ParsingError(
|
|
||||||
f"The measure `{metric.type_params.measure.name}` is referenced on disabled semantic model `{target_semantic_model.name}`.",
|
|
||||||
node=metric,
|
|
||||||
)
|
|
||||||
|
|
||||||
metric.depends_on.add_node(target_semantic_model.unique_id)
|
|
||||||
|
|
||||||
elif metric.type is MetricType.DERIVED or metric.type is MetricType.RATIO:
|
elif metric.type is MetricType.DERIVED or metric.type is MetricType.RATIO:
|
||||||
input_metrics = metric.input_metrics
|
input_metrics = metric.input_metrics
|
||||||
if metric.type is MetricType.RATIO:
|
if metric.type is MetricType.RATIO:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from dbt.contracts.graph.unparsed import (
|
|||||||
UnparsedQueryParams,
|
UnparsedQueryParams,
|
||||||
UnparsedSavedQuery,
|
UnparsedSavedQuery,
|
||||||
UnparsedSemanticModel,
|
UnparsedSemanticModel,
|
||||||
|
UnparsedConversionTypeParams,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.model_config import SavedQueryConfig
|
from dbt.contracts.graph.model_config import SavedQueryConfig
|
||||||
from dbt.contracts.graph.nodes import (
|
from dbt.contracts.graph.nodes import (
|
||||||
@@ -29,6 +30,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
MetricTypeParams,
|
MetricTypeParams,
|
||||||
SemanticModel,
|
SemanticModel,
|
||||||
SavedQuery,
|
SavedQuery,
|
||||||
|
ConversionTypeParams,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.saved_queries import Export, ExportConfig, QueryParams
|
from dbt.contracts.graph.saved_queries import Export, ExportConfig, QueryParams
|
||||||
from dbt.contracts.graph.semantic_layer_common import WhereFilter, WhereFilterIntersection
|
from dbt.contracts.graph.semantic_layer_common import WhereFilter, WhereFilterIntersection
|
||||||
@@ -52,6 +54,7 @@ from dbt.clients.jinja import get_rendered
|
|||||||
from dbt.dataclass_schema import ValidationError
|
from dbt.dataclass_schema import ValidationError
|
||||||
from dbt_semantic_interfaces.type_enums import (
|
from dbt_semantic_interfaces.type_enums import (
|
||||||
AggregationType,
|
AggregationType,
|
||||||
|
ConversionCalculationType,
|
||||||
DimensionType,
|
DimensionType,
|
||||||
EntityType,
|
EntityType,
|
||||||
MetricType,
|
MetricType,
|
||||||
@@ -226,7 +229,7 @@ class MetricParser(YamlReader):
|
|||||||
self.yaml.path,
|
self.yaml.path,
|
||||||
"window",
|
"window",
|
||||||
{"window": unparsed_window},
|
{"window": unparsed_window},
|
||||||
f"Invalid window ({unparsed_window}) in cumulative metric. Should be of the form `<count> <granularity>`, "
|
f"Invalid window ({unparsed_window}) in cumulative/conversion metric. Should be of the form `<count> <granularity>`, "
|
||||||
"e.g., `28 days`",
|
"e.g., `28 days`",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -240,7 +243,7 @@ class MetricParser(YamlReader):
|
|||||||
self.yaml.path,
|
self.yaml.path,
|
||||||
"window",
|
"window",
|
||||||
{"window": unparsed_window},
|
{"window": unparsed_window},
|
||||||
f"Invalid time granularity {granularity} in cumulative metric window string: ({unparsed_window})",
|
f"Invalid time granularity {granularity} in cumulative/conversion metric window string: ({unparsed_window})",
|
||||||
)
|
)
|
||||||
|
|
||||||
count = parts[0]
|
count = parts[0]
|
||||||
@@ -249,7 +252,7 @@ class MetricParser(YamlReader):
|
|||||||
self.yaml.path,
|
self.yaml.path,
|
||||||
"window",
|
"window",
|
||||||
{"window": unparsed_window},
|
{"window": unparsed_window},
|
||||||
f"Invalid count ({count}) in cumulative metric window string: ({unparsed_window})",
|
f"Invalid count ({count}) in cumulative/conversion metric window string: ({unparsed_window})",
|
||||||
)
|
)
|
||||||
|
|
||||||
return MetricTimeWindow(
|
return MetricTimeWindow(
|
||||||
@@ -295,6 +298,20 @@ class MetricParser(YamlReader):
|
|||||||
|
|
||||||
return metric_inputs
|
return metric_inputs
|
||||||
|
|
||||||
|
def _get_optional_conversion_type_params(
|
||||||
|
self, unparsed: Optional[UnparsedConversionTypeParams]
|
||||||
|
) -> Optional[ConversionTypeParams]:
|
||||||
|
if unparsed is None:
|
||||||
|
return None
|
||||||
|
return ConversionTypeParams(
|
||||||
|
base_measure=self._get_input_measure(unparsed.base_measure),
|
||||||
|
conversion_measure=self._get_input_measure(unparsed.conversion_measure),
|
||||||
|
entity=unparsed.entity,
|
||||||
|
calculation=ConversionCalculationType(unparsed.calculation),
|
||||||
|
window=self._get_time_window(unparsed.window),
|
||||||
|
constant_properties=unparsed.constant_properties,
|
||||||
|
)
|
||||||
|
|
||||||
def _get_metric_type_params(self, type_params: UnparsedMetricTypeParams) -> MetricTypeParams:
|
def _get_metric_type_params(self, type_params: UnparsedMetricTypeParams) -> MetricTypeParams:
|
||||||
grain_to_date: Optional[TimeGranularity] = None
|
grain_to_date: Optional[TimeGranularity] = None
|
||||||
if type_params.grain_to_date is not None:
|
if type_params.grain_to_date is not None:
|
||||||
@@ -308,6 +325,9 @@ class MetricParser(YamlReader):
|
|||||||
window=self._get_time_window(type_params.window),
|
window=self._get_time_window(type_params.window),
|
||||||
grain_to_date=grain_to_date,
|
grain_to_date=grain_to_date,
|
||||||
metrics=self._get_metric_inputs(type_params.metrics),
|
metrics=self._get_metric_inputs(type_params.metrics),
|
||||||
|
conversion_type_params=self._get_optional_conversion_type_params(
|
||||||
|
type_params.conversion_type_params
|
||||||
|
)
|
||||||
# input measures are calculated via metric processing post parsing
|
# input measures are calculated via metric processing post parsing
|
||||||
# input_measures=?,
|
# input_measures=?,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ setup(
|
|||||||
# These are major-version-0 packages also maintained by dbt-labs. Accept patches.
|
# These are major-version-0 packages also maintained by dbt-labs. Accept patches.
|
||||||
"dbt-extractor~=0.5.0",
|
"dbt-extractor~=0.5.0",
|
||||||
"minimal-snowplow-tracker~=0.0.2",
|
"minimal-snowplow-tracker~=0.0.2",
|
||||||
"dbt-semantic-interfaces~=0.4.0",
|
"dbt-semantic-interfaces~=0.5.0a2",
|
||||||
# ----
|
# ----
|
||||||
# Expect compatibility with all new versions of these packages, so lower bounds only.
|
# Expect compatibility with all new versions of these packages, so lower bounds only.
|
||||||
"jsonschema>=3.0",
|
"jsonschema>=3.0",
|
||||||
|
|||||||
@@ -7843,7 +7843,8 @@
|
|||||||
"simple",
|
"simple",
|
||||||
"ratio",
|
"ratio",
|
||||||
"cumulative",
|
"cumulative",
|
||||||
"derived"
|
"derived",
|
||||||
|
"conversion"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type_params": {
|
"type_params": {
|
||||||
@@ -8410,6 +8411,241 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"conversion_type_params": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "ConversionTypeParams",
|
||||||
|
"properties": {
|
||||||
|
"base_measure": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricInputMeasure",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilterIntersection",
|
||||||
|
"properties": {
|
||||||
|
"where_filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilter",
|
||||||
|
"properties": {
|
||||||
|
"where_sql_template": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_sql_template"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_filters"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"join_to_timespine": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"fill_nulls_with": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"conversion_measure": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricInputMeasure",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilterIntersection",
|
||||||
|
"properties": {
|
||||||
|
"where_filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilter",
|
||||||
|
"properties": {
|
||||||
|
"where_sql_template": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_sql_template"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_filters"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"join_to_timespine": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"fill_nulls_with": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entity": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"calculation": {
|
||||||
|
"enum": [
|
||||||
|
"conversions",
|
||||||
|
"conversion_rate"
|
||||||
|
],
|
||||||
|
"default": "conversion_rate"
|
||||||
|
},
|
||||||
|
"window": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricTimeWindow",
|
||||||
|
"properties": {
|
||||||
|
"count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"granularity": {
|
||||||
|
"enum": [
|
||||||
|
"day",
|
||||||
|
"week",
|
||||||
|
"month",
|
||||||
|
"quarter",
|
||||||
|
"year"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"count",
|
||||||
|
"granularity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"constant_properties": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "ConstantPropertyInput",
|
||||||
|
"properties": {
|
||||||
|
"base_property": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"conversion_property": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"base_property",
|
||||||
|
"conversion_property"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"base_measure",
|
||||||
|
"conversion_measure",
|
||||||
|
"entity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -16264,7 +16500,8 @@
|
|||||||
"simple",
|
"simple",
|
||||||
"ratio",
|
"ratio",
|
||||||
"cumulative",
|
"cumulative",
|
||||||
"derived"
|
"derived",
|
||||||
|
"conversion"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type_params": {
|
"type_params": {
|
||||||
@@ -16831,6 +17068,241 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"conversion_type_params": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "ConversionTypeParams",
|
||||||
|
"properties": {
|
||||||
|
"base_measure": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricInputMeasure",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilterIntersection",
|
||||||
|
"properties": {
|
||||||
|
"where_filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilter",
|
||||||
|
"properties": {
|
||||||
|
"where_sql_template": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_sql_template"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_filters"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"join_to_timespine": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"fill_nulls_with": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"conversion_measure": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricInputMeasure",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"filter": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilterIntersection",
|
||||||
|
"properties": {
|
||||||
|
"where_filters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "WhereFilter",
|
||||||
|
"properties": {
|
||||||
|
"where_sql_template": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_sql_template"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"where_filters"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"join_to_timespine": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"fill_nulls_with": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entity": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"calculation": {
|
||||||
|
"enum": [
|
||||||
|
"conversions",
|
||||||
|
"conversion_rate"
|
||||||
|
],
|
||||||
|
"default": "conversion_rate"
|
||||||
|
},
|
||||||
|
"window": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"title": "MetricTimeWindow",
|
||||||
|
"properties": {
|
||||||
|
"count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"granularity": {
|
||||||
|
"enum": [
|
||||||
|
"day",
|
||||||
|
"week",
|
||||||
|
"month",
|
||||||
|
"quarter",
|
||||||
|
"year"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"count",
|
||||||
|
"granularity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"constant_properties": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "ConstantPropertyInput",
|
||||||
|
"properties": {
|
||||||
|
"base_property": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"conversion_property": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"base_property",
|
||||||
|
"conversion_property"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"base_measure",
|
||||||
|
"conversion_measure",
|
||||||
|
"entity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"metadata": {"dbt_schema_version": "https://schemas.getdbt.com/dbt/run-results/v6.json", "dbt_version": "1.8.0a1", "generated_at": "2023-12-01T00:27:31.475276Z", "invocation_id": "6dbe790d-e31a-45d3-bf5c-b67232e7e45c", "env": {}}, "results": [{"status": "success", "timing": [{"name": "compile", "started_at": "2023-12-01T00:27:31.399416Z", "completed_at": "2023-12-01T00:27:31.406369Z"}, {"name": "execute", "started_at": "2023-12-01T00:27:31.407149Z", "completed_at": "2023-12-01T00:27:31.458669Z"}], "thread_id": "Thread-8", "execution_time": 0.0613861083984375, "adapter_response": {"_message": "CREATE VIEW", "code": "CREATE VIEW", "rows_affected": -1}, "message": "CREATE VIEW", "failures": null, "unique_id": "model.test.metricflow_time_spine", "compiled": true, "compiled_code": "SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day", "relation_name": "\"dbt\".\"test17013904484151129162_test_previous_version_state\".\"metricflow_time_spine\""}, {"status": "success", "timing": [{"name": "compile", "started_at": "2023-12-01T00:27:31.401527Z", "completed_at": "2023-12-01T00:27:31.402989Z"}, {"name": "execute", "started_at": "2023-12-01T00:27:31.403533Z", "completed_at": "2023-12-01T00:27:31.460610Z"}], "thread_id": "Thread-9", "execution_time": 0.0629112720489502, "adapter_response": {"_message": "CREATE VIEW", "code": "CREATE VIEW", "rows_affected": -1}, "message": "CREATE VIEW", "failures": null, "unique_id": "model.test.my_model", "compiled": true, "compiled_code": "select 1 as id", "relation_name": "\"dbt\".\"test17013904484151129162_test_previous_version_state\".\"my_model\""}], "elapsed_time": 0.5424928665161133, "args": {"log_format_file": "debug", "profiles_dir": "/private/var/folders/79/5290gpvn3lx5jdryk4844rm80000gn/T/pytest-of-quigleymalcolm/pytest-449/profile0", "defer": false, "favor_state": false, "populate_cache": true, "partial_parse": true, "select": [], "show_resource_report": false, "version_check": true, "strict_mode": false, "introspect": true, "project_dir": "/private/var/folders/79/5290gpvn3lx5jdryk4844rm80000gn/T/pytest-of-quigleymalcolm/pytest-449/project0", "indirect_selection": "eager", "vars": {}, "log_level_file": "debug", "log_level": "info", "printer_width": 80, "cache_selected_only": false, "which": "run", "log_path": "/Users/quigleymalcolm/Developer/dbt-labs/dbt-core/logs/test17013904484151129162", "write_json": true, "log_file_max_bytes": 10485760, "macro_debugging": true, "static_parser": true, "enable_legacy_logger": false, "warn_error_options": {"include": [], "exclude": []}, "invocation_command": "dbt tests/functional/artifacts/test_previous_version_state.py", "exclude": [], "use_colors": true, "use_colors_file": true, "quiet": false, "print": true, "send_anonymous_usage_stats": false, "partial_parse_file_diff": true, "log_format": "default"}}
|
{"metadata": {"dbt_schema_version": "https://schemas.getdbt.com/dbt/run-results/v6.json", "dbt_version": "1.8.0a1", "generated_at": "2023-12-06T18:53:19.641690Z", "invocation_id": "ad4ef714-e6c6-425e-b7c8-c1c4369df4ea", "env": {}}, "results": [{"status": "success", "timing": [{"name": "compile", "started_at": "2023-12-06T18:53:19.554953Z", "completed_at": "2023-12-06T18:53:19.559711Z"}, {"name": "execute", "started_at": "2023-12-06T18:53:19.564874Z", "completed_at": "2023-12-06T18:53:19.620151Z"}], "thread_id": "Thread-8", "execution_time": 0.06995701789855957, "adapter_response": {"_message": "CREATE VIEW", "code": "CREATE VIEW", "rows_affected": -1}, "message": "CREATE VIEW", "failures": null, "unique_id": "model.test.metricflow_time_spine", "compiled": true, "compiled_code": "SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day", "relation_name": "\"dbt\".\"test17018887966812726006_test_previous_version_state\".\"metricflow_time_spine\""}, {"status": "success", "timing": [{"name": "compile", "started_at": "2023-12-06T18:53:19.557019Z", "completed_at": "2023-12-06T18:53:19.559247Z"}, {"name": "execute", "started_at": "2023-12-06T18:53:19.561000Z", "completed_at": "2023-12-06T18:53:19.622080Z"}], "thread_id": "Thread-9", "execution_time": 0.07100677490234375, "adapter_response": {"_message": "CREATE VIEW", "code": "CREATE VIEW", "rows_affected": -1}, "message": "CREATE VIEW", "failures": null, "unique_id": "model.test.my_model", "compiled": true, "compiled_code": "select 1 as id", "relation_name": "\"dbt\".\"test17018887966812726006_test_previous_version_state\".\"my_model\""}], "elapsed_time": 0.13903093338012695, "args": {"print": true, "log_level_file": "debug", "quiet": false, "warn_error_options": {"include": [], "exclude": []}, "write_json": true, "invocation_command": "dbt --cov=core --cov-append --cov-report=xml tests/functional/artifacts/test_previous_version_state.py", "log_level": "info", "select": [], "project_dir": "/private/var/folders/67/r0f0jlj54h95zl3fhmb217jh0000gp/T/pytest-of-william/pytest-68/project0", "static_parser": true, "log_file_max_bytes": 10485760, "empty": false, "introspect": true, "log_format_file": "debug", "vars": {}, "strict_mode": false, "indirect_selection": "eager", "show_resource_report": false, "favor_state": false, "version_check": true, "cache_selected_only": false, "enable_legacy_logger": false, "partial_parse": true, "profiles_dir": "/private/var/folders/67/r0f0jlj54h95zl3fhmb217jh0000gp/T/pytest-of-william/pytest-68/profile0", "defer": false, "printer_width": 80, "send_anonymous_usage_stats": false, "use_colors": true, "log_path": "/Users/william/git/dbt-core/logs/test17018887966812726006", "partial_parse_file_diff": true, "populate_cache": true, "macro_debugging": false, "use_colors_file": true, "log_format": "default", "which": "run", "exclude": []}}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -443,7 +443,7 @@ class TestPreviousVersionState:
|
|||||||
current_run_results_schema_version == self.CURRENT_EXPECTED_RUN_RESULTS_VERSION
|
current_run_results_schema_version == self.CURRENT_EXPECTED_RUN_RESULTS_VERSION
|
||||||
), "Sounds like you've bumped the run_results version and need to update this test!"
|
), "Sounds like you've bumped the run_results version and need to update this test!"
|
||||||
# If we need a newly generated run_results, uncomment the following line and commit the result
|
# If we need a newly generated run_results, uncomment the following line and commit the result
|
||||||
self.generate_latest_run_results(project, current_run_results_schema_version)
|
# self.generate_latest_run_results(project, current_run_results_schema_version)
|
||||||
self.compare_previous_results(project, current_run_results_schema_version, True, 0)
|
self.compare_previous_results(project, current_run_results_schema_version, True, 0)
|
||||||
|
|
||||||
def test_backwards_compatible_run_results_versions(self, project):
|
def test_backwards_compatible_run_results_versions(self, project):
|
||||||
|
|||||||
@@ -626,3 +626,41 @@ metrics:
|
|||||||
meta:
|
meta:
|
||||||
my_meta: 'testing'
|
my_meta: 'testing'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
conversion_semantic_model_purchasing_yml = """
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
semantic_models:
|
||||||
|
- name: semantic_purchasing
|
||||||
|
model: ref('purchasing')
|
||||||
|
measures:
|
||||||
|
- name: num_orders
|
||||||
|
agg: COUNT
|
||||||
|
expr: purchased_at
|
||||||
|
- name: num_visits
|
||||||
|
agg: SUM
|
||||||
|
expr: 1
|
||||||
|
dimensions:
|
||||||
|
- name: purchased_at
|
||||||
|
type: TIME
|
||||||
|
entities:
|
||||||
|
- name: purchase
|
||||||
|
type: primary
|
||||||
|
expr: '1'
|
||||||
|
defaults:
|
||||||
|
agg_time_dimension: purchased_at
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_metric_yml = """
|
||||||
|
version: 2
|
||||||
|
metrics:
|
||||||
|
- name: converted_orders_over_visits
|
||||||
|
label: Number of orders converted from visits
|
||||||
|
type: conversion
|
||||||
|
type_params:
|
||||||
|
conversion_type_params:
|
||||||
|
base_measure: num_visits
|
||||||
|
conversion_measure: num_orders
|
||||||
|
entity: purchase
|
||||||
|
"""
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from dbt.tests.util import run_dbt, get_manifest
|
|||||||
|
|
||||||
|
|
||||||
from tests.functional.metrics.fixtures import (
|
from tests.functional.metrics.fixtures import (
|
||||||
|
conversion_semantic_model_purchasing_yml,
|
||||||
|
conversion_metric_yml,
|
||||||
mock_purchase_data_csv,
|
mock_purchase_data_csv,
|
||||||
models_people_sql,
|
models_people_sql,
|
||||||
models_people_metrics_yml,
|
models_people_metrics_yml,
|
||||||
@@ -339,3 +341,61 @@ class TestInvalidTimestampWindowMetrics:
|
|||||||
# initial run
|
# initial run
|
||||||
with pytest.raises(ParsingError):
|
with pytest.raises(ParsingError):
|
||||||
run_dbt(["run"])
|
run_dbt(["run"])
|
||||||
|
|
||||||
|
|
||||||
|
class TestConversionMetric:
|
||||||
|
@pytest.fixture(scope="class")
|
||||||
|
def models(self):
|
||||||
|
return {
|
||||||
|
"purchasing.sql": purchasing_model_sql,
|
||||||
|
"metricflow_time_spine.sql": metricflow_time_spine_sql,
|
||||||
|
"semantic_models.yml": conversion_semantic_model_purchasing_yml,
|
||||||
|
"conversion_metric.yml": conversion_metric_yml,
|
||||||
|
}
|
||||||
|
|
||||||
|
@pytest.fixture(scope="class")
|
||||||
|
def seeds(self):
|
||||||
|
return {
|
||||||
|
"mock_purchase_data.csv": mock_purchase_data_csv,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_conversion_metric(
|
||||||
|
self,
|
||||||
|
project,
|
||||||
|
):
|
||||||
|
# initial parse
|
||||||
|
runner = dbtRunner()
|
||||||
|
result = runner.invoke(["parse"])
|
||||||
|
assert result.success
|
||||||
|
assert isinstance(result.result, Manifest)
|
||||||
|
|
||||||
|
# make sure the metric is in the manifest
|
||||||
|
manifest = get_manifest(project.project_root)
|
||||||
|
metric_ids = list(manifest.metrics.keys())
|
||||||
|
expected_metric_ids = [
|
||||||
|
"metric.test.converted_orders_over_visits",
|
||||||
|
]
|
||||||
|
assert metric_ids == expected_metric_ids
|
||||||
|
assert manifest.metrics[
|
||||||
|
"metric.test.converted_orders_over_visits"
|
||||||
|
].type_params.conversion_type_params
|
||||||
|
assert (
|
||||||
|
len(
|
||||||
|
manifest.metrics[
|
||||||
|
"metric.test.converted_orders_over_visits"
|
||||||
|
].type_params.input_measures
|
||||||
|
)
|
||||||
|
== 2
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
manifest.metrics[
|
||||||
|
"metric.test.converted_orders_over_visits"
|
||||||
|
].type_params.conversion_type_params.window
|
||||||
|
is None
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
manifest.metrics[
|
||||||
|
"metric.test.converted_orders_over_visits"
|
||||||
|
].type_params.conversion_type_params.entity
|
||||||
|
== "purchase"
|
||||||
|
)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import pytest
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
from dbt.contracts.graph.nodes import (
|
from dbt.contracts.graph.nodes import (
|
||||||
|
ConstantPropertyInput,
|
||||||
|
ConversionTypeParams,
|
||||||
Metric,
|
Metric,
|
||||||
MetricInput,
|
MetricInput,
|
||||||
MetricInputMeasure,
|
MetricInputMeasure,
|
||||||
@@ -233,6 +235,21 @@ def complex_metric_input_measure(where_filter) -> MetricInputMeasure:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def conversion_type_params(
|
||||||
|
simple_metric_input_measure, metric_time_window
|
||||||
|
) -> ConversionTypeParams:
|
||||||
|
return ConversionTypeParams(
|
||||||
|
base_measure=simple_metric_input_measure,
|
||||||
|
conversion_measure=simple_metric_input_measure,
|
||||||
|
entity="entity",
|
||||||
|
window=metric_time_window,
|
||||||
|
constant_properties=[
|
||||||
|
ConstantPropertyInput(base_property="base", conversion_property="conversion")
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def complex_metric_type_params(
|
def complex_metric_type_params(
|
||||||
metric_time_window, simple_metric_input, simple_metric_input_measure
|
metric_time_window, simple_metric_input, simple_metric_input_measure
|
||||||
@@ -245,6 +262,7 @@ def complex_metric_type_params(
|
|||||||
window=metric_time_window,
|
window=metric_time_window,
|
||||||
grain_to_date=TimeGranularity.DAY,
|
grain_to_date=TimeGranularity.DAY,
|
||||||
metrics=[simple_metric_input],
|
metrics=[simple_metric_input],
|
||||||
|
conversion_type_params=conversion_type_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user