Skip to content

Commit 8aef495

Browse files
Clean up Pydantic rules list. (#434)
Towards #387 ### Description We have added several new transformations to support turning measures into metrics, but not all of them made it to our standard rules file. Our rules file was also very disorganized, and it was hard to tell how things were grouped together or why things were ordered in specific ways. This is a first pass at all of those issues. I am hoping to be able to use this in metricflow to organize some of the transformation rules more easily, too, so if I run into problems, there may be further updates to this file. ### 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 - [x] 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)
1 parent 336f22d commit 8aef495

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Under the Hood
2+
body: Reorganize and clean up transformation rules.
3+
time: 2025-09-29T16:31:46.425698-07:00
4+
custom:
5+
Author: theyostalservice
6+
Issue: "387"

dbt_semantic_interfaces/transformations/pydantic_rule_set.py

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@
1010
from dbt_semantic_interfaces.transformations.add_input_metric_measures import (
1111
AddInputMetricMeasuresRule,
1212
)
13+
from dbt_semantic_interfaces.transformations.boolean_aggregations import (
14+
BooleanAggregationRule,
15+
)
1316
from dbt_semantic_interfaces.transformations.boolean_measure import (
1417
BooleanMeasureAggregationRule,
1518
)
16-
from dbt_semantic_interfaces.transformations.convert_count import ConvertCountToSumRule
19+
from dbt_semantic_interfaces.transformations.convert_count import (
20+
ConvertCountMetricToSumRule,
21+
ConvertCountToSumRule,
22+
)
1723
from dbt_semantic_interfaces.transformations.convert_median import (
24+
ConvertMedianMetricToPercentile,
1825
ConvertMedianToPercentileRule,
1926
)
2027
from dbt_semantic_interfaces.transformations.cumulative_type_params import (
@@ -51,24 +58,66 @@ def _implements_protocol(self) -> SemanticManifestTransformRuleSet[PydanticSeman
5158
return self
5259

5360
@property
54-
def primary_rules(self) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa:
55-
return (LowerCaseNamesRule(),)
56-
57-
@property
58-
def secondary_rules(self) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa: D
61+
def legacy_measure_update_rules(
62+
self,
63+
) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa: D
64+
"""Legacy rules - Primarily editing legacy measures."""
5965
return (
60-
CreateProxyMeasureRule(),
6166
BooleanMeasureAggregationRule(),
6267
ConvertCountToSumRule(),
6368
ConvertMedianToPercentileRule(),
69+
)
70+
71+
@property
72+
def convert_legacy_measures_to_metrics_rules(
73+
self,
74+
) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa: D
75+
"""Rules that create or update metrics to replace the use of legacy measures.
76+
77+
Should run after all measures are processed and fixed, but before polishing
78+
all metrics (because the metrics need to be created here to be polished later).
79+
"""
80+
return (
81+
# CreateProxyMeasureRule should always run FIRST in this sequence.
82+
CreateProxyMeasureRule(), # FIRST, I SAY!
83+
# This populates "input_measures" for metric fields.
84+
# This does NOT add new metrics or depend on most newly-added metrics, but it must
85+
# run after CreateProxyMeasureRule() to ensure we have all the metrics we will need.
6486
AddInputMetricMeasuresRule(),
65-
SetCumulativeTypeParamsRule(),
66-
RemovePluralFromWindowGranularityRule(),
67-
# The following steps upgrade from old-style measure-including models to new-style metric-only models
6887
FlattenSimpleMetricsWithMeasureInputsRule(),
6988
ReplaceInputMeasuresWithSimpleMetricsTransformationRule(),
7089
)
7190

91+
@property
92+
def general_metric_update_rules(
93+
self,
94+
) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa: D
95+
"""These rules apply once all metrics exist; they apply universally to any metric that meet their criteria.
96+
97+
These should be run AFTER all metrics exist.
98+
"""
99+
return (
100+
SetCumulativeTypeParamsRule(),
101+
RemovePluralFromWindowGranularityRule(),
102+
ConvertMedianMetricToPercentile(),
103+
ConvertCountMetricToSumRule(),
104+
BooleanAggregationRule(),
105+
)
106+
107+
@property
108+
def primary_rules(self) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa:
109+
return (LowerCaseNamesRule(),)
110+
111+
@property
112+
def secondary_rules(self) -> Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]: # noqa: D
113+
"""Secondary rules - Primarily editing, copying, or adapting measures and metrics."""
114+
# Order matters here!
115+
return [
116+
*self.legacy_measure_update_rules,
117+
*self.convert_legacy_measures_to_metrics_rules,
118+
*self.general_metric_update_rules,
119+
]
120+
72121
@property
73122
def all_rules(self) -> Sequence[Sequence[SemanticManifestTransformRule[PydanticSemanticManifest]]]: # noqa: D
74123
return self.primary_rules, self.secondary_rules

0 commit comments

Comments
 (0)