From 2e4004abe623333ffbeee2c26f39a00c7c9ec5fc Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Fri, 12 Jul 2024 12:45:51 -0700 Subject: [PATCH] Remove `SetMetricTimeGranularityRule` (#311) ### Description Per discussion, removing this rule in favor of putting this logic in the group by resolution DAG instead. ### Checklist - [x] I have read [the contributing guide](https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/CONTRIBUTING.md) and understand what's expected of me - [x] I have signed the [CLA](https://docs.getdbt.com/docs/contributor-license-agreements) - [x] This PR includes tests, or tests are not required/relevant for this PR - [ ] I have run `changie new` to [create a changelog entry](https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/CONTRIBUTING.md#adding-a-changelog-entry) --- .../metric_time_granularity.py | 75 ------------------- .../transformations/pydantic_rule_set.py | 4 - .../test_configurable_transform_rules.py | 35 --------- 3 files changed, 114 deletions(-) delete mode 100644 dbt_semantic_interfaces/transformations/metric_time_granularity.py diff --git a/dbt_semantic_interfaces/transformations/metric_time_granularity.py b/dbt_semantic_interfaces/transformations/metric_time_granularity.py deleted file mode 100644 index 1a0d7a27..00000000 --- a/dbt_semantic_interfaces/transformations/metric_time_granularity.py +++ /dev/null @@ -1,75 +0,0 @@ -import logging -from typing import Dict, Set, Tuple - -from typing_extensions import override - -from dbt_semantic_interfaces.implementations.metric import PydanticMetric -from dbt_semantic_interfaces.implementations.semantic_manifest import ( - PydanticSemanticManifest, -) -from dbt_semantic_interfaces.protocols import ProtocolHint -from dbt_semantic_interfaces.protocols.metric import Metric -from dbt_semantic_interfaces.references import ( - DimensionReference, - MetricReference, - SemanticModelReference, - TimeDimensionReference, -) -from dbt_semantic_interfaces.transformations.transform_rule import ( - SemanticManifestTransformRule, -) -from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity - -logger = logging.getLogger(__name__) - - -class SetMetricTimeGranularityRule(ProtocolHint[SemanticManifestTransformRule[PydanticSemanticManifest]]): - """If time_granularity is not set for a metric, set it to DAY if available, else the smallest available grain.""" - - @override - def _implements_protocol(self) -> SemanticManifestTransformRule[PydanticSemanticManifest]: # noqa: D - return self - - @staticmethod - def transform_model(semantic_manifest: PydanticSemanticManifest) -> PydanticSemanticManifest: - """For each metric, set time_granularity to DAY or smallest granularity supported by all agg_time_dims.""" - for metric in semantic_manifest.metrics: - if metric.time_granularity: - continue - - time_granularity = TimeGranularity.DAY - seen_agg_time_dimensions: Set[Tuple[SemanticModelReference, TimeDimensionReference]] = set() - - metric_index: Dict[MetricReference, Metric] = { - MetricReference(metric.name): metric for metric in semantic_manifest.metrics - } - - for semantic_model in semantic_manifest.semantic_models: - for measure_ref in set( - PydanticMetric.all_input_measures_for_metric(metric=metric, metric_index=metric_index) - ).intersection(semantic_model.measure_references): - try: - agg_time_dimension_ref = semantic_model.checked_agg_time_dimension_for_measure(measure_ref) - except AssertionError: - # This indicates the agg_time_dimension is misconfigured, which will fail elsewhere. - # Do nothing here to avoid disrupting the validation process. - logger.warning( - f"Agg time dimension '{agg_time_dimension_ref.element_name}' not found in model." - "This should raise a validation error elsewhere." - ) - continue - # Time dims might have the same names across semantic models, so check model/name combo. - semantic_model_with_agg_time_dimension = (semantic_model.reference, agg_time_dimension_ref) - if semantic_model_with_agg_time_dimension in seen_agg_time_dimensions: - continue - seen_agg_time_dimensions.add(semantic_model_with_agg_time_dimension) - dimension = semantic_model.get_dimension(DimensionReference(agg_time_dimension_ref.element_name)) - if ( - dimension.type_params - and dimension.type_params.time_granularity.to_int() > time_granularity.to_int() - ): - time_granularity = dimension.type_params.time_granularity - - metric.time_granularity = time_granularity - - return semantic_manifest diff --git a/dbt_semantic_interfaces/transformations/pydantic_rule_set.py b/dbt_semantic_interfaces/transformations/pydantic_rule_set.py index 1ad5ea1f..7c2f4568 100644 --- a/dbt_semantic_interfaces/transformations/pydantic_rule_set.py +++ b/dbt_semantic_interfaces/transformations/pydantic_rule_set.py @@ -20,9 +20,6 @@ from dbt_semantic_interfaces.transformations.cumulative_type_params import ( SetCumulativeTypeParamsRule, ) -from dbt_semantic_interfaces.transformations.metric_time_granularity import ( - SetMetricTimeGranularityRule, -) from dbt_semantic_interfaces.transformations.names import LowerCaseNamesRule from dbt_semantic_interfaces.transformations.proxy_measure import CreateProxyMeasureRule from dbt_semantic_interfaces.transformations.rule_set import ( @@ -57,7 +54,6 @@ def secondary_rules(self) -> Sequence[SemanticManifestTransformRule[PydanticSema ConvertMedianToPercentileRule(), AddInputMetricMeasuresRule(), SetCumulativeTypeParamsRule(), - SetMetricTimeGranularityRule(), ) @property diff --git a/tests/transformations/test_configurable_transform_rules.py b/tests/transformations/test_configurable_transform_rules.py index 591581d5..573d0d71 100644 --- a/tests/transformations/test_configurable_transform_rules.py +++ b/tests/transformations/test_configurable_transform_rules.py @@ -1,18 +1,12 @@ -from typing import Dict - from dbt_semantic_interfaces.implementations.semantic_manifest import ( PydanticSemanticManifest, ) -from dbt_semantic_interfaces.transformations.metric_time_granularity import ( - SetMetricTimeGranularityRule, -) from dbt_semantic_interfaces.transformations.semantic_manifest_transformer import ( PydanticSemanticManifestTransformer, ) from dbt_semantic_interfaces.transformations.transform_rule import ( SemanticManifestTransformRule, ) -from dbt_semantic_interfaces.type_enums import TimeGranularity class SliceNamesRule(SemanticManifestTransformRule): @@ -38,32 +32,3 @@ def test_can_configure_model_transform_rules( # noqa: D rules = [SliceNamesRule()] transformed_model = PydanticSemanticManifestTransformer.transform(pre_model, ordered_rule_sequences=(rules,)) assert all(len(x.name) == 3 for x in transformed_model.semantic_models) - - -def test_set_time_granularity_rule( # noqa: D - simple_semantic_manifest__with_primary_transforms: PydanticSemanticManifest, -) -> None: - pre_model = simple_semantic_manifest__with_primary_transforms - - metric_exists_without_time_granularity = False - configured_default_granularities: Dict[str, TimeGranularity] = {} - for metric in pre_model.metrics: - if metric.time_granularity: - configured_default_granularities[metric.name] = metric.time_granularity - metric_exists_without_time_granularity = True - - assert ( - pre_model.metrics and metric_exists_without_time_granularity - ), "If there are no metrics without a configured time_granularity, this tests nothing." - - rules = [SetMetricTimeGranularityRule()] - transformed_model = PydanticSemanticManifestTransformer.transform(pre_model, ordered_rule_sequences=(rules,)) - - for metric in transformed_model.metrics: - assert metric.time_granularity, f"No time_granularity set in transformation for metric '{metric.name}'" - if metric.name in configured_default_granularities: - assert ( - metric.time_granularity == configured_default_granularities[metric.name] - ), f"Time granularity was unexpected changed during transformation for metric '{metric.name}" - if metric.name == "monthly_times_yearly_bookings": - assert metric.time_granularity == TimeGranularity.YEAR